Repository: ambari Updated Branches: refs/heads/trunk b9aa4a80b -> 65b11d50c
AMBARI-6000. Add unit tests for mirroring controllers/views. (akovalenko) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/65b11d50 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/65b11d50 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/65b11d50 Branch: refs/heads/trunk Commit: 65b11d50c18ae5099a1e66116ba153229b4fc0f1 Parents: b9aa4a8 Author: Aleksandr Kovalenko <[email protected]> Authored: Tue Jun 3 14:36:39 2014 +0300 Committer: Aleksandr Kovalenko <[email protected]> Committed: Tue Jun 3 14:36:39 2014 +0300 ---------------------------------------------------------------------- ambari-web/app/assets/test/tests.js | 2 + .../main/mirroring/edit_dataset_controller.js | 159 +++++-- .../mirroring/manage_clusters_controller.js | 5 - ambari-web/app/utils/ajax/ajax.js | 2 +- .../views/main/mirroring/edit_dataset_view.js | 17 +- .../mirroring/edit_dataset_controller_test.js | 420 +++++++++++++++++++ .../main/mirroring/edit_dataset_view_test.js | 243 +++++++++++ 7 files changed, 798 insertions(+), 50 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/65b11d50/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 fc64341..8132f29 100644 --- a/ambari-web/app/assets/test/tests.js +++ b/ambari-web/app/assets/test/tests.js @@ -76,6 +76,7 @@ require('test/controllers/main/jobs/hive_job_details_controller_test'); require('test/controllers/main/service_test'); require('test/controllers/main/admin_test'); require('test/controllers/main/alerts_controller_test'); +require('test/controllers/main/mirroring/edit_dataset_controller_test'); require('test/controllers/installer_test'); require('test/controllers/wizard_test'); require('test/controllers/wizard/step0_test'); @@ -158,6 +159,7 @@ require('test/views/main/jobs/hive_job_details_view_test'); require('test/views/main/charts/heatmap/heatmap_host_test'); require('test/views/main/charts/heatmap/heatmap_rack_test'); require('test/views/main/service/info/config_test'); +require('test/views/main/mirroring/edit_dataset_view_test'); require('test/views/common/configs/services_config_test'); require('test/views/wizard/step3/hostLogPopupBody_view_test'); require('test/views/wizard/step3/hostWarningPopupBody_view_test'); http://git-wip-us.apache.org/repos/asf/ambari/blob/65b11d50/ambari-web/app/controllers/main/mirroring/edit_dataset_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/mirroring/edit_dataset_controller.js b/ambari-web/app/controllers/main/mirroring/edit_dataset_controller.js index 36f74b4..844a47d 100644 --- a/ambari-web/app/controllers/main/mirroring/edit_dataset_controller.js +++ b/ambari-web/app/controllers/main/mirroring/edit_dataset_controller.js @@ -19,11 +19,22 @@ App.MainMirroringEditDataSetController = Ember.Controller.extend({ name: 'mainMirroringEditDataSetController', + /** + * Defines to show Edit Dataset or Create New Dataset popup + * @type {Boolean} + */ isEdit: false, + /** + * Contains Dataset id if <code>isEdit</code> is true + * @type {Boolean} + */ datasetIdToEdit: null, - // Fields values from Edit DataSet form + /** + * Fields values from Edit DataSet form + * @type {Object} + */ formFields: Ember.Object.create({ datasetName: null, datasetTargetClusterName: null, @@ -41,7 +52,10 @@ App.MainMirroringEditDataSetController = Ember.Controller.extend({ repeatOptionSelected: null }), - // Messages for errors occurred during Edit DataSet form validation + /** + * Messages for errors occurred during Edit DataSet form validation + * @type {Object} + */ errorMessages: Ember.Object.create({ name: '', sourceDir: '', @@ -52,6 +66,10 @@ App.MainMirroringEditDataSetController = Ember.Controller.extend({ targetClusterName: '' }), + /** + * Flags with errors related to each field in Edit/Create Dataset form + * @type {Object} + */ errors: Ember.Object.create({ isNameError: false, isSourceDirError: false, @@ -62,6 +80,9 @@ App.MainMirroringEditDataSetController = Ember.Controller.extend({ isTargetClusterNameError: false }), + /** + * Clear all fields in Edit/Create Dataset form and clears all errors + */ clearStep: function () { var formFields = this.get('formFields'); Em.keys(formFields).forEach(function (key) { @@ -70,6 +91,9 @@ App.MainMirroringEditDataSetController = Ember.Controller.extend({ this.clearErrors(); }, + /** + * Clear all error flags and messages + */ clearErrors: function () { var errorMessages = this.get('errorMessages'); Em.keys(errorMessages).forEach(function (key) { @@ -81,17 +105,31 @@ App.MainMirroringEditDataSetController = Ember.Controller.extend({ }, this); }, + /** + * Show Create New Dataset popup + * @return {Object} popup view + */ showAddPopup: function () { - this.showPopup(Em.I18n.t('mirroring.dataset.newDataset')); + var popup = this.showPopup(Em.I18n.t('mirroring.dataset.newDataset')); this.set('isEdit', false); + return popup; }, + /** + * Show Edit Dataset popup + * @return {Object} popup view + */ showEditPopup: function (dataset) { this.set('datasetIdToEdit', dataset.get('id')); - this.showPopup(Em.I18n.t('mirroring.dataset.editDataset')); + var popup = this.showPopup(Em.I18n.t('mirroring.dataset.editDataset')); this.set('isEdit', true); + return popup; }, + /** + * Show popup with Dataset form fields + * @return {Object} popup view + */ showPopup: function (header) { var self = this; var popup = App.ModalPopup.show({ @@ -129,9 +167,12 @@ App.MainMirroringEditDataSetController = Ember.Controller.extend({ }) }); this.set('popup', popup); + return popup; }, - // Set observer to call validate method if any property from formFields will change + /** + * Set observer to call validate method if any property from formFields will change + */ applyValidation: function () { Em.keys(this.get('formFields')).forEach(function (key) { this.addObserver('formFields.' + key, this, 'validate'); @@ -139,7 +180,10 @@ App.MainMirroringEditDataSetController = Ember.Controller.extend({ this.validate(); }, - // Return date object calculated from appropriate fields + /** + * Return date object calculated from appropriate fields + * @type {Date} + */ scheduleStartDate: function () { var startDate = this.get('formFields.datasetStartDate'); var hoursForStart = this.get('formFields.hoursForStart'); @@ -151,7 +195,10 @@ App.MainMirroringEditDataSetController = Ember.Controller.extend({ return null; }.property('formFields.datasetStartDate', 'formFields.hoursForStart', 'formFields.minutesForStart', 'formFields.middayPeriodForStart'), - // Return date object calculated from appropriate fields + /** + * Return date object calculated from appropriate fields + * @type {Date} + */ scheduleEndDate: function () { var endDate = this.get('formFields.datasetEndDate'); var hoursForEnd = this.get('formFields.hoursForEnd'); @@ -164,7 +211,9 @@ App.MainMirroringEditDataSetController = Ember.Controller.extend({ }.property('formFields.datasetEndDate', 'formFields.hoursForEnd', 'formFields.minutesForEnd', 'formFields.middayPeriodForEnd'), - // Validation for every field in Edit DataSet form + /** + * Validation for every field in Edit DataSet form + */ validate: function () { var formFields = this.get('formFields'); var errors = this.get('errors'); @@ -185,7 +234,7 @@ App.MainMirroringEditDataSetController = Ember.Controller.extend({ errorMessages.set('endDate', Em.I18n.t('mirroring.dateOrder.error')); } // Check that startDate is after current date - if (!this.get('isEdit') && new Date(App.dateTime()) > scheduleStartDate) { + if (scheduleStartDate && !this.get('isEdit') && new Date(App.dateTime()) > scheduleStartDate) { errors.set('isStartDateError', true); errorMessages.set('startDate', Em.I18n.t('mirroring.startDate.error')); } @@ -196,25 +245,50 @@ App.MainMirroringEditDataSetController = Ember.Controller.extend({ } }, - // Add '0' for numbers less than 10 + + /** + * Add '0' for numbers less than 10 + * @param {Number|String} number + * @return {String} + */ addZero: function (number) { return ('0' + number).slice(-2); }, - // Convert date to TZ format + /** + * Convert date to TZ format + * @param {Date} date + * @return {String} + */ toTZFormat: function (date) { return date.toISOString().replace(/\:\d{2}\.\d{3}/,''); }, - // Converts hours value from 24-hours format to AM/PM format + /** + * Converts hours value from 24-hours format to AM/PM format + * @param {Number|String} hours + * @return {String} + */ toAMPMHours: function (hours) { var result = hours % 12; result = result ? result : 12; return this.addZero(result); }, + /** + * Save data from dataset form to server + */ save: function () { this.set('popup.isSaving', true); + var datasetXML = this.createDatasetXML(); + this.sendDatasetToServer(datasetXML); + }, + + /** + * Compose XML-object from populated dataset form fields + * @return {String} + */ + createDatasetXML: function () { var datasetNamePrefix = App.mirroringDatasetNamePrefix; var datasetName = this.get('formFields.datasetName'); var prefixedDatasetName = datasetNamePrefix + datasetName; @@ -229,46 +303,47 @@ App.MainMirroringEditDataSetController = Ember.Controller.extend({ var scheduleStartDateFormatted = this.toTZFormat(startDate); var scheduleEndDateFormatted = this.toTZFormat(endDate); - // Compose XML data, that will be sended to server - var dataToSend = '<?xml version="1.0"?><feed description="" name="' + prefixedDatasetName + '" xmlns="uri:falcon:feed:0.1"><frequency>' + repeatOptionSelected + '(' + datasetFrequency + ')' + + return '<?xml version="1.0"?><feed description="" name="' + prefixedDatasetName + '" xmlns="uri:falcon:feed:0.1"><frequency>' + repeatOptionSelected + '(' + datasetFrequency + ')' + '</frequency><clusters><cluster name="' + sourceCluster + '" type="source"><validity start="' + scheduleStartDateFormatted + '" end="' + scheduleEndDateFormatted + '"/><retention limit="days(7)" action="delete"/></cluster><cluster name="' + targetCluster + '" type="target"><validity start="' + scheduleStartDateFormatted + '" end="' + scheduleEndDateFormatted + '"/><retention limit="months(1)" action="delete"/><locations><location type="data" path="' + targetDir + '" /></locations></cluster></clusters><locations><location type="data" path="' + sourceDir + '" /></locations><ACL owner="hue" group="users" permission="0755" /><schema location="/none" provider="none"/></feed>'; - if (this.get('isEdit')) { - App.ajax.send({ - name: 'mirroring.update_entity', - sender: this, - data: { - name: prefixedDatasetName, - type: 'feed', - entity: dataToSend, - falconServer: App.get('falconServerURL') - }, - success: 'onSaveSuccess', - error: 'onSaveError' - }); - } else { - // Send request to server to create dataset - App.ajax.send({ - name: 'mirroring.create_new_dataset', - sender: this, - data: { - dataset: dataToSend, - falconServer: App.get('falconServerURL') - }, - success: 'onSaveSuccess', - error: 'onSaveError' - }); - } }, + /** + * Send dataset XML-data to server + * @param {String} datasetXML + */ + sendDatasetToServer: function (datasetXML) { + var datasetNamePrefix = App.mirroringDatasetNamePrefix; + var datasetName = this.get('formFields.datasetName'); + var prefixedDatasetName = datasetNamePrefix + datasetName; + return App.ajax.send({ + name: this.get('isEdit') ? 'mirroring.update_entity' : 'mirroring.create_new_dataset', + sender: this, + data: { + name: prefixedDatasetName, + type: 'feed', + entity: datasetXML, + falconServer: App.get('falconServerURL') + }, + success: 'onSaveSuccess', + error: 'onSaveError' + }); + }, + + /** + * Callback for success saving XML-data on server + */ onSaveSuccess: function () { this.set('popup.isSaving', false); this.get('popup').hide(); App.router.get('mainMirroringController').loadData(); }, + /** + * Callback for error while saving XML-data on server + */ onSaveError: function (response) { this.set('popup.isSaving', false); if (response && response.responseText) { @@ -279,6 +354,10 @@ App.MainMirroringEditDataSetController = Ember.Controller.extend({ } }, + /** + * Defines if save button should be disabled + * @type {Boolean} + */ saveDisabled: function () { var errors = this.get('errors'); return errors.get('isNameError') || errors.get('isSourceDirError') || errors.get('isTargetDirError') || errors.get('isStartDateError') || errors.get('isEndDateError') || errors.get('isFrequencyError') || errors.get('isTargetClusterNameError'); http://git-wip-us.apache.org/repos/asf/ambari/blob/65b11d50/ambari-web/app/controllers/main/mirroring/manage_clusters_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/mirroring/manage_clusters_controller.js b/ambari-web/app/controllers/main/mirroring/manage_clusters_controller.js index 9eb01aa..c069915 100644 --- a/ambari-web/app/controllers/main/mirroring/manage_clusters_controller.js +++ b/ambari-web/app/controllers/main/mirroring/manage_clusters_controller.js @@ -64,11 +64,6 @@ App.MainMirroringManageClustersController = Em.ArrayController.extend({ selectedCluster: null, - // Disable input fields for already created clusters - isEditDisabled: function () { - return !this.get('clustersToCreate').mapProperty('name').contains(this.get('selectedCluster.name')); - }.property('selectedCluster.name', '[email protected]'), - addCluster: function () { var self = this; var newClusterPopup = App.ModalPopup.show({ http://git-wip-us.apache.org/repos/asf/ambari/blob/65b11d50/ambari-web/app/utils/ajax/ajax.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/ajax/ajax.js b/ambari-web/app/utils/ajax/ajax.js index 19b63c5..26b2de0 100644 --- a/ambari-web/app/utils/ajax/ajax.js +++ b/ambari-web/app/utils/ajax/ajax.js @@ -1841,7 +1841,7 @@ var urls = { return { contentType: 'text/xml', dataType: 'xml', - data: data.dataset, + data: data.entity, headers: { 'AmbariProxy-Content-Type': 'text/xml' } http://git-wip-us.apache.org/repos/asf/ambari/blob/65b11d50/ambari-web/app/views/main/mirroring/edit_dataset_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/main/mirroring/edit_dataset_view.js b/ambari-web/app/views/main/mirroring/edit_dataset_view.js index b50b858..519d643 100644 --- a/ambari-web/app/views/main/mirroring/edit_dataset_view.js +++ b/ambari-web/app/views/main/mirroring/edit_dataset_view.js @@ -17,14 +17,17 @@ */ var App = require('app'); -var filters = require('views/common/filter_view'); -var sort = require('views/common/sort_view'); -var date = require('utils/date'); App.MainMirroringEditDataSetView = Em.View.extend({ + name: 'mainMirroringEditDataSetView', + templateName: require('templates/main/mirroring/edit_dataset'), + /** + * Defines if there are some target clusters defined + * @type {Boolean} + */ hasTargetClusters: false, targetClusters: App.TargetCluster.find(), @@ -46,6 +49,9 @@ App.MainMirroringEditDataSetView = Em.View.extend({ } }), + /** + * Set <code>hasTargetClusters</code> after clustes load + */ onTargetClustersChange: function () { if (this.get('isLoaded') && this.get('targetClusters.length') > 1) { this.set('hasTargetClusters', true); @@ -71,9 +77,12 @@ App.MainMirroringEditDataSetView = Em.View.extend({ App.router.get('mainMirroringController').manageClusters(); }, + /** + * Fill form input fields for selected dataset to edit + */ fillForm: function () { var isEdit = this.get('controller.isEdit'); - if (this.get('isLoaded') && isEdit) { + if (this.get('isLoaded') && isEdit) { var controller = this.get('controller'); var dataset = App.Dataset.find().findProperty('id', controller.get('datasetIdToEdit')); var scheduleStartDate = new Date(dataset.get('scheduleStartDate')); http://git-wip-us.apache.org/repos/asf/ambari/blob/65b11d50/ambari-web/test/controllers/main/mirroring/edit_dataset_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/mirroring/edit_dataset_controller_test.js b/ambari-web/test/controllers/main/mirroring/edit_dataset_controller_test.js new file mode 100644 index 0000000..f898e1f --- /dev/null +++ b/ambari-web/test/controllers/main/mirroring/edit_dataset_controller_test.js @@ -0,0 +1,420 @@ +/** + * 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('controllers/main/mirroring/edit_dataset_controller'); +require('models/target_cluster'); +require('views/main/mirroring/edit_dataset_view'); + +describe('App.MainMirroringEditDataSetController', function () { + + describe('#clearStep', function () { + it('should clear all fields, error flags and messages', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create(); + var errors = mainMirroringEditDataSetController.get('errors'); + var errorMessages = mainMirroringEditDataSetController.get('errorMessages'); + var formFeilds = mainMirroringEditDataSetController.get('formFields'); + formFeilds.set('datasetName', 'test'); + sinon.spy(mainMirroringEditDataSetController, 'clearErrors'); + mainMirroringEditDataSetController.clearStep(); + expect(mainMirroringEditDataSetController.clearErrors.calledOnce).to.be.true; + Em.keys(formFeilds).forEach(function (field) { + expect(formFeilds[field]).to.be.null; + }); + mainMirroringEditDataSetController.clearErrors.restore(); + }); + }); + + describe('#clearErrors', function () { + it('should clear all error messages and flags', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create(); + var errors = mainMirroringEditDataSetController.get('errors'); + var errorMessages = mainMirroringEditDataSetController.get('errorMessages'); + Em.keys(errors).forEach(function (error) { + errors[error] = true; + }, this); + Em.keys(errorMessages).forEach(function (errorMessage) { + errorMessages[errorMessage] = 'test'; + }, this); + mainMirroringEditDataSetController.clearErrors(); + Em.keys(errors).forEach(function (error) { + expect(errors[error]).to.be.false; + }); + Em.keys(errorMessages).forEach(function (errorMessage) { + expect(errorMessages[errorMessage]).to.be.empty; + }); + }); + }); + + describe('#showAddPopup', function () { + it('should show popup and set isEdit as false', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create(); + sinon.spy(App.ModalPopup, 'show'); + mainMirroringEditDataSetController.showAddPopup(); + expect(App.ModalPopup.show.calledOnce).to.be.true; + expect(mainMirroringEditDataSetController.get('isEdit')).to.be.false; + App.ModalPopup.show.restore(); + }); + }); + + describe('#showEditPopup', function () { + it('should show popup,set isEdit as true and set dataset id', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create(); + var dataset = Ember.Object.create({ + id: 'test' + }); + sinon.spy(App.ModalPopup, 'show'); + mainMirroringEditDataSetController.showEditPopup(dataset); + expect(App.ModalPopup.show.calledOnce).to.equal(true); + expect(mainMirroringEditDataSetController.get('isEdit')).to.be.true; + expect(mainMirroringEditDataSetController.get('datasetIdToEdit')).to.equal('test'); + App.ModalPopup.show.restore(); + }); + }); + + describe('#showPopup', function () { + it('should show dataset popup and save its view', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create(); + sinon.spy(App.ModalPopup, 'show'); + mainMirroringEditDataSetController.showPopup(); + expect(App.ModalPopup.show.calledOnce).to.equal(true); + expect(mainMirroringEditDataSetController.get('popup')).to.not.be.empty; + App.ModalPopup.show.restore(); + }); + }); + + describe('#applyValidation', function () { + it('should add observers to all fields to validate form', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create(); + sinon.spy(mainMirroringEditDataSetController, 'validate'); + mainMirroringEditDataSetController.applyValidation(); + expect(mainMirroringEditDataSetController.validate.calledOnce).to.be.true; + Em.keys(mainMirroringEditDataSetController.get('formFields')).forEach(function (field) { + expect(mainMirroringEditDataSetController.hasObserverFor('formFields.' + field)).to.be.true; + }); + mainMirroringEditDataSetController.validate.restore(); + }); + }); + + var testCases = [ + { + day: '01/01/2001', + hours: '00', + minutes: '00', + middayPeriod: 'AM', + result: new Date('01/01/2001 00:00 AM'), + message: 'should return date object' + }, + { + day: '06/05/2014', + hours: '12', + minutes: '59', + middayPeriod: 'PM', + result: new Date('06/05/2014 12:59 PM'), + message: 'should return date object' + }, + { + day: '', + hours: '00', + minutes: '00', + middayPeriod: 'AM', + result: null, + message: 'should return null if there are empty fields' + } + ]; + + describe('#scheduleStartDate', function () { + testCases.forEach(function (test) { + it(test.message, function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create({ + formFields: Ember.Object.create({ + datasetStartDate: test.day, + hoursForStart: test.hours, + minutesForStart: test.minutes, + middayPeriodForStart: test.middayPeriod + }) + }); + expect(mainMirroringEditDataSetController.get('scheduleStartDate')).to.deep.equal(test.result); + }); + }); + }); + + describe('#scheduleEndDate', function () { + testCases.forEach(function (test) { + it(test.message, function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create({ + formFields: Ember.Object.create({ + datasetEndDate: test.day, + hoursForEnd: test.hours, + minutesForEnd: test.minutes, + middayPeriodForEnd: test.middayPeriod + }) + }); + expect(mainMirroringEditDataSetController.get('scheduleEndDate')).to.deep.equal(test.result); + }); + }); + }); + + var formFields = Ember.Object.create({ + datasetName: 'test', + datasetTargetClusterName: 'test', + datasetSourceDir: '/test', + datasetTargetDir: '/test', + datasetStartDate: '01/19/2038', + hoursForStart: '03', + minutesForStart: '15', + middayPeriodForStart: 'AM', + datasetEndDate: '01/19/2039', + hoursForEnd: '03', + minutesForEnd: '15', + middayPeriodForEnd: 'AM', + datasetFrequency: '1', + repeatOptionSelected: 'days' + }) + + describe('#validate', function () { + it('should set an error for empty fields', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create(); + mainMirroringEditDataSetController.validate(); + var errors = mainMirroringEditDataSetController.get('errors'); + var errorMessages = mainMirroringEditDataSetController.get('errorMessages'); + Em.keys(errors).forEach(function (error) { + expect(errors[error]).to.be.true; + }); + Em.keys(errorMessages).forEach(function (errorMessage) { + expect(errorMessages[errorMessage]).to.equal(Em.I18n.t('mirroring.required.error')); + }); + }); + it('should set an error if start date is after end date', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create(); + var formFields = mainMirroringEditDataSetController.get('formFields'); + formFields.set('datasetStartDate', '04/07/2014'); + formFields.set('hoursForStart', '11'); + formFields.set('minutesForStart', '00'); + formFields.set('middayPeriodForStart', 'PM'); + formFields.set('datasetEndDate', '04/07/2014'); + formFields.set('hoursForEnd', '11'); + formFields.set('minutesForEnd', '00'); + formFields.set('middayPeriodForEnd', 'AM'); + mainMirroringEditDataSetController.validate(); + expect(mainMirroringEditDataSetController.get('errors.isEndDateError')).to.be.true; + expect(mainMirroringEditDataSetController.get('errorMessages.endDate')).to.equal(Em.I18n.t('mirroring.dateOrder.error')); + }); + it('should set an error if start date is in the past', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create(); + var formFields = mainMirroringEditDataSetController.get('formFields'); + formFields.set('datasetStartDate', '04/07/2014'); + formFields.set('hoursForStart', '11'); + formFields.set('minutesForStart', '00'); + formFields.set('middayPeriodForStart', 'AM'); + mainMirroringEditDataSetController.validate(); + expect(mainMirroringEditDataSetController.get('errors.isStartDateError')).to.be.true; + expect(mainMirroringEditDataSetController.get('errorMessages.startDate')).to.equal(Em.I18n.t('mirroring.startDate.error')); + }); + it('should set an error if repeat field value consist not only form digits', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create(); + var formFields = mainMirroringEditDataSetController.get('formFields'); + formFields.set('datasetFrequency', 'test'); + mainMirroringEditDataSetController.validate(); + expect(mainMirroringEditDataSetController.get('errors.isFrequencyError')).to.be.true; + expect(mainMirroringEditDataSetController.get('errorMessages.frequency')).to.equal(Em.I18n.t('mirroring.required.invalidNumberError')); + formFields.set('datasetFrequency', '100test'); + mainMirroringEditDataSetController.validate(); + expect(mainMirroringEditDataSetController.get('errors.isFrequencyError')).to.be.true; + expect(mainMirroringEditDataSetController.get('errorMessages.frequency')).to.equal(Em.I18n.t('mirroring.required.invalidNumberError')); + }); + it('should not set errors if all fields are filled correctly', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create({ + formFields: formFields + }); + mainMirroringEditDataSetController.validate(); + var errors = mainMirroringEditDataSetController.get('errors'); + var errorMessages = mainMirroringEditDataSetController.get('errorMessages'); + Em.keys(errors).forEach(function (error) { + expect(errors[error]).to.be.false; + }); + Em.keys(errorMessages).forEach(function (errorMessage) { + expect(errorMessages[errorMessage]).to.be.empty; + }); + }); + }); + + describe('#addZero', function () { + it('should add 0 for numbers less than 10', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create(); + expect(mainMirroringEditDataSetController.addZero(1)).to.equal('01'); + expect(mainMirroringEditDataSetController.addZero(9)).to.equal('09'); + expect(mainMirroringEditDataSetController.addZero(0)).to.equal('00'); + }); + it('should not add 0 for numbers greater than 9', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create(); + expect(mainMirroringEditDataSetController.addZero(10)).to.equal('10'); + expect(mainMirroringEditDataSetController.addZero(99)).to.equal('99'); + }); + }); + + describe('#toTZFormat', function () { + it('should convert date to TZ format', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create(); + expect(mainMirroringEditDataSetController.toTZFormat(new Date(Date.UTC(2014, 0, 1, 1, 1)))).to.equal('2014-01-01T01:01Z'); + expect(mainMirroringEditDataSetController.toTZFormat(new Date(Date.UTC(2014, 11, 31, 23, 59)))).to.equal('2014-12-31T23:59Z'); + }); + }); + + describe('#toAMPMHours', function () { + it('should convert time to 12-hours format', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create(); + expect(mainMirroringEditDataSetController.toAMPMHours(13)).to.equal('01'); + expect(mainMirroringEditDataSetController.toAMPMHours(20)).to.equal('08'); + expect(mainMirroringEditDataSetController.toAMPMHours(24)).to.equal('12'); + expect(mainMirroringEditDataSetController.toAMPMHours(0)).to.equal('12'); + }); + it('should not convert time if argument is less than 12', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create(); + expect(mainMirroringEditDataSetController.toAMPMHours(1)).to.equal('01'); + expect(mainMirroringEditDataSetController.toAMPMHours(8)).to.equal('08'); + expect(mainMirroringEditDataSetController.toAMPMHours(11)).to.equal('11'); + }); + }); + + describe('#save', function () { + it('should create XML and send it to server', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create({ + popup: Ember.Object.create({ + isSaving: false + }) + }); + sinon.spy(mainMirroringEditDataSetController, 'createDatasetXML'); + sinon.spy(mainMirroringEditDataSetController, 'sendDatasetToServer'); + mainMirroringEditDataSetController.save(); + expect(mainMirroringEditDataSetController.createDatasetXML.calledOnce).to.be.true; + expect(mainMirroringEditDataSetController.sendDatasetToServer.calledOnce).to.be.true; + expect(mainMirroringEditDataSetController.get('popup.isSaving')).to.be.true; + mainMirroringEditDataSetController.createDatasetXML.restore(); + mainMirroringEditDataSetController.sendDatasetToServer.restore(); + }); + }); + + describe('#createDatasetXML', function () { + it('should create XML-fromatted data', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create({ + formFields: formFields + }); + var startDate = new Date('01/19/2038 03:15 AM').toISOString().replace(/\:\d{2}\.\d{3}/, ''); + var endDate = new Date('01/19/2039 03:15 AM').toISOString().replace(/\:\d{2}\.\d{3}/, ''); + var expectedResult = '<?xml version="1.0"?><feed description="" name="' + App.mirroringDatasetNamePrefix + 'test" xmlns="uri:falcon:feed:0.1"><frequency>days(1)' + + '</frequency><clusters><cluster name="' + App.get('clusterName') + '" type="source"><validity start="' + startDate + '" end="' + endDate + + '"/><retention limit="days(7)" action="delete"/></cluster><cluster name="test" type="target"><validity start="' + startDate + '" end="' + endDate + + '"/><retention limit="months(1)" action="delete"/><locations><location type="data" path="/test" /></locations></cluster></clusters><locations><location type="data" path="' + + '/test" /></locations><ACL owner="hue" group="users" permission="0755" /><schema location="/none" provider="none"/></feed>'; + var result = mainMirroringEditDataSetController.createDatasetXML(); + expect(result).to.equal(expectedResult); + }); + }); + + describe('#sendDatasetToServer', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create({ + formFields: formFields + }); + beforeEach(function () { + sinon.stub(App.ajax, 'send', Em.K); + }); + afterEach(function () { + App.ajax.send.restore(); + }); + it('should send data with correct dataset name', function () { + mainMirroringEditDataSetController.sendDatasetToServer('test'); + expect(App.ajax.send.args[0][0].data.name).to.equal(App.mirroringDatasetNamePrefix + formFields.datasetName); + }); + it('should send data from param', function () { + mainMirroringEditDataSetController.sendDatasetToServer('test'); + expect(App.ajax.send.args[0][0].data.entity).to.equal('test'); + }); + it('should use edit request if isEdit is true', function () { + mainMirroringEditDataSetController.set('isEdit', true); + mainMirroringEditDataSetController.sendDatasetToServer('test'); + expect(App.ajax.send.args[0][0].name).to.equal('mirroring.update_entity'); + }); + it('should use create request if isEdit is false', function () { + mainMirroringEditDataSetController.set('isEdit', false); + mainMirroringEditDataSetController.sendDatasetToServer('test'); + expect(App.ajax.send.args[0][0].name).to.equal('mirroring.create_new_dataset'); + }); + }); + + describe('#onSaveSuccess', function () { + it('should hide popup and load data', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create({ + popup: Ember.Object.create({ + isSaving: true, + hide: function () { + } + }) + }); + App.router.set('mainMirroringController', Ember.Object.create({ + loadData: function () { + } + })); + sinon.spy(mainMirroringEditDataSetController.get('popup'), 'hide'); + sinon.spy(App.router.get('mainMirroringController'), 'loadData'); + mainMirroringEditDataSetController.onSaveSuccess(); + expect(mainMirroringEditDataSetController.get('popup.isSaving')).to.be.false; + expect(App.router.get('mainMirroringController').loadData.calledOnce).to.be.true; + expect(mainMirroringEditDataSetController.get('popup').hide.calledOnce).to.be.true; + mainMirroringEditDataSetController.get('popup').hide.restore(); + App.router.get('mainMirroringController').loadData.restore(); + }); + }); + + describe('#onSaveError', function () { + var mainMirroringEditDataSetController; + beforeEach(function () { + mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create({ + popup: Ember.Object.create({ + isSaving: true + }) + }); + sinon.stub(App, 'showAlertPopup', Em.K); + }); + afterEach(function () { + App.showAlertPopup.restore(); + }); + it('shouldn\'t show error popup and enable button', function () { + mainMirroringEditDataSetController.onSaveError(null); + expect(App.showAlertPopup.calledOnce).to.be.false; + expect(mainMirroringEditDataSetController.get('popup.isSaving')).to.be.false; + }); + it('should show error popup and enable button', function () { + mainMirroringEditDataSetController.onSaveError({responseText: '<message>test</message>'}); + expect(App.showAlertPopup.args[0][1]).to.be.equal(Em.I18n.t('mirroring.manageClusters.error') + ': test'); + expect(mainMirroringEditDataSetController.get('popup.isSaving')).to.be.false; + }); + }); + + describe('#saveDisabled', function () { + it('should return false if there are no errors', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create({}); + expect(mainMirroringEditDataSetController.get('saveDisabled')).to.be.false; + }); + it('should return true if there are some errors', function () { + var mainMirroringEditDataSetController = App.MainMirroringEditDataSetController.create(); + mainMirroringEditDataSetController.set('errors.isNameError', true); + expect(mainMirroringEditDataSetController.get('saveDisabled')).to.be.true; + }); + }); +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/65b11d50/ambari-web/test/views/main/mirroring/edit_dataset_view_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/views/main/mirroring/edit_dataset_view_test.js b/ambari-web/test/views/main/mirroring/edit_dataset_view_test.js new file mode 100644 index 0000000..d5b34d1 --- /dev/null +++ b/ambari-web/test/views/main/mirroring/edit_dataset_view_test.js @@ -0,0 +1,243 @@ +/** + * 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('controllers/main/mirroring/edit_dataset_controller'); +require('models/target_cluster'); +require('views/main/mirroring/edit_dataset_view'); + +var mainMirroringEditDataSetView; +describe('App.MainMirroringEditDataSetView', function () { + + beforeEach(function () { + mainMirroringEditDataSetView = App.MainMirroringEditDataSetView.create({ + controller: App.MainMirroringEditDataSetController.create(), + isLoaded: true + }); + }); + + describe('targetClusterSelect.content', function () { + var targetClusterSelect; + beforeEach(function () { + targetClusterSelect = mainMirroringEditDataSetView.get('targetClusterSelect').create({ + parentView: mainMirroringEditDataSetView + }); + }); + + it('should be empty if data is not loaded', function () { + targetClusterSelect.set('parentView.isLoaded', false); + expect(targetClusterSelect.get('content')).to.be.empty; + }); + it('should contain list of clusters if data is loaded', function () { + targetClusterSelect.set('parentView.isLoaded', true); + targetClusterSelect.set('parentView.targetClusters', [ + {name: 'test1'}, + {name: 'test2'}, + {name: App.get('clusterName')} + ]); + expect(targetClusterSelect.get('content')).to.eql([ + 'test1', + 'test2', + Em.I18n.t('mirroring.dataset.addTargetCluster') + ]); + }); + }); + + describe('targetClusterSelect.change', function () { + var targetClusterSelect; + beforeEach(function () { + targetClusterSelect = mainMirroringEditDataSetView.get('targetClusterSelect').create({ + parentView: mainMirroringEditDataSetView, + content: ['test1', 'test2', 'test3'] + }); + sinon.stub(targetClusterSelect.parentView, 'manageClusters', Em.K); + }); + + afterEach(function () { + targetClusterSelect.parentView.manageClusters.restore(); + }); + + it('should open manage cluster popup if appropriate option was selected', function () { + targetClusterSelect.set('selection', Em.I18n.t('mirroring.dataset.addTargetCluster')); + targetClusterSelect.change(); + expect(targetClusterSelect.get('selection')).to.equal('test1'); + expect(targetClusterSelect.parentView.manageClusters.calledOnce).to.be.true; + expect(targetClusterSelect.get('parentView.controller.formFields.datasetTargetClusterName')).to.equal('test1'); + }); + it('should not open manage cluster popup if appropriate option was not selected', function () { + targetClusterSelect.set('selection', 'test3'); + targetClusterSelect.change(); + expect(targetClusterSelect.get('selection')).to.equal('test3'); + expect(targetClusterSelect.parentView.manageClusters.calledOnce).to.be.false; + expect(targetClusterSelect.get('parentView.controller.formFields.datasetTargetClusterName')).to.equal('test3'); + }); + }); + + describe('onTargetClustersChange', function () { + + var testCases = [ + { + isLoaded: true, + targetClusters: [1, 2, 3], + targetClusterName: 'test', + hasTargetClusters: true + }, + { + isLoaded: false, + targetClusters: [1, 2, 3], + targetClusterName: null, + hasTargetClusters: false + }, + { + isLoaded: true, + targetClusters: [1], + targetClusterName: null, + hasTargetClusters: false + } + ]; + + testCases.forEach(function (test) { + it('should set hasTargetClusters property depending on cluster list', function () { + mainMirroringEditDataSetView.set('isLoaded', test.isLoaded); + mainMirroringEditDataSetView.set('targetClusters', test.targetClusters); + mainMirroringEditDataSetView.set('controller.formFields.datasetTargetClusterName', 'test'); + mainMirroringEditDataSetView.onTargetClustersChange(); + expect(mainMirroringEditDataSetView.get('hasTargetClusters')).to.equal(test.hasTargetClusters); + expect(mainMirroringEditDataSetView.get('controller.formFields.datasetTargetClusterName')).to.equal(test.targetClusterName); + }); + }); + }); + + describe('fillForm', function () { + + App.store.loadMany(App.Dataset, [ + { + id: 'test1', + name: 'test1', + target_cluster_name: 'testCluster1', + source_dir: '/testDir1', + target_dir: '/testDir1', + frequency: '5', + frequency_unit: 'days', + schedule_start_date: new Date('11/29/2014 01:00 AM').toISOString().replace(/\:\d{2}\.\d{3}/, ''), + schedule_end_date: new Date('11/29/2014 02:00 AM').toISOString().replace(/\:\d{2}\.\d{3}/, '') + }, + { + id: 'test2', + name: 'test2', + target_cluster_name: 'testCluster2', + source_dir: '/testDir2', + target_dir: '/testDir2', + frequency: '10', + frequency_unit: 'hours', + schedule_start_date: new Date('11/20/2014 01:00 AM').toISOString().replace(/\:\d{2}\.\d{3}/, ''), + schedule_end_date: new Date('11/21/2014 02:00 PM').toISOString().replace(/\:\d{2}\.\d{3}/, '') + }, + { + id: 'test3', + name: 'test3', + target_cluster_name: 'testCluster3', + source_dir: '/testDir3', + target_dir: '/testDir3', + frequency: '1', + frequency_unit: 'minutes', + schedule_start_date: new Date('10/29/2014 01:00 AM').toISOString().replace(/\:\d{2}\.\d{3}/, ''), + schedule_end_date: new Date('11/29/2015 02:00 AM').toISOString().replace(/\:\d{2}\.\d{3}/, '') + } + ]); + + var testCases = [ + { + datasetName: 'test1', + datasetSourceDir: '/testDir1', + datasetTargetDir: '/testDir1', + datasetTargetClusterName: 'testCluster1', + datasetFrequency: '5', + repeatOptionSelected: 'days', + datasetStartDate: '11/29/14', + datasetEndDate: '11/29/14', + hoursForStart: '01', + hoursForEnd: '02', + minutesForStart: '00', + minutesForEnd: '00', + middayPeriodForStart: 'AM', + middayPeriodForEnd: 'AM' + }, + { + datasetName: 'test2', + datasetSourceDir: '/testDir2', + datasetTargetDir: '/testDir2', + datasetTargetClusterName: 'testCluster2', + datasetFrequency: '10', + repeatOptionSelected: 'hours', + datasetStartDate: '11/20/14', + datasetEndDate: '11/21/14', + hoursForStart: '01', + hoursForEnd: '02', + minutesForStart: '00', + minutesForEnd: '00', + middayPeriodForStart: 'AM', + middayPeriodForEnd: 'PM' + }, + { + datasetName: 'test3', + datasetSourceDir: '/testDir3', + datasetTargetDir: '/testDir3', + datasetTargetClusterName: 'testCluster3', + datasetFrequency: '1', + repeatOptionSelected: 'minutes', + datasetStartDate: '10/29/14', + datasetEndDate: '11/29/15', + hoursForStart: '01', + hoursForEnd: '02', + minutesForStart: '00', + minutesForEnd: '00', + middayPeriodForStart: 'AM', + middayPeriodForEnd: 'AM' + } + ]; + + it('should not set form fields if isLoaded is false', function () { + mainMirroringEditDataSetView.set('isLoaded', false); + mainMirroringEditDataSetView.fillForm(); + Em.keys(mainMirroringEditDataSetView.get('controller.formFields')).forEach(function (field) { + expect(mainMirroringEditDataSetView.get('controller.formFields.' + field)).to.be.null; + }); + }); + + it('should not set form fields if controller.isEdit is false', function () { + mainMirroringEditDataSetView.set('controller.isEdit', false); + mainMirroringEditDataSetView.fillForm(); + Em.keys(mainMirroringEditDataSetView.get('controller.formFields')).forEach(function (field) { + expect(mainMirroringEditDataSetView.get('controller.formFields.' + field)).to.be.null; + }); + }); + + testCases.forEach(function (test) { + it('set appropriate form fields from dataset model', function () { + mainMirroringEditDataSetView.set('controller.datasetIdToEdit', test.datasetName); + mainMirroringEditDataSetView.set('controller.isEdit', true); + mainMirroringEditDataSetView.fillForm(); + Em.keys(mainMirroringEditDataSetView.get('controller.formFields')).forEach(function (field) { + expect(mainMirroringEditDataSetView.get('controller.formFields.' + field)).to.equal(test[field]); + }); + }); + }); + }); +});
