You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by at...@apache.org on 2016/03/17 14:22:34 UTC

ambari git commit: AMBARI-15440 Cover create widget views with unit tests. (atkach)

Repository: ambari
Updated Branches:
  refs/heads/trunk 0503753da -> fac2eece9


AMBARI-15440 Cover create widget views with unit tests. (atkach)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/fac2eece
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/fac2eece
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/fac2eece

Branch: refs/heads/trunk
Commit: fac2eece9fe9b5bf8169f49448417b922bb56b5e
Parents: 0503753
Author: Andrii Tkach <at...@hortonworks.com>
Authored: Wed Mar 16 15:46:06 2016 +0200
Committer: Andrii Tkach <at...@hortonworks.com>
Committed: Thu Mar 17 15:20:32 2016 +0200

----------------------------------------------------------------------
 ambari-web/app/assets/test/tests.js             |   4 +
 .../service/widgets/create/expression_view.js   |  18 +-
 .../main/service/widgets/create/step1_view.js   |   3 +-
 .../main/service/widgets/create/step2_view.js   |   7 +-
 .../main/service/widgets/create/step3_view.js   |   3 +-
 .../widgets/create/expression_view_test.js      | 382 ++++++++++++++++++-
 .../service/widgets/create/step1_view_test.js   |  63 +++
 .../service/widgets/create/step2_view_test.js   | 132 +++++++
 .../service/widgets/create/step3_view_test.js   |  48 +++
 .../service/widgets/create/wizard_view_test.js  | 109 ++++++
 10 files changed, 745 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/fac2eece/ambari-web/app/assets/test/tests.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/test/tests.js b/ambari-web/app/assets/test/tests.js
index 1d5f8ad..6e33833 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -285,6 +285,10 @@ var files = [
   'test/views/main/service/services/storm_test',
   'test/views/main/service/services/yarn_test',
   'test/views/main/service/widgets/create/expression_view_test',
+  'test/views/main/service/widgets/create/wizard_view_test',
+  'test/views/main/service/widgets/create/step3_view_test',
+  'test/views/main/service/widgets/create/step2_view_test',
+  'test/views/main/service/widgets/create/step1_view_test',
   'test/views/main/admin/highAvailability/nameNode/step1_view_test',
   'test/views/main/admin/highAvailability/nameNode/step3_view_test',
   'test/views/main/admin/highAvailability/nameNode/step4_view_test',

http://git-wip-us.apache.org/repos/asf/ambari/blob/fac2eece/ambari-web/app/views/main/service/widgets/create/expression_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/widgets/create/expression_view.js b/ambari-web/app/views/main/service/widgets/create/expression_view.js
index 55f4cd0..3688270 100644
--- a/ambari-web/app/views/main/service/widgets/create/expression_view.js
+++ b/ambari-web/app/views/main/service/widgets/create/expression_view.js
@@ -96,9 +96,8 @@ App.WidgetWizardExpressionView = Em.View.extend({
 
   /**
    * add operator to expression data
-   * @param event
    */
-  addNumber: function (event) {
+  addNumber: function () {
     var data = this.get('expression.data');
     var lastId = (data.length > 0) ? Math.max.apply(this, data.mapProperty('id')) : 0;
 
@@ -424,7 +423,7 @@ App.InputCursorTextfieldView = Ember.TextField.extend({
     });
   }.observes('parentView.expression.data.length'),
 
-  focusOut: function(evt) {
+  focusOut: function() {
     this.saveNumber();
   },
 
@@ -444,7 +443,7 @@ App.InputCursorTextfieldView = Ember.TextField.extend({
           isOperator: true
         }));
         this.set('value', '');
-      } else if (value && value == 'm') {
+      } else if (value && value === 'm') {
         // open add metric menu
         var expressionId = "_" + parentView.get('expression.id');
         $('#add-metric-menu' + expressionId + '> div > a').click();
@@ -458,22 +457,19 @@ App.InputCursorTextfieldView = Ember.TextField.extend({
   }.observes('value'),
 
   keyDown: function (event) {
-    if ((event.keyCode == 8 || event.which == 8) && !this.get('value')) { // backspace
+    if ((event.keyCode === 8 || event.which === 8) && !this.get('value')) { // backspace
       var data = this.get('parentView.expression.data');
       if (data.length >= 1) {
         data.removeObject(data[data.length - 1]);
       }
-    } else if (event.keyCode == 13) { //Enter
+    } else if (event.keyCode === 13) { //Enter
       this.saveNumber();
     }
   },
 
   saveNumber: function() {
-    var number_utils = require("utils/number_utils");
-    var value = this.get('value');
-    if (number_utils.isPositiveNumber(value))  {
-      var parentView = this.get('parentView');
-      var data = parentView.get('expression.data');
+    if (number_utils.isPositiveNumber(this.get('value')))  {
+      var data = this.get('parentView.expression.data');
       var lastId = (data.length > 0) ? Math.max.apply(this, data.mapProperty('id')) : 0;
       data.pushObject(Em.Object.create({
         id: ++lastId,

http://git-wip-us.apache.org/repos/asf/ambari/blob/fac2eece/ambari-web/app/views/main/service/widgets/create/step1_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/widgets/create/step1_view.js b/ambari-web/app/views/main/service/widgets/create/step1_view.js
index 8334935..46655ad 100644
--- a/ambari-web/app/views/main/service/widgets/create/step1_view.js
+++ b/ambari-web/app/views/main/service/widgets/create/step1_view.js
@@ -23,8 +23,7 @@ App.WidgetWizardStep1View = Em.View.extend({
   templateName: require('templates/main/service/widgets/create/step1'),
 
   didInsertElement: function () {
-    var controller = this.get('controller');
-    controller.loadStep();
+    this.get('controller').loadStep();
     Em.run.later(this, function () {
       App.tooltip($("[rel='selectable-tooltip']"));
     }, 300);

http://git-wip-us.apache.org/repos/asf/ambari/blob/fac2eece/ambari-web/app/views/main/service/widgets/create/step2_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/widgets/create/step2_view.js b/ambari-web/app/views/main/service/widgets/create/step2_view.js
index fb359a1..dbc5bc7 100644
--- a/ambari-web/app/views/main/service/widgets/create/step2_view.js
+++ b/ambari-web/app/views/main/service/widgets/create/step2_view.js
@@ -23,6 +23,7 @@ App.WidgetWizardStep2View = Em.View.extend({
 
   /**
    * calculate template by widget type
+   * @type {object}
    */
   templateType: function () {
     switch (this.get('controller.content.widgetType')) {
@@ -38,7 +39,9 @@ App.WidgetWizardStep2View = Em.View.extend({
       case 'GRAPH':
         return {
           isGraph: true
-        }
+        };
+      default:
+        return {};
     }
   }.property('controller.content.widgetType'),
 
@@ -46,7 +49,7 @@ App.WidgetWizardStep2View = Em.View.extend({
     Em.run.later(this, function () {
       App.tooltip($("[rel='threshold-tooltip']"));
     }, 500);
-  }.observes(''),
+  },
 
   didInsertElement: function () {
     var controller = this.get('controller');

http://git-wip-us.apache.org/repos/asf/ambari/blob/fac2eece/ambari-web/app/views/main/service/widgets/create/step3_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/service/widgets/create/step3_view.js b/ambari-web/app/views/main/service/widgets/create/step3_view.js
index cdb975d..799a6f5 100644
--- a/ambari-web/app/views/main/service/widgets/create/step3_view.js
+++ b/ambari-web/app/views/main/service/widgets/create/step3_view.js
@@ -21,8 +21,7 @@ App.WidgetWizardStep3View = Em.View.extend({
   templateName: require('templates/main/service/widgets/create/step3'),
 
   didInsertElement: function () {
-    var controller = this.get('controller');
-    controller.initPreviewData();
+    this.get('controller').initPreviewData();
   }
 
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/fac2eece/ambari-web/test/views/main/service/widgets/create/expression_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/service/widgets/create/expression_view_test.js b/ambari-web/test/views/main/service/widgets/create/expression_view_test.js
index 72c2527..6f1d96d 100644
--- a/ambari-web/test/views/main/service/widgets/create/expression_view_test.js
+++ b/ambari-web/test/views/main/service/widgets/create/expression_view_test.js
@@ -17,16 +17,23 @@
  */
 
 var App = require('app');
+var number_utils = require("utils/number_utils");
+var misc = require('utils/misc');
 
 
 describe('App.WidgetWizardExpressionView', function () {
-  var view = App.WidgetWizardExpressionView.create({
-    expression: {
-      data: []
-    },
-    controller: Em.Object.create({
-      updateExpressions: Em.K
-    })
+  var view;
+
+  beforeEach(function() {
+    view = App.WidgetWizardExpressionView.create({
+      expression: {
+        data: []
+      },
+      controller: Em.Object.create({
+        updateExpressions: Em.K
+      })
+    });
+    view.removeObserver('expression.data.length', view, 'validate');
   });
 
   describe("#validate()", function() {
@@ -180,8 +187,369 @@ describe('App.WidgetWizardExpressionView', function () {
     testCases.forEach(function (test) {
       it(test.data.mapProperty('name').join("") + " - isInvalid = " + test.result, function () {
         view.set('expression.data', test.data);
+        view.validate();
         expect(view.get('isInvalid')).to.equal(test.result);
       });
     }, this);
   });
+
+  describe("#isNumberValueInvalid", function() {
+
+    beforeEach(function() {
+      sinon.stub(number_utils, 'isPositiveNumber').returns(true)
+    });
+    afterEach(function() {
+      number_utils.isPositiveNumber.restore();
+    });
+
+    it("numberValue is empty", function() {
+      view.set('numberValue', '');
+      view.propertyDidChange('isNumberValueInvalid');
+      expect(view.get('isNumberValueInvalid')).to.be.true;
+    });
+
+    it("numberValue is ' '", function() {
+      view.set('numberValue', ' ');
+      view.propertyDidChange('isNumberValueInvalid');
+      expect(view.get('isNumberValueInvalid')).to.be.true;
+    });
+
+    it("numberValue is '2'", function() {
+      view.set('numberValue', '2');
+      view.propertyDidChange('isNumberValueInvalid');
+      expect(view.get('isNumberValueInvalid')).to.be.false;
+    });
+  });
+
+  describe("#addOperator()", function() {
+
+    it("add first operator", function() {
+      var event = {context: 'o1'};
+      view.set('expression', Em.Object.create({
+        data: []
+      }));
+      view.addOperator(event);
+      expect(view.get('expression.data').mapProperty('id')).to.eql([1]);
+      expect(view.get('expression.data').mapProperty('name')).to.eql(['o1']);
+    });
+
+    it("add second operator", function() {
+      var event = {context: 'o2'};
+      view.set('expression', Em.Object.create({
+        data: [{id: 1, name: 'o1'}]
+      }));
+      view.addOperator(event);
+      expect(view.get('expression.data').mapProperty('id')).to.eql([1, 2]);
+      expect(view.get('expression.data').mapProperty('name')).to.eql(['o1', 'o2']);
+    });
+  });
+
+  describe("#addNumber()", function() {
+
+    it("add first number", function() {
+      view.set('expression', Em.Object.create({
+        data: []
+      }));
+      view.set('numberValue', '1');
+      view.addNumber();
+      expect(view.get('expression.data').mapProperty('id')).to.eql([1]);
+      expect(view.get('expression.data').mapProperty('name')).to.eql(['1']);
+      expect(view.get('numberValue')).to.be.empty;
+    });
+
+    it("add second number", function() {
+      view.set('expression', Em.Object.create({
+        data: [{id: 1, name: '1'}]
+      }));
+      view.set('numberValue', '2');
+      view.addNumber();
+      expect(view.get('expression.data').mapProperty('id')).to.eql([1, 2]);
+      expect(view.get('expression.data').mapProperty('name')).to.eql(['1', '2']);
+      expect(view.get('numberValue')).to.be.empty;
+    });
+  });
+
+  describe("#redrawField()", function() {
+
+    beforeEach(function() {
+      sinon.stub(misc, 'sortByOrder').returns([{}]);
+    });
+    afterEach(function() {
+      misc.sortByOrder.restore();
+    });
+
+    it("sortByOrder should be called", function() {
+      view.redrawField();
+      expect(misc.sortByOrder.calledOnce).to.be.true;
+      expect(view.get('expression.data')).to.be.eql([{}]);
+    });
+  });
+
+  describe("#didInsertElement()", function() {
+
+    beforeEach(function() {
+      sinon.stub(view, 'propertyDidChange');
+      sinon.stub(Em.run, 'next');
+    });
+    afterEach(function() {
+      view.propertyDidChange.restore();
+      Em.run.next.restore();
+    });
+
+    it("Em.run.next should be called", function() {
+      view.didInsertElement();
+      expect(view.propertyDidChange.calledOnce).to.be.true;
+      expect(Em.run.next.calledOnce).to.be.true;
+    });
+  });
+
+  describe("#removeElement()", function() {
+
+    it("object should be removed", function() {
+      var event = {context: 'el1'};
+      view.set('expression.data', [event.context]);
+      view.removeElement(event);
+      expect(view.get('expression.data')).to.be.empty;
+    });
+  });
+});
+
+describe("App.AddNumberExpressionView", function() {
+
+  var view;
+
+  beforeEach(function() {
+    view = App.AddNumberExpressionView.create();
+  });
+
+  describe("#isInvalid", function() {
+
+    beforeEach(function() {
+      sinon.stub(number_utils, 'isPositiveNumber').returns(true)
+    });
+    afterEach(function() {
+      number_utils.isPositiveNumber.restore();
+    });
+
+    it("value is empty", function() {
+      view.set('value', '');
+      view.propertyDidChange('isInvalid');
+      expect(view.get('isInvalid')).to.be.false;
+    });
+
+    it("value is ' '", function() {
+      view.set('value', ' ');
+      view.propertyDidChange('isInvalid');
+      expect(view.get('isInvalid')).to.be.false;
+    });
+
+    it("value is '2'", function() {
+      view.set('value', '2');
+      view.propertyDidChange('isInvalid');
+      expect(view.get('isInvalid')).to.be.false;
+    });
+  });
+});
+
+describe("App.InputCursorTextfieldView", function() {
+
+  var view;
+
+  beforeEach(function() {
+    view = App.InputCursorTextfieldView.create({
+      parentView: App.WidgetWizardExpressionView.create({
+        expression: {
+          data: []
+        },
+        controller: Em.Object.create({
+          updateExpressions: Em.K
+        })
+      })
+    });
+    view.removeObserver('value', view, 'validateInput');
+  });
+
+  describe("#didInsertElement()", function() {
+
+    beforeEach(function() {
+      sinon.stub(view, 'focusCursor');
+    });
+    afterEach(function() {
+      view.focusCursor.restore();
+    });
+
+    it("focusCursor should be called", function() {
+      view.didInsertElement();
+      expect(view.focusCursor.calledOnce).to.be.true;
+    });
+  });
+
+  describe("#focusOut()", function() {
+
+    beforeEach(function() {
+      sinon.stub(view, 'saveNumber');
+    });
+    afterEach(function() {
+      view.saveNumber.restore();
+    });
+
+    it("saveNumber should be called", function() {
+      view.focusOut();
+      expect(view.saveNumber.calledOnce).to.be.true;
+    });
+  });
+
+  describe("#focusCursor()", function() {
+    var mock = {
+      focus: Em.K
+    };
+
+    beforeEach(function() {
+      sinon.stub(Em.run, 'next', Em.clb);
+      sinon.stub(view, '$').returns(mock);
+      sinon.stub(mock, 'focus');
+      view.focusCursor();
+    });
+    afterEach(function() {
+      Em.run.next.restore();
+      view.$.restore();
+      mock.focus.restore();
+    });
+
+    it("Em.run.next should be called", function() {
+      expect(Em.run.next.calledOnce).to.be.true;
+    });
+
+    it("$ should be called", function() {
+      expect(view.$.calledTwice).to.be.true;
+    });
+
+    it("focus should be called", function() {
+      expect(mock.focus.calledOnce).to.be.true;
+    });
+  });
+
+  describe("#validateInput()", function() {
+
+    beforeEach(function() {
+      this.mock = sinon.stub(number_utils, 'isPositiveNumber');
+    });
+    afterEach(function() {
+      this.mock.restore();
+    });
+
+    it("value is positive number", function() {
+      this.mock.returns(true);
+      view.validateInput();
+      expect(view.get('isInvalid')).to.be.false;
+    });
+
+    it("value is null", function() {
+      this.mock.returns(false);
+      view.set('value', null);
+      view.validateInput();
+      expect(view.get('isInvalid')).to.be.false;
+    });
+
+    it("value is empty", function() {
+      this.mock.returns(false);
+      view.set('value', '');
+      view.validateInput();
+      expect(view.get('isInvalid')).to.be.false;
+    });
+
+    it("value is operator", function() {
+      this.mock.returns(false);
+      view.set('value', '+');
+      view.validateInput();
+      expect(view.get('isInvalid')).to.be.false;
+      expect(view.get('parentView.expression.data')).to.not.be.empty;
+      expect(view.get('value')).to.be.empty;
+    });
+
+    it("value is 'm'", function() {
+      this.mock.returns(false);
+      view.set('value', '+');
+      view.validateInput();
+      expect(view.get('isInvalid')).to.be.false;
+      expect(view.get('value')).to.be.empty;
+    });
+
+    it("value is invalid", function() {
+      this.mock.returns(false);
+      view.set('value', '%');
+      view.validateInput();
+      expect(view.get('isInvalid')).to.be.true;
+    });
+  });
+
+  describe("#keyDown()", function() {
+
+    beforeEach(function() {
+      sinon.stub(view, 'saveNumber');
+    });
+    afterEach(function() {
+      view.saveNumber.restore();
+    });
+
+    it("unexpected key", function() {
+      view.set('parentView.expression.data', [{name: '1'}, {name: '2'}]);
+      view.keyDown({keyCode: 9});
+      expect(view.saveNumber.called).to.be.false;
+      expect(view.get('parentView.expression.data.length')).to.be.equal(2);
+    });
+
+    it("backspace key and not empty value", function() {
+      view.set('value', 'm');
+      view.set('parentView.expression.data', [{name: '1'}, {name: '2'}]);
+      view.keyDown({keyCode: 8});
+      expect(view.saveNumber.called).to.be.false;
+      expect(view.get('parentView.expression.data.length')).to.be.equal(2);
+    });
+
+    it("backspace key and empty value", function() {
+      view.set('value', '');
+      view.set('parentView.expression.data', [{name: '1'}, {name: '2'}]);
+      view.keyDown({keyCode: 8});
+      expect(view.saveNumber.called).to.be.false;
+      expect(view.get('parentView.expression.data.length')).to.be.equal(1);
+    });
+
+    it("enter key", function() {
+      view.set('value', '');
+      view.set('parentView.expression.data', [{name: '1'}, {name: '2'}]);
+      view.keyDown({keyCode: 13});
+      expect(view.saveNumber.called).to.be.true;
+      expect(view.get('parentView.expression.data.length')).to.be.equal(2);
+    });
+  });
+
+  describe("#saveNumber()", function() {
+
+    beforeEach(function() {
+      this.mock = sinon.stub(number_utils, 'isPositiveNumber');
+    });
+    afterEach(function() {
+      this.mock.restore();
+    });
+
+    it("value is a positive number", function() {
+      view.set('value', '1');
+      this.mock.returns(true);
+      view.saveNumber();
+      expect(view.get('parentView.expression.data').mapProperty('name')).to.be.eql(['1']);
+      expect(view.get('numberValue')).to.be.empty;
+      expect(view.get('isInvalid')).to.be.false;
+      expect(view.get('value')).to.be.empty;
+    });
+
+    it("value is not a positive number", function() {
+      view.set('value', '-1');
+      this.mock.returns(false);
+      view.saveNumber();
+      expect(view.get('parentView.expression.data')).to.be.empty;
+      expect(view.get('value')).to.be.equal('-1');
+    });
+  });
+
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/fac2eece/ambari-web/test/views/main/service/widgets/create/step1_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/service/widgets/create/step1_view_test.js b/ambari-web/test/views/main/service/widgets/create/step1_view_test.js
new file mode 100644
index 0000000..b2eb779
--- /dev/null
+++ b/ambari-web/test/views/main/service/widgets/create/step1_view_test.js
@@ -0,0 +1,63 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+require('/views/main/service/widgets/create/step1_view');
+
+
+describe('App.WidgetWizardStep1View', function () {
+  var view;
+
+  beforeEach(function() {
+    view = App.WidgetWizardStep1View.create({
+      controller: Em.Object.create({
+        content: Em.Object.create(),
+        loadStep: Em.K
+      })
+    });
+  });
+
+  describe("#didInsertElement()", function() {
+
+    beforeEach(function () {
+      sinon.stub(Em.run, 'later', function (ctx, callback) {
+        callback();
+      });
+      sinon.stub(App, 'tooltip');
+      sinon.stub(view.get('controller'), 'loadStep');
+      view.didInsertElement();
+    });
+    afterEach(function () {
+      Em.run.later.restore();
+      App.tooltip.restore();
+      view.get('controller').loadStep.restore();
+    });
+
+    it("loadStep should be called", function() {
+      expect(view.get('controller').loadStep.calledOnce).to.be.true;
+    });
+
+    it("Em.run.later should be called", function() {
+      expect(Em.run.later.calledOnce).to.be.true;
+    });
+
+    it("App.tooltip should be called", function() {
+      expect(App.tooltip.calledOnce).to.be.true;
+    });
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/fac2eece/ambari-web/test/views/main/service/widgets/create/step2_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/service/widgets/create/step2_view_test.js b/ambari-web/test/views/main/service/widgets/create/step2_view_test.js
new file mode 100644
index 0000000..f2baf86
--- /dev/null
+++ b/ambari-web/test/views/main/service/widgets/create/step2_view_test.js
@@ -0,0 +1,132 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+require('/views/main/service/widgets/create/step2_view');
+
+
+describe('App.WidgetWizardStep2View', function () {
+  var view;
+
+  beforeEach(function() {
+    view = App.WidgetWizardStep2View.create({
+      controller: Em.Object.create({
+        content: Em.Object.create(),
+        convertData: Em.K,
+        initWidgetData: Em.K,
+        renderProperties: Em.K,
+        updateExpressions: Em.K
+      })
+    });
+  });
+
+  describe("#templateType", function () {
+
+    it("widgetType is null", function () {
+      view.set('controller.content.widgetType', null);
+      view.propertyDidChange('templateType');
+      expect(view.get('templateType')).to.be.empty;
+    });
+
+    it("widgetType is GAUGE", function () {
+      view.set('controller.content.widgetType', 'GAUGE');
+      view.propertyDidChange('templateType');
+      expect(view.get('templateType')).to.eql({isNumber: true});
+    });
+
+    it("widgetType is NUMBER", function () {
+      view.set('controller.content.widgetType', 'NUMBER');
+      view.propertyDidChange('templateType');
+      expect(view.get('templateType')).to.eql({isNumber: true});
+    });
+
+    it("widgetType is TEMPLATE", function () {
+      view.set('controller.content.widgetType', 'TEMPLATE');
+      view.propertyDidChange('templateType');
+      expect(view.get('templateType')).to.eql({isTemplate: true});
+    });
+
+    it("widgetType is GRAPH", function () {
+      view.set('controller.content.widgetType', 'GRAPH');
+      view.propertyDidChange('templateType');
+      expect(view.get('templateType')).to.eql({isGraph: true});
+    });
+  });
+
+  describe("#ensureTooltip()", function() {
+
+    beforeEach(function () {
+      sinon.stub(Em.run, 'later', function (ctx, callback) {
+        callback();
+      });
+      sinon.stub(App, 'tooltip');
+      view.ensureTooltip();
+    });
+    afterEach(function () {
+      Em.run.later.restore();
+      App.tooltip.restore();
+    });
+
+    it("Em.run.later should be called", function() {
+      expect(Em.run.later.calledOnce).to.be.true;
+    });
+
+    it("App.tooltip should be called", function() {
+      expect(App.tooltip.calledOnce).to.be.true;
+    });
+  });
+
+  describe("#didInsertElement()", function () {
+
+    beforeEach(function () {
+      sinon.stub(view, 'ensureTooltip');
+      sinon.stub(view.get('controller'), 'convertData');
+      sinon.stub(view.get('controller'), 'initWidgetData');
+      sinon.stub(view.get('controller'), 'renderProperties');
+      sinon.stub(view.get('controller'), 'updateExpressions');
+      view.didInsertElement();
+    });
+    afterEach(function () {
+      view.ensureTooltip.restore();
+      view.get('controller').convertData.restore();
+      view.get('controller').initWidgetData.restore();
+      view.get('controller').renderProperties.restore();
+      view.get('controller').updateExpressions.restore();
+    });
+
+    it("ensureTooltip should be called", function () {
+      expect(view.ensureTooltip.calledOnce).to.be.true;
+    });
+
+    it("convertData should be called", function () {
+      expect(view.get('controller').convertData.calledOnce).to.be.true;
+    });
+
+    it("initWidgetData should be called", function () {
+      expect(view.get('controller').initWidgetData.calledOnce).to.be.true;
+    });
+
+    it("renderProperties should be called", function () {
+      expect(view.get('controller').renderProperties.calledOnce).to.be.true;
+    });
+
+    it("updateExpressions should be called", function () {
+      expect(view.get('controller').updateExpressions.calledOnce).to.be.true;
+    });
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/fac2eece/ambari-web/test/views/main/service/widgets/create/step3_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/service/widgets/create/step3_view_test.js b/ambari-web/test/views/main/service/widgets/create/step3_view_test.js
new file mode 100644
index 0000000..f7bb2bf
--- /dev/null
+++ b/ambari-web/test/views/main/service/widgets/create/step3_view_test.js
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+require('/views/main/service/widgets/create/step3_view');
+
+
+describe('App.WidgetWizardStep3View', function () {
+  var view;
+
+  beforeEach(function() {
+    view = App.WidgetWizardStep3View.create({
+      controller: Em.Object.create({
+        initPreviewData: Em.K
+      })
+    });
+  });
+
+  describe("#didInsertElement()", function() {
+
+    beforeEach(function () {
+      sinon.stub(view.get('controller'), 'initPreviewData');
+    });
+    afterEach(function () {
+      view.get('controller').initPreviewData.restore();
+    });
+
+    it("initPreviewData should be called", function() {
+      view.didInsertElement();
+      expect(view.get('controller').initPreviewData.calledOnce).to.be.true;
+    });
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/fac2eece/ambari-web/test/views/main/service/widgets/create/wizard_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/main/service/widgets/create/wizard_view_test.js b/ambari-web/test/views/main/service/widgets/create/wizard_view_test.js
new file mode 100644
index 0000000..50eea41
--- /dev/null
+++ b/ambari-web/test/views/main/service/widgets/create/wizard_view_test.js
@@ -0,0 +1,109 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var App = require('app');
+require('/views/main/service/widgets/create/wizard_view');
+
+
+describe('App.WidgetWizardView', function () {
+  var view;
+
+  beforeEach(function() {
+    view = App.WidgetWizardView.create({
+      controller: Em.Object.create({
+        content: Em.Object.create()
+      })
+    });
+  });
+
+  describe("#previewWidgetClass", function() {
+
+    it("widgetType is null", function() {
+      view.set('controller.content.widgetType', null);
+      view.propertyDidChange('previewWidgetClass');
+      expect(view.get('previewWidgetClass').create()).to.be.instanceof(Em.View);
+    });
+
+    it("widgetType is GRAPH", function() {
+      view.set('controller.content.widgetType', 'GRAPH');
+      view.propertyDidChange('previewWidgetClass');
+      expect(view.get('previewWidgetClass').create()).to.be.instanceof(App.GraphWidgetView);
+    });
+
+    it("widgetType is TEMPLATE", function() {
+      view.set('controller.content.widgetType', 'TEMPLATE');
+      view.propertyDidChange('previewWidgetClass');
+      expect(view.get('previewWidgetClass').create()).to.be.instanceof(App.TemplateWidgetView);
+    });
+
+    it("widgetType is NUMBER", function() {
+      view.set('controller.content.widgetType', 'NUMBER');
+      view.propertyDidChange('previewWidgetClass');
+      expect(view.get('previewWidgetClass').create()).to.be.instanceof(App.NumberWidgetView);
+    });
+
+    it("widgetType is GAUGE", function() {
+      view.set('controller.content.widgetType', 'GAUGE');
+      view.propertyDidChange('previewWidgetClass');
+      expect(view.get('previewWidgetClass').create()).to.be.instanceof(App.GaugeWidgetView);
+    });
+  });
+
+  describe("#isStep2", function() {
+
+    it("currentStep is '2'", function() {
+      view.set('controller.currentStep', '2');
+      view.propertyDidChange('isStep2');
+      expect(view.get('isStep2')).to.be.true;
+    });
+
+    it("currentStep is 2", function() {
+      view.set('controller.currentStep', 2);
+      view.propertyDidChange('isStep2');
+      expect(view.get('isStep2')).to.be.true;
+    });
+
+    it("currentStep is null", function() {
+      view.set('controller.currentStep', null);
+      view.propertyDidChange('isStep2');
+      expect(view.get('isStep2')).to.be.false;
+    });
+  });
+
+  describe("#isStep3", function() {
+
+    it("currentStep is '3'", function() {
+      view.set('controller.currentStep', '3');
+      view.propertyDidChange('isStep3');
+      expect(view.get('isStep3')).to.be.true;
+    });
+
+    it("currentStep is 3", function() {
+      view.set('controller.currentStep', 3);
+      view.propertyDidChange('isStep3');
+      expect(view.get('isStep3')).to.be.true;
+    });
+
+    it("currentStep is null", function() {
+      view.set('controller.currentStep', null);
+      view.propertyDidChange('isStep3');
+      expect(view.get('isStep3')).to.be.false;
+    });
+  });
+
+});