ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From onechipore...@apache.org
Subject [1/5] ambari git commit: AMBARI-14297. Apply common tests for Em.computed macros (onechiporenko)
Date Thu, 10 Dec 2015 14:14:12 GMT
Repository: ambari
Updated Branches:
  refs/heads/trunk df4bbdd85 -> 8750537a3


http://git-wip-us.apache.org/repos/asf/ambari/blob/43306594/ambari-web/test/views/main/dashboard/widgets/text_widget_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/dashboard/widgets/text_widget_test.js b/ambari-web/test/views/main/dashboard/widgets/text_widget_test.js
index b598f6b..1f95076 100644
--- a/ambari-web/test/views/main/dashboard/widgets/text_widget_test.js
+++ b/ambari-web/test/views/main/dashboard/widgets/text_widget_test.js
@@ -21,6 +21,10 @@ var App = require('app');
 require('views/main/dashboard/widget');
 require('views/main/dashboard/widgets/text_widget');
 
+function getView() {
+  return App.TextDashboardWidgetView.create({thresh1:40, thresh2:70});
+}
+
 describe('App.TextDashboardWidgetView', function() {
 
   var tests = [
@@ -81,4 +85,8 @@ describe('App.TextDashboardWidgetView', function() {
     });
   });
 
+  App.TestAliases.testAsComputedGtProperties(getView(), 'isGreen', 'data', 'thresh2');
+
+  App.TestAliases.testAsComputedLteProperties(getView(), 'isRed', 'data', 'thresh1');
+
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/43306594/ambari-web/test/views/main/host/details/host_component_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/host/details/host_component_view_test.js b/ambari-web/test/views/main/host/details/host_component_view_test.js
index c1ad6aa..e8366bd 100644
--- a/ambari-web/test/views/main/host/details/host_component_view_test.js
+++ b/ambari-web/test/views/main/host/details/host_component_view_test.js
@@ -22,20 +22,26 @@ require('views/main/host/details/host_component_view');
 
 var hostComponentView;
 
+function getView() {
+  return App.HostComponentView.create({
+    startBlinking: function(){},
+    doBlinking: function(){},
+    getDesiredAdminState: function(){return $.ajax({});},
+    content: Em.Object.create({
+      componentName: 'component'
+    }),
+    hostComponent: Em.Object.create()
+  });
+}
+
 describe('App.HostComponentView', function() {
 
   beforeEach(function() {
-    hostComponentView = App.HostComponentView.create({
-      startBlinking: function(){},
-      doBlinking: function(){},
-      getDesiredAdminState: function(){return $.ajax({});},
-      content: Em.Object.create({
-        componentName: 'component'
-      }),
-      hostComponent: Em.Object.create()
-    });
+    hostComponentView = getView();
   });
 
+  App.TestAliases.testAsComputedNotEqual(getView(), 'isRestartComponentDisabled', 'workStatus',
App.HostComponentStatus.started);
+
   describe('#disabled', function() {
 
     var tests = Em.A([
@@ -80,150 +86,25 @@ describe('App.HostComponentView', function() {
 
   });
 
-  describe('#isUpgradeFailed', function() {
-
-    var tests = ['UPGRADE_FAILED'];
-    var testE = true;
-    var defaultE = false;
-
-    App.HostComponentStatus.getStatusesList().forEach(function(status) {
-      it(status, function() {
-        hostComponentView.get('hostComponent').set('workStatus', status);
-        var e = tests.contains(status) ? testE : defaultE;
-        expect(hostComponentView.get('isUpgradeFailed')).to.equal(e);
-      });
-    });
-
-  });
-
-  describe('#isInstallFailed', function() {
-
-    var tests = ['INSTALL_FAILED'];
-    var testE = true;
-    var defaultE = false;
-
-    App.HostComponentStatus.getStatusesList().forEach(function(status) {
-      it(status, function() {
-        hostComponentView.get('hostComponent').set('workStatus', status);
-        var e = tests.contains(status) ? testE : defaultE;
-        expect(hostComponentView.get('isInstallFailed')).to.equal(e);
-      });
-    });
-
-  });
-
-  describe('#isStart', function() {
-
-    var tests = ['STARTED','STARTING'];
-    var testE = true;
-    var defaultE = false;
-
-    App.HostComponentStatus.getStatusesList().forEach(function(status) {
-      it(status, function() {
-        hostComponentView.get('hostComponent').set('workStatus', status);
-        var e = tests.contains(status) ? testE : defaultE;
-        expect(hostComponentView.get('isStart')).to.equal(e);
-      });
-    });
-
-  });
-
-  describe('#isStop', function() {
-
-    var tests = ['INSTALLED'];
-    var testE = true;
-    var defaultE = false;
-
-    App.HostComponentStatus.getStatusesList().forEach(function(status) {
-      it(status, function() {
-        hostComponentView.get('hostComponent').set('workStatus', status);
-        var e = tests.contains(status) ? testE : defaultE;
-        expect(hostComponentView.get('isStop')).to.equal(e);
-      });
-    });
-
-  });
-
-  describe('#isInstalling', function() {
-
-    var tests = ['INSTALLING'];
-    var testE = true;
-    var defaultE = false;
-
-    App.HostComponentStatus.getStatusesList().forEach(function(status) {
-      it(status, function() {
-        hostComponentView.get('hostComponent').set('workStatus', status);
-        var e = tests.contains(status) ? testE : defaultE;
-        expect(hostComponentView.get('isInstalling')).to.equal(e);
-      });
-    });
-
-  });
-
-  describe('#isInit', function() {
-
-    var tests = ['INIT'];
-    var testE = true;
-    var defaultE = false;
-
-    App.HostComponentStatus.getStatusesList().forEach(function(status) {
-      it(status, function() {
-        hostComponentView.get('hostComponent').set('workStatus', status);
-        var e = tests.contains(status) ? testE : defaultE;
-        expect(hostComponentView.get('isInit')).to.equal(e);
-      });
-    });
-
-  });
-
-  describe('#noActionAvailable', function() {
+  App.TestAliases.testAsComputedEqual(getView(), 'isUpgradeFailed', 'workStatus', App.HostComponentStatus.upgrade_failed);
 
-    var tests = ['STARTING', 'STOPPING', 'UNKNOWN', 'DISABLED'];
-    var testE = 'hidden';
-    var defaultE = '';
+  App.TestAliases.testAsComputedEqual(getView(), 'isInstallFailed', 'workStatus', App.HostComponentStatus.install_failed);
 
-    App.HostComponentStatus.getStatusesList().forEach(function(status) {
-      it(status, function() {
-        hostComponentView.get('hostComponent').set('workStatus', status);
-        var e = tests.contains(status) ? testE : defaultE;
-        expect(hostComponentView.get('noActionAvailable')).to.equal(e);
-      });
-    });
-
-  });
+  App.TestAliases.testAsComputedEqual(getView(), 'isStop', 'workStatus', App.HostComponentStatus.stopped);
 
-  describe('#isActive', function() {
+  App.TestAliases.testAsComputedEqual(getView(), 'isInstalling', 'workStatus', App.HostComponentStatus.installing);
 
-    var tests = Em.A([
-      {passiveState: 'OFF', e: true},
-      {passiveState: 'ON', e: false},
-      {passiveState: 'IMPLIED', e: false}
-    ]);
-
-    tests.forEach(function(test) {
-      it(test.workStatus, function() {
-        hostComponentView.get('content').set('passiveState', test.passiveState);
-        expect(hostComponentView.get('isActive')).to.equal(test.e);
-      });
-    });
+  App.TestAliases.testAsComputedEqual(getView(), 'isInit', 'workStatus', App.HostComponentStatus.init);
 
-  });
+  App.TestAliases.testAsComputedExistsIn(getView(), 'isInProgress', 'workStatus', [App.HostComponentStatus.stopping,
App.HostComponentStatus.starting]);
 
-  describe('#isRestartComponentDisabled', function() {
+  App.TestAliases.testAsComputedExistsIn(getView(), 'withoutActions', 'workStatus', [App.HostComponentStatus.starting,
App.HostComponentStatus.stopping, App.HostComponentStatus.unknown, App.HostComponentStatus.disabled]);
 
-    var tests = ['STARTED'];
-    var testE = false;
-    var defaultE = true;
+  App.TestAliases.testAsComputedExistsIn(getView(), 'isStart', 'workStatus', [App.HostComponentStatus.started,
App.HostComponentStatus.starting]);
 
-    App.HostComponentStatus.getStatusesList().forEach(function(status) {
-      it(status, function() {
-        hostComponentView.get('hostComponent').set('workStatus', status);
-        var e = tests.contains(status) ? testE : defaultE;
-        expect(hostComponentView.get('isRestartComponentDisabled')).to.equal(e);
-      });
-    });
+  App.TestAliases.testAsComputedIfThenElse(getView(), 'noActionAvailable', 'withoutActions',
'hidden', '');
 
-  });
+  App.TestAliases.testAsComputedEqual(getView(), 'isActive', 'content.passiveState', 'OFF');
 
   describe('#isDeleteComponentDisabled', function() {
 
@@ -371,22 +252,6 @@ describe('App.HostComponentView', function() {
 
   });
 
-  describe('#isInProgress', function() {
-
-    var tests = ['STOPPING', 'STARTING'];
-    var testE = true;
-    var defaultE = false;
-
-    App.HostComponentStatus.getStatusesList().forEach(function(status) {
-      it(status, function() {
-        hostComponentView.get('hostComponent').set('workStatus', status);
-        var e = tests.contains(status) ? testE : defaultE;
-        expect(hostComponentView.get('isInProgress')).to.equal(e);
-      });
-    });
-
-  });
-
   describe('#statusIconClass', function() {
     var tests = Em.A([
       {s: 'health-status-started', e: App.healthIconClassGreen},
@@ -634,16 +499,4 @@ describe('App.HostComponentView', function() {
     });
   });
 
-  describe("#isRestartComponentDisabled", function() {
-    it("component is restartable", function() {
-      hostComponentView.get('hostComponent').set('workStatus', 'STARTED');
-      hostComponentView.propertyDidChange('isRestartComponentDisabled');
-      expect(hostComponentView.get('isRestartComponentDisabled')).to.be.false;
-    });
-    it("component is not restartable", function() {
-      hostComponentView.get('hostComponent').set('workStatus', 'INSTALLED');
-      hostComponentView.propertyDidChange('isRestartComponentDisabled');
-      expect(hostComponentView.get('isRestartComponentDisabled')).to.be.true;
-    });
-  });
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/43306594/ambari-web/test/views/main/host_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/host_test.js b/ambari-web/test/views/main/host_test.js
index 22954ff..6bb3462 100644
--- a/ambari-web/test/views/main/host_test.js
+++ b/ambari-web/test/views/main/host_test.js
@@ -20,16 +20,22 @@
 var App = require('app');
 require('views/main/host');
 
+function getView() {
+  return App.MainHostView.create({
+    controller: App.MainHostController.create()
+  });
+}
+
 describe('App.MainHostView', function () {
 
   var view;
 
   beforeEach(function () {
-    view = App.MainHostView.create({
-      controller: App.MainHostController.create()
-    });
+    view = getView();
   });
 
+  App.TestAliases.testAsComputedAlias(getView(), 'colPropAssoc', 'controller.colPropAssoc',
'array');
+
   describe('#didInsertElement', function () {
 
     var cases = [

http://git-wip-us.apache.org/repos/asf/ambari/blob/43306594/ambari-web/test/views/main/service/info/summary_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/service/info/summary_test.js b/ambari-web/test/views/main/service/info/summary_test.js
index 1db8c1a..66db774 100644
--- a/ambari-web/test/views/main/service/info/summary_test.js
+++ b/ambari-web/test/views/main/service/info/summary_test.js
@@ -37,6 +37,14 @@ describe('App.MainServiceInfoSummaryView', function() {
     service: Em.Object.create()
   });
 
+  App.TestAliases.testAsComputedAlias(view, 'servicesHaveClients', 'App.services.hasClient',
'boolean');
+
+  App.TestAliases.testAsComputedAlias(view, 'serviceName', 'service.serviceName', 'string');
+
+  App.TestAliases.testAsComputedAlias(view, 'alertsCount', 'controller.content.alertsCount',
'number');
+
+  App.TestAliases.testAsComputedAlias(view, 'hasCriticalAlerts', 'controller.content.hasCriticalAlerts',
'boolean');
+
   describe('#servers', function () {
     it('services shouldn\'t have servers except FLUME and ZOOKEEPER', function () {
       expect(view.get('servers')).to.be.empty;
@@ -443,4 +451,5 @@ describe('App.MainServiceInfoSummaryView', function() {
       App.router.get.restore();
     });
   });
+
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/43306594/ambari-web/test/views/main/service/item_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/service/item_test.js b/ambari-web/test/views/main/service/item_test.js
index 560760a..8319699 100644
--- a/ambari-web/test/views/main/service/item_test.js
+++ b/ambari-web/test/views/main/service/item_test.js
@@ -21,8 +21,22 @@ require('views/main/service/item');
 
 var view;
 
+function getView() {
+  return App.MainServiceItemView.create({
+    controller: Em.Object.create({
+      content: Em.Object.create({
+        hostComponents: []
+      })
+    })
+  });
+}
+
 describe('App.MainServiceItemView', function () {
 
+  App.TestAliases.testAsComputedAlias(getView(), 'serviceName', 'controller.content.serviceName',
'string');
+
+  App.TestAliases.testAsComputedAlias(getView(), 'displayName', 'controller.content.displayName',
'string');
+
   describe('#mastersExcludedCommands', function () {
 
     view = App.MainServiceItemView.create({
@@ -564,5 +578,6 @@ describe('App.MainServiceItemView', function () {
       expect(view.get('isMaintenanceSet')).to.be.false;
     });
   });
+
 });
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/43306594/ambari-web/test/views/wizard/step1_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/wizard/step1_view_test.js b/ambari-web/test/views/wizard/step1_view_test.js
index 76491a5..a470495 100644
--- a/ambari-web/test/views/wizard/step1_view_test.js
+++ b/ambari-web/test/views/wizard/step1_view_test.js
@@ -22,6 +22,10 @@ require('views/wizard/step1_view');
 var view;
 var controller;
 
+function getView() {
+  return App.WizardStep1View.create();
+}
+
 describe('App.WizardStep1View', function () {
 
   describe('#operatingSystems', function () {
@@ -204,42 +208,7 @@ describe('App.WizardStep1View', function () {
     });
   });
 
-  describe('#isNoOsChecked', function () {
-    view = App.WizardStep1View.create();
-
-    var tests = Em.A([
-      {
-        operatingSystems: [
-          {'isSelected': false},
-          {'isSelected': false}
-        ],
-        e: true
-      },
-      {
-        operatingSystems: [
-          {'isSelected': true},
-          {'isSelected': false}
-        ],
-        e: false
-      },
-      {
-        operatingSystems: [
-          {'isSelected': true},
-          {'isSelected': true}
-        ],
-        e: false
-      }
-    ]);
-
-    tests.forEach(function (test) {
-      it(test.operatingSystems.mapProperty('isSelected').join(', '), function () {
-        var operatingSystems = view.get('operatingSystems');
-        Ember.set(operatingSystems[0], 'isSelected', test.operatingSystems[0].isSelected);
-        Ember.set(operatingSystems[1], 'isSelected', test.operatingSystems[1].isSelected);
-        expect(view.get('isNoOsChecked')).to.equal(test.e);
-      });
-    });
-  });
+  App.TestAliases.testAsComputedEveryBy(getView(), 'isNoOsChecked', 'operatingSystems', 'isSelected',
false);
 
   describe('#stacks', function () {
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/43306594/ambari-web/test/views/wizard/step2_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/wizard/step2_view_test.js b/ambari-web/test/views/wizard/step2_view_test.js
index fc8f79f..0a74566 100644
--- a/ambari-web/test/views/wizard/step2_view_test.js
+++ b/ambari-web/test/views/wizard/step2_view_test.js
@@ -23,20 +23,17 @@ var view, controller = Em.Object.create({
   clusterNameError: ''
 });
 
+function getView() {
+  return App.WizardStep2View.create({'controller': controller});
+}
+
 describe('App.WizardStep0View', function () {
 
   beforeEach(function() {
-    view = App.WizardStep2View.create({'controller': controller});
+    view = getView();
   });
 
-  describe('#sshKeyState', function() {
-    it('should be equal to controller.content.installOptions.manualInstall', function() {
-      controller.set('content', {installOptions: {manualInstall: false}});
-      expect(view.get('sshKeyState')).to.equal(false);
-      controller.toggleProperty('content.installOptions.manualInstall');
-      expect(view.get('sshKeyState')).to.equal(true);
-    });
-  });
+  App.TestAliases.testAsComputedAlias(getView(), 'sshKeyState', 'controller.content.installOptions.manualInstall',
'string');
 
   describe('#didInsertElement', function() {
     beforeEach(function () {

http://git-wip-us.apache.org/repos/asf/ambari/blob/43306594/ambari-web/test/views/wizard/step3/hostLogPopupBody_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/wizard/step3/hostLogPopupBody_view_test.js b/ambari-web/test/views/wizard/step3/hostLogPopupBody_view_test.js
index 2275a6c..8c0b8b3 100644
--- a/ambari-web/test/views/wizard/step3/hostLogPopupBody_view_test.js
+++ b/ambari-web/test/views/wizard/step3/hostLogPopupBody_view_test.js
@@ -19,14 +19,19 @@
 var App = require('app');
 require('views/wizard/step3/hostLogPopupBody_view');
 var view;
+
+function getView() {
+  return App.WizardStep3HostLogPopupBody.create({
+    parentView: Em.Object.create({
+      host: Em.Object.create()
+    })
+  });
+}
+
 describe('App.WizardStep3HostLogPopupBody', function() {
 
   beforeEach(function() {
-    view = App.WizardStep3HostLogPopupBody.create({
-      parentView: Em.Object.create({
-        host: Em.Object.create()
-      })
-    });
+    view = getView();
   });
 
   describe('#textArea', function() {
@@ -47,12 +52,7 @@ describe('App.WizardStep3HostLogPopupBody', function() {
 
   });
 
-  describe('#bootLog', function() {
-    it('should be equal to parentView.host.bootLog', function() {
-      var log = 'i wanna play a game';
-      view.set('parentView.host.bootLog', log);
-      expect(view.get('bootLog')).to.equal(log);
-    });
-  });
+  App.TestAliases.testAsComputedAlias(getView(), 'bootLog', 'parentView.host.bootLog', 'string');
+
 
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/43306594/ambari-web/test/views/wizard/step3/hostWarningPopupBody_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/wizard/step3/hostWarningPopupBody_view_test.js b/ambari-web/test/views/wizard/step3/hostWarningPopupBody_view_test.js
index 3cd53a0..d49cb7a 100644
--- a/ambari-web/test/views/wizard/step3/hostWarningPopupBody_view_test.js
+++ b/ambari-web/test/views/wizard/step3/hostWarningPopupBody_view_test.js
@@ -21,19 +21,27 @@ var lazyloading = require('utils/lazy_loading');
 require('views/wizard/step3/hostWarningPopupBody_view');
 var view;
 
+function getView() {
+  return App.WizardStep3HostWarningPopupBody.create({
+    didInsertElement: Em.K,
+    $: function() {
+      return Em.Object.create({
+        toggle: Em.K
+      })
+    }
+  });
+}
+
 describe('App.WizardStep3HostWarningPopupBody', function() {
 
   beforeEach(function() {
-    view = App.WizardStep3HostWarningPopupBody.create({
-      didInsertElement: Em.K,
-      $: function() {
-        return Em.Object.create({
-          toggle: Em.K
-        })
-      }
-    });
+    view = getView();
   });
 
+  App.TestAliases.testAsComputedAlias(getView(), 'warningsByHost', 'bodyController.warningsByHost',
'array');
+
+  App.TestAliases.testAsComputedAlias(getView(), 'warnings', 'bodyController.warnings', 'array');
+
   describe('#onToggleBlock', function() {
     it('should toggle', function() {
       var context = Em.Object.create({isCollapsed: false});

http://git-wip-us.apache.org/repos/asf/ambari/blob/43306594/ambari-web/test/views/wizard/step6_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/wizard/step6_view_test.js b/ambari-web/test/views/wizard/step6_view_test.js
index 199c24e..9beca51 100644
--- a/ambari-web/test/views/wizard/step6_view_test.js
+++ b/ambari-web/test/views/wizard/step6_view_test.js
@@ -23,14 +23,20 @@ require('utils/string_utils');
 require('views/wizard/step6_view');
 var view;
 
+function getView() {
+  return App.WizardStep6View.create({
+    controller: App.WizardStep6Controller.create()
+  });
+}
+
 describe('App.WizardStep6View', function() {
 
   beforeEach(function() {
-    view = App.WizardStep6View.create({
-      controller: App.WizardStep6Controller.create()
-    });
+    view = getView();
   });
 
+  App.TestAliases.testAsComputedAlias(getView(), 'filteredContent', 'content', 'array');
+
   describe('#content', function() {
     it('should be same to controller.hosts', function() {
       view.set('content', []);
@@ -40,15 +46,6 @@ describe('App.WizardStep6View', function() {
     });
   });
 
-  describe('#filteredContent', function() {
-    it('should be same to content', function() {
-      view.set('content', []);
-      var d = [{}, {}];
-      view.set('controller.hosts', d);
-      expect(view.get('filteredContent')).to.eql(d);
-    });
-  });
-
   describe('#didInsertElement', function() {
 
     beforeEach(function() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/43306594/ambari-web/test/views/wizard/step9/hostLogPopupBody_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/wizard/step9/hostLogPopupBody_view_test.js b/ambari-web/test/views/wizard/step9/hostLogPopupBody_view_test.js
index c039c0a..24cac78 100644
--- a/ambari-web/test/views/wizard/step9/hostLogPopupBody_view_test.js
+++ b/ambari-web/test/views/wizard/step9/hostLogPopupBody_view_test.js
@@ -20,16 +20,22 @@ var App = require('app');
 require('views/wizard/step9/hostLogPopupBody_view');
 var view;
 
+function getView() {
+  return App.WizardStep9HostLogPopupBodyView.create({
+    parentView: Em.Object.create({
+      host: Em.Object.create()
+    })
+  });
+}
+
 describe('App.WizardStep9HostLogPopupBodyView', function() {
 
   beforeEach(function() {
-    view = App.WizardStep9HostLogPopupBodyView.create({
-      parentView: Em.Object.create({
-        host: Em.Object.create()
-      })
-    });
+    view = getView();
   });
 
+  App.TestAliases.testAsComputedAlias(getView(), 'isNoTasksScheduled', 'parentView.host.isNoTasksForInstall',
'boolean');
+
   describe('#isHeartbeatLost', function() {
     it('should depends on parentView.host.status', function() {
       view.set('parentView.host.status', 'success');
@@ -39,15 +45,6 @@ describe('App.WizardStep9HostLogPopupBodyView', function() {
     });
   });
 
-  describe('#isNoTasksScheduled', function() {
-    it('should be same to parentView.host.isNoTasksForInstall', function() {
-      view.set('parentView.host.isNoTasksForInstall', true);
-      expect(view.get('isNoTasksScheduled')).to.equal(true);
-      view.set('parentView.host.isNoTasksForInstall', false);
-      expect(view.get('isNoTasksScheduled')).to.equal(false);
-    });
-  });
-
   describe('#visibleTasks', function() {
     Em.A([
         {


Mime
View raw message