Ver Fonte

AMBARI-8000. Add UI unit tests for Slider View controllers (Max Shepel via akovalenko)

Aleksandr Kovalenko há 10 anos atrás
pai
commit
a0916c8b45

+ 201 - 0
contrib/views/slider/src/main/resources/ui/test/unit/controllers/create_app_wizard_controller_test.js

@@ -0,0 +1,201 @@
+/**
+ * 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.
+ */
+
+moduleFor('controller:createAppWizard', 'App.CreateAppWizardController');
+
+var stepCases = [
+    {
+      currentStep: 0,
+      step: 5,
+      fromNextButton: true,
+      expectedCurrentStep: 0
+    },
+    {
+      currentStep: 1,
+      step: 0,
+      fromNextButton: true,
+      expectedCurrentStep: 1
+    },
+    {
+      currentStep: 2,
+      step: 3,
+      fromNextButton: false,
+      expectedCurrentStep: 2
+    },
+    {
+      currentStep: 0,
+      step: 1,
+      fromNextButton: true,
+      expectedCurrentStep: 1
+    }
+  ],
+  currentStepTitle = 'currentStep should be {0}',
+  newApp = {
+    configs: {
+      n0: 'v0'
+    },
+    predefinedConfigNames: []
+  };
+
+test('loadStep', function () {
+
+  var controller = this.subject({
+    transitionToRoute: Em.K
+  });
+
+  Em.run(function () {
+    controller.loadStep();
+  });
+
+  equal(controller.get('currentStep'), 1, 'currentStep should be 1');
+
+});
+
+test('gotoStep', function () {
+
+  var controller = this.subject({
+    transitionToRoute: Em.K
+  });
+
+  stepCases.forEach(function (item) {
+
+    Em.run(function () {
+      controller.set('currentStep', item.currentStep);
+      controller.gotoStep(item.step, item.fromNextButton);
+    });
+
+    equal(controller.get('currentStep'), item.expectedCurrentStep, currentStepTitle.format(item.expectedCurrentStep));
+
+  });
+
+});
+
+test('actions.gotoStep', function () {
+
+  var controller = this.subject({
+    transitionToRoute: Em.K
+  });
+
+  stepCases.rejectBy('fromNextButton').forEach(function (item) {
+
+    Em.run(function () {
+      controller.set('currentStep', item.currentStep);
+      controller.send('gotoStep', item.step);
+    });
+
+    equal(controller.get('currentStep'), item.expectedCurrentStep, currentStepTitle.format(item.expectedCurrentStep));
+
+  });
+
+});
+
+test('gotoStep', function () {
+
+  var createAppWizardController = this.subject({
+    transitionToRoute: Em.K,
+    newApp: newApp
+  });
+
+  Em.run(function () {
+    createAppWizardController.gotoStep(1);
+  });
+
+  propEqual(createAppWizardController.get('newApp.configs', {}, 'custom configs should be dropped'));
+
+});
+
+test('actions.gotoStep', function () {
+
+  var createAppWizardController = this.subject({
+    transitionToRoute: Em.K,
+    newApp: newApp
+  });
+
+  Em.run(function () {
+    createAppWizardController.send('gotoStep', 1);
+  });
+
+  propEqual(createAppWizardController.get('newApp.configs', {}, 'custom configs should be dropped'));
+
+});
+
+test('dropCustomConfigs', function () {
+
+  var controller = this.subject({
+    newApp: {
+      configs: {
+        n0: 'v0',
+        n1: 'v1'
+      },
+      predefinedConfigNames: ['n0']
+    }
+  });
+
+  Em.run(function () {
+    controller.dropCustomConfigs();
+  });
+
+  propEqual(controller.get('newApp.configs'), {n0: 'v0'}, 'custom configs should be dropped');
+
+});
+
+test('nextStep', function () {
+
+  var controller = this.subject({
+    transitionToRoute: Em.K,
+    currentStep: 1
+  });
+
+  Em.run(function () {
+    controller.nextStep();
+  });
+
+  equal(controller.get('currentStep'), '2', 'should go to step2');
+
+});
+
+test('prevStep', function () {
+
+  var controller = this.subject({
+    transitionToRoute: Em.K,
+    currentStep: 2
+  });
+
+  Em.run(function () {
+    controller.prevStep();
+  });
+
+  equal(controller.get('currentStep'), '1', 'should go to step1');
+
+});
+
+test('hidePopup', function () {
+
+  var controller = this.subject({
+    viewEnabled: true,
+    transitionToRoute: Em.K,
+    newApp: {}
+  });
+
+  Em.run(function () {
+    controller.hidePopup();
+  });
+
+  equal(controller.get('newApp'), null, 'should erase app data');
+
+});

+ 472 - 1
contrib/views/slider/src/main/resources/ui/test/unit/controllers/slider_app_controller_test.js

@@ -16,7 +16,13 @@
  * limitations under the License.
  */
 
-moduleFor('controller:sliderApp', 'App.SliderAppController');
+moduleFor('controller:sliderApp', 'App.SliderAppController', {
+
+  needs: [
+    'component:bs-modal'
+  ]
+
+});
 
 test('availableActions', function () {
 
@@ -63,6 +69,471 @@ test('availableActions', function () {
 
 });
 
+test('sliderAppTabs', function () {
+
+  var cases = [
+      {
+        length: 1
+      },
+      {
+        configs: {},
+        length: 1
+      },
+      {
+        configs: {
+          n0: 'v0'
+        },
+        length: 2
+      }
+    ],
+    title = 'number of tabs should be {0}',
+    controller = this.subject();
+
+  cases.forEach(function (item) {
+
+    Em.run(function () {
+      controller.set('model', {
+        configs: item.configs
+      })
+    });
+
+    equal(controller.get('sliderAppTabs.length'), item.length, title.format(item.length));
+
+  });
+
+});
+
+test('weHaveQuicklinks', function () {
+
+  var cases = [
+      {
+        content: [
+          {
+            id: '0'
+          }
+        ],
+        value: true
+      },
+      {
+        value: false
+      }
+    ],
+    title = 'should be {0}',
+    controller = this.subject();
+
+  cases.forEach(function (item) {
+
+    Em.run(function () {
+      controller.set('model', {
+        quickLinks: {
+          content: {
+            content: item.content
+          }
+        }
+      });
+    });
+
+    equal(controller.get('weHaveQuicklinks'), item.value, title.format(item.value));
+
+  });
+
+});
+
+test('destroyButtonEnabled', function () {
+
+  var cases = [
+      {
+        confirmChecked: true,
+        string: 'disabled'
+      },
+      {
+        confirmChecked: false,
+        string: 'enabled'
+      }
+    ],
+    title = 'button is {0}',
+    controller = this.subject();
+
+  cases.forEach(function (item) {
+
+    Em.run(function () {
+      controller.set('confirmChecked', item.confirmChecked);
+    });
+
+    equal(controller.get('destroyButtonEnabled'), !item.confirmChecked, title.format(item.string));
+
+  });
+
+});
+
+test('confirmDestroy', function () {
+
+  var bsRegister = Bootstrap.ModalManager.register,
+    controller = this.subject(),
+    assertionsEqual = [
+      {
+        propertyName: 'name',
+        value: 'confirm-modal'
+      },
+      {
+        propertyName: 'title',
+        value: Ember.I18n.t('sliderApp.destroy.confirm.title')
+      },
+      {
+        propertyName: 'manual',
+        value: true
+      }
+    ],
+    assertionsDeepEqual = [
+      {
+        propertyName: 'targetObject',
+        value: controller
+      },
+      {
+        propertyName: 'controller',
+        value: controller
+      },
+      {
+        propertyName: 'body',
+        value: App.DestroyAppPopupView
+      },
+      {
+        propertyName: 'footerViews',
+        value: [App.DestroyAppPopupFooterView]
+      }
+    ],
+    title = 'modalComponent.{0} should be {1}';
+
+  Em.run(function () {
+    Bootstrap.set('ModalManager.register', function (name, component) {
+      this.registeredComponent = component;
+    });
+    controller.confirmDestroy();
+  });
+
+  assertionsEqual.forEach(function (item) {
+    equal(Bootstrap.ModalManager.registeredComponent[item.propertyName], item.value, title.format(item.propertyName, item.value));
+  });
+  assertionsDeepEqual.forEach(function (item) {
+    deepEqual(Bootstrap.ModalManager.registeredComponent[item.propertyName], item.value, title.format(item.propertyName, item.value));
+  });
+
+  Bootstrap.set('ModalManager.register', bsRegister);
+
+});
+
+test('tryDoAction', function () {
+
+  var controller = this.subject({
+    currentAction: 'customMethod',
+    customMethod: function () {
+      this.set('groupedComponents', [{}]);
+    }
+  });
+
+  Em.run(function () {
+    controller.tryDoAction();
+  });
+
+  deepEqual(controller.get('groupedComponents'), [{}], 'currentAction should be executed');
+
+});
+
+test('groupComponents', function () {
+
+  var controller = this.subject({
+    appType: {
+      components: [
+        Em.Object.create({
+          name: 'c0'
+        }),
+        Em.Object.create({
+          name: 'c1'
+        })
+      ]
+    },
+    components: [
+      Em.Object.create({
+        componentName: 'c0'
+      })
+    ]
+  });
+
+  Em.run(function () {
+    controller.groupComponents();
+  });
+
+  equal(controller.get('groupedComponents')[0].count, 1, 'count should be incremented');
+  equal(controller.get('groupedComponents')[1].count, 0, 'count shouldn\'t be incremented');
+
+});
+
+test('validateGroupedComponents', function () {
+
+  var cases = [
+      {
+        count: ' 1',
+        hasErrors: true,
+        title: 'validation failure'
+      },
+      {
+        count: '-1',
+        hasErrors: true,
+        title: 'validation failure'
+      },
+      {
+        count: 1,
+        hasErrors: false,
+        title: 'validation success'
+      }
+    ],
+    controller = this.subject();
+
+  cases.forEach(function (item) {
+
+    Em.run(function () {
+      controller.set('groupedComponents', [{
+        count: item.count
+      }]);
+      controller.validateGroupedComponents();
+    });
+
+    equal(controller.get('groupedComponentsHaveErrors'), item.hasErrors, item.title);
+
+  });
+
+});
+
+test('flex', function () {
+
+  var bsOpen = Bootstrap.ModalManager.open,
+    controller = this.subject({
+      appType: {
+        components: [
+          Em.Object.create({
+            name: 'c0'
+          }),
+          Em.Object.create({
+            name: 'c1'
+          })
+        ]
+      },
+      components: [
+        Em.Object.create({
+          componentName: 'c0'
+        })
+      ]
+    });
+
+  Em.run(function () {
+    Bootstrap.set('ModalManager.open', Em.K);
+    controller.flex();
+  });
+
+  equal(controller.get('groupedComponents')[0].count, 1, 'count should be incremented');
+  equal(controller.get('groupedComponents')[1].count, 0, 'count shouldn\'t be incremented');
+
+  Bootstrap.set('ModalManager.open', bsOpen);
+
+});
+
+test('mapComponentsForFlexRequest', function () {
+
+  var controller = this.subject({
+    groupedComponents: [
+      {
+        name: 'c0',
+        count: 1
+      },
+      {
+        name: 'c1',
+        count: 0
+      }
+    ]
+  });
+
+  deepEqual(controller.mapComponentsForFlexRequest(), {
+    c0: {
+      instanceCount: 1
+    },
+    c1: {
+      instanceCount: 0
+    }
+  }, 'should map grouped components');
+
+});
+
+test('destroy', function () {
+
+  var controller = this.subject({
+    model: Em.Object.create({
+      isActionPerformed: false
+    })
+  });
+
+  Em.run(function () {
+    controller.destroy();
+  });
+
+  ok(controller.get('model.isActionPerformed'), 'model.isActionPerformed should be true');
+
+});
+
+test('actionErrorCallback', function () {
+
+  var controller = this.subject({
+    model: Em.Object.create({
+      isActionPerformed: true
+    }),
+    defaultErrorHandler: Em.K
+  });
+
+  Em.run(function () {
+    controller.actionErrorCallback(null, null, null, {
+      url: null,
+      type: null
+    });
+  });
+
+  ok(!controller.get('model.isActionPerformed'), 'model.isActionPerformed should be true');
+
+});
+
+test('actions.submitFlex', function () {
+
+  var bsClose = Bootstrap.ModalManager.close,
+    controller = this.subject({
+      model: Em.Object.create({
+        id: 0,
+        name: 'n'
+      }),
+      validateGroupedComponents: function () {
+        return false;
+      },
+      groupedComponentsHaveErrors: true
+    });
+
+  Em.run(function () {
+    Bootstrap.set('ModalManager.close', Em.K);
+    controller.send('submitFlex');
+  });
+
+  equal(controller.get('groupedComponents.length'), 0, 'should clear grouped components');
+  ok(!controller.get('groupedComponentsHaveErrors'), 'should clear components errors');
+
+  Bootstrap.set('ModalManager.close', bsClose);
+
+});
+
+test('actions.closeFlex', function () {
+
+  var controller = this.subject({
+    groupedComponents: [{}],
+    groupedComponentsHaveErrors: true
+  });
+
+  Em.run(function () {
+    controller.send('closeFlex');
+  });
+
+  equal(controller.get('groupedComponents.length'), 0, 'should clear grouped components');
+  ok(!controller.get('groupedComponentsHaveErrors'), 'should clear components errors');
+
+});
+
+test('modalConfirmed', function () {
+
+  var bsClose = Bootstrap.ModalManager.close,
+    controller = this.subject({
+      confirmChecked: true,
+      currentAction: 'customMethod',
+      customMethod: function () {
+        this.set('groupedComponents', [{}]);
+      }
+    });
+
+  Em.run(function () {
+    Bootstrap.set('ModalManager.close', Em.K);
+    controller.send('modalConfirmed');
+  });
+
+  deepEqual(controller.get('groupedComponents'), [{}], 'currentAction should be executed');
+  ok(!controller.get('confirmChecked'), 'confirmChecked should be false');
+
+  Bootstrap.set('ModalManager.close', bsClose);
+
+});
+
+test('modalCanceled', function () {
+
+  var bsClose = Bootstrap.ModalManager.close,
+    controller = this.subject({
+      confirmChecked: true
+    });
+
+  Em.run(function () {
+    Bootstrap.set('ModalManager.close', Em.K);
+    controller.send('modalCanceled');
+  });
+
+  ok(!controller.get('confirmChecked'), 'confirmChecked should be false');
+
+  Bootstrap.set('ModalManager.close', bsClose);
+
+});
+
+test('openModal', function () {
+
+  var bsOpen = Bootstrap.ModalManager.open,
+    cases = [
+      {
+        options: {
+          action: 'customMethod'
+        },
+        groupedComponents: [{}],
+        title: 'should execute currentAction'
+      },
+      {
+        options: {
+          action: 'customMethod',
+          customConfirm: 'customConfirmMethod'
+        },
+        groupedComponents: [{}, {}],
+        title: 'should execute customConfirm'
+      }
+    ],
+    controller = this.subject({
+      customMethod: function () {
+        this.set('groupedComponents', [{}]);
+      },
+      customConfirmMethod: function () {
+        this.set('groupedComponents', [{}, {}]);
+      }
+    });
+
+  Em.run(function () {
+    Bootstrap.set('ModalManager.open', Em.K);
+    controller.send('openModal', {
+      action: 'customMethod'
+    });
+  });
+
+  equal(controller.get('currentAction'), 'customMethod', 'should set currentAction');
+
+  cases.forEach(function (item) {
+
+    Em.run(function () {
+      controller.send('openModal', item.options);
+    });
+
+    deepEqual(controller.get('groupedComponents'), item.groupedComponents, item.title);
+
+  });
+
+  Bootstrap.set('ModalManager.open', bsOpen);
+
+});
+
 test('quickLinksOrdered', function() {
   expect(2);
 

+ 52 - 0
contrib/views/slider/src/main/resources/ui/test/unit/controllers/slider_apps_controller_test.js

@@ -0,0 +1,52 @@
+/**
+ * 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.
+ */
+
+moduleFor('controller:sliderApps', 'App.SliderAppsController');
+
+test('showUnavailableAppsPopup', function () {
+
+  var bsOpen = Bootstrap.ModalManager.open,
+    cases = [
+      {
+        message: 'message',
+        result: 'message',
+        title: 'errorMessage property should be set'
+      },
+      {
+        result: Em.I18n.t('slider.apps.undefined.issue'),
+        title: 'default error message'
+      }
+    ],
+    controller = this.subject({
+      errorMessage: null
+    });
+
+  cases.forEach(function (item) {
+
+    Em.run(function () {
+      Bootstrap.set('ModalManager.open', Em.K);
+      controller.showUnavailableAppsPopup(item.message);
+    });
+
+    equal(controller.get('errorMessage'), item.result, item.title);
+
+    Bootstrap.set('ModalManager.open', bsOpen);
+
+  });
+
+});

+ 166 - 1
contrib/views/slider/src/main/resources/ui/test/unit/controllers/slider_controller_test.js

@@ -16,7 +16,32 @@
  * limitations under the License.
  */
 
-moduleFor('controller:slider', 'App.SliderController');
+moduleFor('controller:slider', 'App.SliderController', {
+
+  setup: function () {
+    App.setProperties({
+      gangliaHost: null,
+      gangliaClusters: null
+    });
+    Ember.run(App, App.advanceReadiness);
+  },
+
+  teardown: function () {
+    App.reset();
+  }
+
+});
+
+var properties = [
+  Em.Object.create({
+    viewConfigName: 'ganglia.additional.clusters',
+    value: 'h0:8080,h1:3333'
+  }),
+  Em.Object.create({
+    viewConfigName: 'ganglia.server.hostname',
+    value: 'h2'
+  })
+];
 
 test('getViewDisplayParametersSuccessCallback', function () {
 
@@ -39,3 +64,143 @@ test('getViewDisplayParametersSuccessCallback', function () {
   equal(App.get('sliderUser'), 'admin', 'valid sliderUser is set');
 
 });
+
+test('getParametersFromViewPropertiesSuccessCallback', function () {
+
+  var storeAll = App.SliderApp.store.all,
+    controller = this.subject();
+
+  Em.run(function () {
+    App.SliderApp.store.all = function () {
+      return properties;
+    };
+    controller.getParametersFromViewPropertiesSuccessCallback({
+      parameters: {
+        'ganglia.additional.clusters': 'h0:8080,h1:3333',
+        'ganglia.server.hostname': 'h2'
+      },
+      validations: [{}, {}]
+    });
+  });
+
+  deepEqual(App.get('gangliaClusters'), [
+    {
+      name: 'h0',
+      port: '8080'
+    },
+    {
+      name: 'h1',
+      port: '3333'
+    }
+  ], 'should set gangliaClusters');
+  equal(App.get('gangliaHost'), 'h2', 'should set gangliaHost');
+
+  App.SliderApp.store.set('all', storeAll);
+
+});
+
+ test('initGangliaProperties', function () {
+
+   var storeAll = App.SliderApp.store.all,
+     controller = this.subject();
+
+   Em.run(function () {
+     App.SliderApp.store.all = function () {
+       return properties;
+     };
+     controller.initGangliaProperties();
+   });
+
+   deepEqual(App.get('gangliaClusters'), [
+     {
+       name: 'h0',
+       port: '8080'
+     },
+     {
+       name: 'h1',
+       port: '3333'
+     }
+   ], 'should set gangliaClusters');
+   equal(App.get('gangliaHost'), 'h2', 'should set gangliaHost');
+
+   App.SliderApp.store.set('all', storeAll);
+
+ });
+
+test('formatGangliaClusters', function () {
+
+  var cases = [
+      {
+        prop: null,
+        gangliaCustomClusters: [],
+        title: 'empty value'
+      },
+      {
+        prop: 'h0',
+        gangliaCustomClusters: [],
+        title: 'no port specified'
+      },
+      {
+        prop: 'h1:8080,h2:3333',
+        gangliaCustomClusters: [
+          {
+            name: 'h1',
+            port: '8080'
+          },
+          {
+            name: 'h2',
+            port: '3333'
+          }
+        ],
+        title: 'two items with ports'
+      },
+      {
+        prop: '\'h3\':8080',
+        gangliaCustomClusters: [
+          {
+            name: 'h3',
+            port: '8080'
+          }
+        ],
+        title: 'remove apostrophes'
+      }
+    ],
+    controller = this.subject();
+
+  cases.forEach(function (item) {
+
+    deepEqual(controller.formatGangliaClusters(item.prop), item.gangliaCustomClusters, item.title);
+
+  });
+
+});
+
+test('finishSliderConfiguration', function () {
+
+  var cases = [
+      {
+        validations: [],
+        viewEnabled: true,
+        title: 'view enabled'
+      },
+      {
+        validations: [{}, {}],
+        viewEnabled: false,
+        title: 'view disabled'
+      }
+    ],
+    controller = this.subject();
+
+  cases.forEach(function (item) {
+
+    Em.run(function () {
+      controller.finishSliderConfiguration({
+        validations: item.validations
+      });
+    });
+
+    equal(App.get('viewEnabled'), item.viewEnabled, item.title);
+
+  });
+
+});

+ 1 - 3
contrib/views/slider/src/main/resources/ui/test/unit/views/slider_apps_view_test.js → contrib/views/slider/src/main/resources/ui/test/unit/views/common/table_view_test.js

@@ -16,9 +16,7 @@
  * limitations under the License.
  */
 
-moduleFor('view:SliderApps', 'App.SliderAppsView', {
-  needs: ['controller:SliderApps']
-});
+moduleFor('view:table', 'App.TableView');
 
 test('clearFilters', function () {