You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ak...@apache.org on 2014/05/20 14:21:34 UTC
[1/4] git commit: AMBARI-5820. Add unit tests for mixins. (Max Shepel
via akovalenko)
Repository: ambari
Updated Branches:
refs/heads/trunk 07193440d -> 82ffda436
AMBARI-5820. Add unit tests for mixins. (Max Shepel via akovalenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/de909721
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/de909721
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/de909721
Branch: refs/heads/trunk
Commit: de9097218a6bdb9509bfe2f25c2436cb99b03def
Parents: 0719344
Author: Aleksandr Kovalenko <ak...@hortonworks.com>
Authored: Tue May 20 15:01:56 2014 +0300
Committer: Aleksandr Kovalenko <ak...@hortonworks.com>
Committed: Tue May 20 15:01:56 2014 +0300
----------------------------------------------------------------------
ambari-web/app/assets/test/tests.js | 3 +
.../common/chart/storm_linear_time_test.js | 77 +++++++++++
.../test/mixins/common/localStorage_test.js | 77 +++++++++++
.../host_components/decommissionable_test.js | 131 +++++++++++++++++++
4 files changed, 288 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/de909721/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 ec8650e..d820fcd 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -97,6 +97,9 @@ require('test/mappers/runs_mapper_test');
require('test/mappers/service_mapper_test');
require('test/mappers/status_mapper_test');
require('test/mappers/users_mapper_test');
+require('test/mixins/common/chart/storm_linear_time_test');
+require('test/mixins/common/localStorage_test');
+require('test/mixins/main/host/details/host_components/decommissionable_test');
require('test/utils/configs/defaults_providers/yarn_defaults_provider_test');
require('test/utils/configs/defaults_providers/tez_defaults_provider_test');
require('test/utils/configs/defaults_providers/hive_defaults_provider_test');
http://git-wip-us.apache.org/repos/asf/ambari/blob/de909721/ambari-web/test/mixins/common/chart/storm_linear_time_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mixins/common/chart/storm_linear_time_test.js b/ambari-web/test/mixins/common/chart/storm_linear_time_test.js
new file mode 100644
index 0000000..b9bc19b
--- /dev/null
+++ b/ambari-web/test/mixins/common/chart/storm_linear_time_test.js
@@ -0,0 +1,77 @@
+/**
+ * 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('mixins/common/chart/storm_linear_time');
+
+var slt,
+ template,
+ series,
+ jsonDataFalse = {
+ metrics: {
+ id: 'metrics'
+ }
+ },
+ jsonDataTrue = {
+ metrics: {
+ storm: {
+ nimbus: {
+ name: 'nimbus'
+ }
+ }
+ }
+ };
+
+describe('App.StormLinearTimeChartMixin', function () {
+
+ beforeEach(function () {
+ slt = Em.Object.create(App.StormLinearTimeChartMixin, {
+ stormChartDefinition: [
+ {
+ field: 'name',
+ name: 'nimbus'
+ }
+ ]
+ });
+ });
+
+ describe('#getDataForAjaxRequest', function () {
+ it('should take data from stormChartDefinition', function () {
+ template = slt.getDataForAjaxRequest().metricsTemplate;
+ expect(template).to.contain('metrics');
+ expect(template).to.contain('storm');
+ expect(template).to.contain('nimbus');
+ });
+ });
+
+ describe('#transformToSeries', function () {
+ it('should be empty', function () {
+ expect(slt.transformToSeries(jsonDataFalse)).to.be.empty;
+ });
+ it('should take one element from data', function () {
+ slt.set('transformData', function (data, name) {
+ return name + ': ' + JSON.stringify(data);
+ });
+ series = slt.transformToSeries(jsonDataTrue);
+ expect(series).to.have.length(1);
+ expect(series[0]).to.equal('nimbus: "nimbus"');
+ });
+ });
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/de909721/ambari-web/test/mixins/common/localStorage_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mixins/common/localStorage_test.js b/ambari-web/test/mixins/common/localStorage_test.js
new file mode 100644
index 0000000..e96f1fb
--- /dev/null
+++ b/ambari-web/test/mixins/common/localStorage_test.js
@@ -0,0 +1,77 @@
+/**
+ * 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('mixins/common/localStorage');
+
+var localStorage,
+ nameCases = [
+ {
+ toSet: {
+ name: 'name'
+ },
+ toExpect: 'Name'
+ },
+ {
+ toSet: {
+ name: null,
+ controller: {
+ name: 'samplecontroller'
+ }
+ },
+ toExpect: 'Samplecontroller'
+ },
+ {
+ toSet: {
+ controller: {
+ name: 'sampleController'
+ }
+ },
+ toExpect: 'Sample'
+ }
+ ];
+
+describe('App.LocalStorage', function () {
+
+ beforeEach(function () {
+ localStorage = Em.Object.create(App.LocalStorage);
+ });
+
+ after(function () {
+ App.db.cleanUp();
+ });
+
+ describe('#dbNamespace', function () {
+ nameCases.forEach(function (item) {
+ it('should be ' + item.toExpect, function () {
+ localStorage.setProperties(item.toSet);
+ expect(localStorage.get('dbNamespace')).to.equal(item.toExpect)
+ });
+ });
+ });
+
+ describe('#getDBProperty', function () {
+ it('should take value from DB', function () {
+ localStorage.set('name', 'name');
+ localStorage.setDBProperty('key', 'value');
+ expect(localStorage.getDBProperty('key')).to.equal('value');
+ });
+ });
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/de909721/ambari-web/test/mixins/main/host/details/host_components/decommissionable_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mixins/main/host/details/host_components/decommissionable_test.js b/ambari-web/test/mixins/main/host/details/host_components/decommissionable_test.js
new file mode 100644
index 0000000..c175dad
--- /dev/null
+++ b/ambari-web/test/mixins/main/host/details/host_components/decommissionable_test.js
@@ -0,0 +1,131 @@
+/**
+ * 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('mixins/main/host/details/host_components/decommissionable');
+
+var decommissionable,
+ view,
+ statusCases = [
+ {
+ status: App.HostComponentStatus.started,
+ expected: false
+ },
+ {
+ status: 'status',
+ expected: true
+ }
+ ],
+ responseCases = [
+ {
+ HostRoles: {
+ desired_admin_state: 'state'
+ },
+ ServiceComponentInfo: 'info'
+ },
+ {
+ HostRoles: {
+ desired_admin_state: null
+ },
+ ServiceComponentInfo: null
+ }
+ ],
+ textCases = [
+ {
+ available: true,
+ text: Em.I18n.t('common.decommission')
+ },
+ {
+ available: false,
+ text: Em.I18n.t('common.recommission')
+ }
+ ];
+
+describe('App.Decommissionable', function () {
+
+ beforeEach(function () {
+ decommissionable = Em.Object.create(App.Decommissionable);
+ });
+
+ describe('#isComponentDecommissionDisable', function () {
+ statusCases.forEach(function (item) {
+ it('should be ' + item.expected, function () {
+ decommissionable.set('content', {
+ service: {
+ workStatus: item.status
+ }
+ });
+ expect(decommissionable.get('isComponentDecommissionDisable')).to.equal(item.expected);
+ });
+ });
+ });
+
+ describe('#getDesiredAdminStateSuccessCallback', function () {
+ responseCases.forEach(function (item) {
+ var state = item.HostRoles.desired_admin_state;
+ it('should return ' + state, function () {
+ decommissionable.getDesiredAdminStateSuccessCallback(item);
+ expect(decommissionable.get('desiredAdminState')).to.equal(state);
+ });
+ });
+ });
+
+ describe('#getDesiredAdminStateErrorCallback', function () {
+ it('should return null', function () {
+ decommissionable.getDesiredAdminStateErrorCallback();
+ expect(decommissionable.get('desiredAdminState')).to.be.a('null');
+ });
+ });
+
+ describe('#getDecommissionStatusSuccessCallback', function () {
+ responseCases.forEach(function (item) {
+ var state = item.ServiceComponentInfo;
+ it('should return ' + state, function () {
+ decommissionable.getDecommissionStatusSuccessCallback(item);
+ expect(decommissionable.get('decommissionedStatusObject')).to.equal(state);
+ });
+ });
+ });
+
+ describe('#getDecommissionStatusErrorCallback', function () {
+ it('should return null', function () {
+ decommissionable.getDecommissionStatusErrorCallback();
+ expect(decommissionable.get('decommissionedStatusObject')).to.be.a('null');
+ });
+ });
+
+ describe('#decommissionView.text', function () {
+
+ beforeEach(function () {
+ view = decommissionable.decommissionView.create();
+ view.reopen({
+ parentView: decommissionable
+ });
+ });
+
+ textCases.forEach(function (item) {
+ it('should be ' + item.text, function () {
+ view.set('parentView.isComponentDecommissionAvailable', item.available);
+ expect(view.get('text')).to.equal(item.text);
+ });
+ });
+
+ });
+
+});
[3/4] AMBARI-5822. Add unit tests for models. (Max Shepel via
akovalenko)
Posted by ak...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/82ffda43/ambari-web/test/models/user_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/user_test.js b/ambari-web/test/models/user_test.js
new file mode 100644
index 0000000..d844472
--- /dev/null
+++ b/ambari-web/test/models/user_test.js
@@ -0,0 +1,227 @@
+/**
+ * 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');
+
+var modelSetup = require('test/init_model_test');
+require('models/user');
+
+var user,
+ form,
+ userNameField,
+ userData = {
+ id: 'user'
+ },
+ objectData = Em.Object.create({
+ userName: 'name',
+ isLdap: true
+ });
+
+describe('App.User', function () {
+
+ beforeEach(function () {
+ user = App.User.createRecord(userData);
+ });
+
+ afterEach(function () {
+ modelSetup.deleteRecord(user);
+ });
+
+ describe('#id', function () {
+ it('should take value from userName', function () {
+ user.set('userName', 'name');
+ expect(user.get('id')).to.equal('name');
+ });
+ });
+
+ describe('#type', function () {
+ it('should be LDAP', function () {
+ user.set('isLdap', true);
+ expect(user.get('type')).to.equal('LDAP');
+ });
+ it('should be Local', function () {
+ user.set('isLdap', false);
+ expect(user.get('type')).to.equal('Local');
+ });
+ });
+
+});
+
+describe('App.EditUserForm', function () {
+
+ beforeEach(function () {
+ form = App.EditUserForm.create();
+ });
+
+ describe('#object', function () {
+
+ before(function () {
+ sinon.stub(App.router, 'get', function (k) {
+ if (k === 'mainAdminUserEditController.content') return userData;
+ return Em.get(App.router, k);
+ });
+ });
+
+ after(function () {
+ App.router.get.restore();
+ });
+
+ it('should take data from controller', function () {
+ expect(form.get('object')).to.eql(userData);
+ });
+
+ });
+
+ describe('#disableUsername', function () {
+ it('should update userName field', function () {
+ form.set('object', userData);
+ expect(form.get('field.userName.disabled')).to.equal('disabled');
+ });
+ });
+
+ describe('#disableAdminCheckbox', function () {
+
+ before(function () {
+ sinon.stub(App, 'get', function(k) {
+ switch (k) {
+ case 'router':
+ return {
+ getLoginName: Em.K
+ };
+ case 'supports.ldapGroupMapping':
+ return true;
+ default:
+ return Em.get(App, k);
+ }
+ });
+ sinon.stub(App.router, 'get', function (k) {
+ if (k === 'mainAdminUserEditController.content') return objectData;
+ return Em.get(App.router, k);
+ });
+ });
+
+ after(function () {
+ App.get.restore();
+ App.router.get.restore();
+ });
+
+ it('should not disable', function () {
+ expect(form.get('field.admin.disabled')).to.be.false;
+ });
+
+ it('should disable', function () {
+ form.set('object', objectData);
+ expect(form.get('field.admin.disabled')).to.be.true;
+ });
+
+ });
+
+ describe('#isValid', function () {
+ it('should be true as default', function () {
+ expect(form.isValid()).to.be.true;
+ });
+ it('should be false', function () {
+ form.set('field.new_password.isRequired', true);
+ expect(form.isValid()).to.be.false;
+ });
+ });
+
+ describe('#save', function () {
+
+ before(function () {
+ sinon.stub(App.router, 'get', function (k) {
+ if (k === 'mainAdminUserEditController.content') return objectData;
+ return Em.get(App.router, k);
+ });
+ });
+
+ after(function () {
+ App.router.get.restore();
+ });
+
+ it('should record form values to object', function () {
+ form.set('field.userName.value', 'name');
+ form.save();
+ expect(form.get('object.userName')).to.equal('name');
+ });
+ });
+
+});
+
+describe('App.CreateUserForm', function () {
+
+ beforeEach(function () {
+ form = App.CreateUserForm.create();
+ });
+
+ describe('#object', function () {
+
+ before(function () {
+ sinon.stub(App.router, 'get', function (k) {
+ if (k === 'mainAdminUserCreateController.content') return userData;
+ return Em.get(App, k);
+ });
+ });
+
+ after(function () {
+ App.router.get.restore();
+ });
+
+ it('should take data from controller', function () {
+ expect(form.get('object')).to.eql(userData);
+ });
+
+ });
+
+ describe('#field.userName.toLowerCase', function () {
+ it('should convert userName into lower case', function () {
+ userNameField = form.getField('userName');
+ userNameField.set('value', 'NAME');
+ expect(userNameField.get('value')).to.equal('name');
+ });
+ });
+
+ describe('#isValid', function () {
+ it('should be false as default', function () {
+ expect(form.isValid()).to.be.false;
+ });
+ it('should be true', function () {
+ form.get('fields').forEach(function (item) {
+ if (item.get('isRequired')) {
+ item.set('value', 'value');
+ }
+ });
+ expect(form.isValid()).to.be.true;
+ });
+ });
+
+ describe('#isWarn', function () {
+ it('should be false as default', function () {
+ expect(form.isWarn()).to.be.false;
+ });
+ it('should be true', function () {
+ form.getField('userName').set('value', '1');
+ expect(form.isWarn()).to.be.true;
+ });
+ it('should be false', function () {
+ form.getField('userName').set('value', 'name');
+ expect(form.isWarn()).to.be.false;
+ });
+ });
+
+});
[2/4] git commit: AMBARI-5821. Add unit tests for jobs models. (Max
Shepel via akovalenko)
Posted by ak...@apache.org.
AMBARI-5821. Add unit tests for jobs models. (Max Shepel via akovalenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/6d029a22
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/6d029a22
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/6d029a22
Branch: refs/heads/trunk
Commit: 6d029a22764bb30102b9a5beb2792040f0632515
Parents: de90972
Author: Aleksandr Kovalenko <ak...@hortonworks.com>
Authored: Tue May 20 15:08:24 2014 +0300
Committer: Aleksandr Kovalenko <ak...@hortonworks.com>
Committed: Tue May 20 15:08:24 2014 +0300
----------------------------------------------------------------------
ambari-web/app/assets/test/tests.js | 2 +
ambari-web/test/models/jobs/job_test.js | 98 ++++++++++++++++++++
ambari-web/test/models/jobs/tez_dag_test.js | 111 +++++++++++++++++++++++
3 files changed, 211 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/6d029a22/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 d820fcd..f694cb9 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -172,6 +172,8 @@ require('test/views/wizard/step8_view_test');
require('test/views/wizard/step9_view_test');
require('test/views/wizard/step9/hostLogPopupBody_view_test');
require('test/views/wizard/step10_view_test');
+require('test/models/jobs/job_test');
+require('test/models/jobs/tez_dag_test');
require('test/models/service/flume_test');
require('test/models/service/hbase_test');
require('test/models/service/hdfs_test');
http://git-wip-us.apache.org/repos/asf/ambari/blob/6d029a22/ambari-web/test/models/jobs/job_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/jobs/job_test.js b/ambari-web/test/models/jobs/job_test.js
new file mode 100644
index 0000000..1ca21d8
--- /dev/null
+++ b/ambari-web/test/models/jobs/job_test.js
@@ -0,0 +1,98 @@
+/**
+ * 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');
+
+var modelSetup = require('test/init_model_test');
+require('models/jobs/job');
+
+var job,
+ jobData = {
+ id: 'job'
+ },
+ timeCases = [
+ {
+ toSet: 'startTime',
+ toExpect: 'startTimeDisplay'
+ },
+ {
+ toSet: 'endTime',
+ toExpect: 'endTimeDisplay'
+ }
+ ],
+ timeDataCorrect = {
+ startTime: 1000,
+ endTime: 2000
+ },
+ timeDataRunning = {
+ startTime: App.dateTime() - 1000,
+ endTime: undefined
+ },
+ timeDataIncorrect = {
+ startTime: App.dateTime() - 1000,
+ endTime: 1
+ };
+
+describe('App.AbstractJob', function () {
+
+ beforeEach(function () {
+ job = App.AbstractJob.createRecord(jobData);
+ });
+
+ afterEach(function () {
+ modelSetup.deleteRecord(job);
+ });
+
+ timeCases.forEach(function (item) {
+ var toSet = item.toSet,
+ toExpect = item.toExpect;
+ describe('#' + toExpect, function () {
+ it('should be empty', function () {
+ job.set(toSet, 0);
+ expect(job.get(toExpect)).to.be.empty;
+ });
+ it('should return formatted time', function () {
+ job.set(toSet, 1000000);
+ expect(job.get(toExpect)).to.equal('Thu, Jan 01, 1970 00:16');
+ });
+ });
+ });
+
+ describe('#duration', function () {
+ it('should calculate the difference between endTime and startTime', function () {
+ job.setProperties(timeDataCorrect);
+ expect(job.get('duration')).to.equal(1000);
+ });
+ it('should calculate the difference between current time and startTime if the job is running', function () {
+ job.setProperties(timeDataRunning);
+ expect(job.get('duration')).to.be.at.least(1000);
+ });
+ it('should calculate the difference between current time and startTime if endTime is incorrect', function () {
+ job.setProperties(timeDataIncorrect);
+ expect(job.get('duration')).to.be.at.least(1000);
+ });
+ });
+
+ describe('#durationDisplay', function () {
+ it('should return formatted string', function () {
+ job.setProperties(timeDataCorrect);
+ expect(job.get('durationDisplay')).to.equal('1.00 secs');
+ });
+ });
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/6d029a22/ambari-web/test/models/jobs/tez_dag_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/jobs/tez_dag_test.js b/ambari-web/test/models/jobs/tez_dag_test.js
new file mode 100644
index 0000000..17e6c7e
--- /dev/null
+++ b/ambari-web/test/models/jobs/tez_dag_test.js
@@ -0,0 +1,111 @@
+/**
+ * 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');
+
+var modelSetup = require('test/init_model_test');
+require('models/jobs/tez_dag');
+
+var vertex,
+ vertexData = {
+ id: 'vertex'
+ },
+ timeData = {
+ startTime: 1000,
+ endTime: 2000
+ },
+ tasksCases = [
+ {
+ count: 5,
+ number: 5,
+ title: 'should return tasks count'
+ },
+ {
+ count: null,
+ number: 0,
+ title: 'should return 0'
+ }
+ ],
+ dataSizeCases = [
+ {
+ file: 'fileReadBytes',
+ hdfs: 'hdfsReadBytes',
+ total: 'totalReadBytes',
+ totalDisplay: 'totalReadBytesDisplay'
+ },
+ {
+ file: 'fileWriteBytes',
+ hdfs: 'hdfsWriteBytes',
+ total: 'totalWriteBytes',
+ totalDisplay: 'totalWriteBytesDisplay'
+ }
+ ],
+ setDataSize = function (vertex, fileProp, fileVal, hdfsProp, hdfsVal) {
+ vertex.set(fileProp, fileVal);
+ vertex.set(hdfsProp, hdfsVal);
+ };
+
+describe('App.TezDagVertex', function () {
+
+ beforeEach(function () {
+ vertex = App.TezDagVertex.createRecord(vertexData);
+ });
+
+ afterEach(function () {
+ modelSetup.deleteRecord(vertex);
+ });
+
+ describe('#duration', function () {
+ it('should calculate the difference between endTime and startTime', function () {
+ vertex.setProperties(timeData);
+ expect(vertex.get('duration')).to.equal(1000);
+ });
+ });
+
+ tasksCases.forEach(function(item) {
+ describe('#tasksNumber', function () {
+ it(item.title, function () {
+ vertex.set('tasksCount', item.count);
+ expect(vertex.get('tasksNumber')).to.equal(item.number);
+ });
+ });
+ });
+
+ dataSizeCases.forEach(function (item) {
+ describe('#' + item.total, function () {
+ it('should sum ' + item.file + ' and ' + item.hdfs, function () {
+ setDataSize(vertex, item.file, 1024, item.hdfs, 2048);
+ expect(vertex.get(item.total)).to.equal(3072);
+ });
+ });
+ describe('#' + item.totalDisplay, function () {
+ it('should return formatted ' + item.total, function () {
+ setDataSize(vertex, item.file, 1024, item.hdfs, 2048);
+ expect(vertex.get(item.totalDisplay)).to.equal('3 KB');
+ });
+ });
+ });
+
+ describe('#durationDisplay', function () {
+ it('should return formatted string', function () {
+ vertex.setProperties(timeData);
+ expect(vertex.get('durationDisplay')).to.equal('1.00 secs');
+ });
+ });
+
+});
[4/4] git commit: AMBARI-5822. Add unit tests for models. (Max Shepel
via akovalenko)
Posted by ak...@apache.org.
AMBARI-5822. Add unit tests for models. (Max Shepel via akovalenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/82ffda43
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/82ffda43
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/82ffda43
Branch: refs/heads/trunk
Commit: 82ffda43687b3f792e0247925486d172289abf7f
Parents: 6d029a2
Author: Aleksandr Kovalenko <ak...@hortonworks.com>
Authored: Tue May 20 15:14:01 2014 +0300
Committer: Aleksandr Kovalenko <ak...@hortonworks.com>
Committed: Tue May 20 15:14:01 2014 +0300
----------------------------------------------------------------------
ambari-web/app/assets/test/tests.js | 14 +
ambari-web/app/models/cluster_states.js | 2 +-
ambari-web/app/models/config_group.js | 2 +-
ambari-web/app/models/user.js | 2 +-
ambari-web/test/models/alert_test.js | 230 +++++++
ambari-web/test/models/authentication_test.js | 91 +++
ambari-web/test/models/cluster_states_test.js | 114 ++++
ambari-web/test/models/config_group_test.js | 154 +++++
ambari-web/test/models/dataset_job_test.js | 138 +++++
ambari-web/test/models/dataset_test.js | 148 +++++
ambari-web/test/models/form_test.js | 218 +++++++
ambari-web/test/models/hosts_test.js | 87 +++
ambari-web/test/models/job_test.js | 60 ++
ambari-web/test/models/run_test.js | 169 +++++
ambari-web/test/models/service_config_test.js | 617 +++++++++++++++++++
ambari-web/test/models/service_test.js | 292 +++++++++
.../test/models/stack_service_component_test.js | 254 ++++++++
ambari-web/test/models/user_test.js | 227 +++++++
18 files changed, 2816 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/82ffda43/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 f694cb9..2db199d 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -180,6 +180,20 @@ require('test/models/service/hdfs_test');
require('test/models/service/mapreduce_test');
require('test/models/service/mapreduce2_test');
require('test/models/service/yarn_test');
+require('test/models/alert_test');
+require('test/models/authentication_test');
+require('test/models/cluster_states_test');
+require('test/models/config_group_test');
+require('test/models/dataset_test');
+require('test/models/dataset_job_test');
+require('test/models/form_test');
require('test/models/host_test');
require('test/models/host_component_test');
+require('test/models/hosts_test');
+require('test/models/job_test');
require('test/models/rack_test');
+require('test/models/run_test');
+require('test/models/service_test');
+require('test/models/service_config_test');
+require('test/models/stack_service_component_test');
+require('test/models/user_test');
http://git-wip-us.apache.org/repos/asf/ambari/blob/82ffda43/ambari-web/app/models/cluster_states.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/cluster_states.js b/ambari-web/app/models/cluster_states.js
index 0d88860..320c3f4 100644
--- a/ambari-web/app/models/cluster_states.js
+++ b/ambari-web/app/models/cluster_states.js
@@ -186,7 +186,7 @@ App.clusterStatus = Em.Object.create(App.UserPref, {
* @return {*}
*/
setClusterStatus: function (newValue, opt) {
- if (App.testMode) return false;
+ if (App.get('testMode')) return false;
var user = App.db.getUser();
var login = App.db.getLoginName();
var val = {clusterName: this.get('clusterName')};
http://git-wip-us.apache.org/repos/asf/ambari/blob/82ffda43/ambari-web/app/models/config_group.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/config_group.js b/ambari-web/app/models/config_group.js
index 82db2a9..b1f178b 100644
--- a/ambari-web/app/models/config_group.js
+++ b/ambari-web/app/models/config_group.js
@@ -122,7 +122,7 @@ App.ConfigGroup = Ember.Object.extend({
}
// parentConfigGroup.hosts(hosts from default group) - are available hosts, which don't belong to any group
this.get('parentConfigGroup.hosts').forEach(function (hostName) {
- unusedHostsMap[hostName] = true;
+ unusedHostsMap[hostName.get('id')] = true;
});
sharedHosts.forEach(function (host) {
if (unusedHostsMap[host.get('id')]) {
http://git-wip-us.apache.org/repos/asf/ambari/blob/82ffda43/ambari-web/app/models/user.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/user.js b/ambari-web/app/models/user.js
index 46af975..d1f1b9a 100644
--- a/ambari-web/app/models/user.js
+++ b/ambari-web/app/models/user.js
@@ -58,7 +58,7 @@ App.EditUserForm = App.Form.extend({
disableAdminCheckbox:function () {
var object = this.get('object');
if (object) {
- if ((object.get('userName') == App.get('router').getLoginName()) || App.supports.ldapGroupMapping && object.get("isLdap")) {
+ if ((object.get('userName') == App.get('router').getLoginName()) || App.get('supports.ldapGroupMapping') && object.get("isLdap")) {
this.getField("admin").set("disabled", true);
} else {
this.getField("admin").set("disabled", false);
http://git-wip-us.apache.org/repos/asf/ambari/blob/82ffda43/ambari-web/test/models/alert_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/alert_test.js b/ambari-web/test/models/alert_test.js
new file mode 100644
index 0000000..48d06b5
--- /dev/null
+++ b/ambari-web/test/models/alert_test.js
@@ -0,0 +1,230 @@
+/**
+ * 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('models/alert');
+
+var alert,
+ sampleTime = 1399312800,
+ statusCases = [
+ {
+ status: 0,
+ property: 'isOk',
+ format: 'OK'
+ },
+ {
+ status: 1,
+ property: 'isWarning',
+ format: 'WARN'
+ },
+ {
+ status: 2,
+ property: 'isCritical',
+ format: 'CRIT'
+ },
+ {
+ status: 3,
+ property: 'isPassive',
+ format: 'MAINT'
+ },
+ {
+ status: 4,
+ property: '',
+ format: 'UNKNOWN'
+ }
+ ],
+ ignoredCases = [
+ {
+ title: 'title',
+ result: false
+ },
+ {
+ title: 'Percent',
+ result: true
+ }
+ ],
+ serviceTypeCases = [
+ {
+ type: 'MAPREDUCE',
+ name: 'MapReduce',
+ link: '#/main/services/MAPREDUCE/summary'
+ },
+ {
+ type: 'HDFS',
+ name: 'HDFS',
+ link: '#/main/services/HDFS/summary'
+ },
+ {
+ type: 'HBASE',
+ name: 'HBase',
+ link: '#/main/services/HBASE/summary'
+ },
+ {
+ type: 'ZOOKEEPER',
+ name: 'Zookeeper',
+ link: '#/main/services/ZOOKEEPER/summary'
+ },
+ {
+ type: 'OOZIE',
+ name: 'Oozie',
+ link: '#/main/services/OOZIE/summary'
+ },
+ {
+ type: 'HIVE',
+ name: 'Hive',
+ link: '#/main/services/HIVE/summary'
+ },
+ {
+ type: 'service',
+ name: null,
+ link: null
+ },
+ {
+ type: null,
+ name: null,
+ link: null
+ }
+ ],
+ titles = ['NodeManager health', 'NodeManager process', 'TaskTracker process', 'RegionServer process', 'DataNode process', 'DataNode space', 'ZooKeeper Server process', 'Supervisors process'];
+
+describe('App.Alert', function () {
+
+ beforeEach(function() {
+ alert = App.Alert.create();
+ });
+
+ describe('#date', function () {
+ it('is Mon May 05 2014', function () {
+ alert.set('lastTime', sampleTime);
+ expect(alert.get('date').toDateString()).to.equal('Mon May 05 2014');
+ });
+ });
+
+ statusCases.forEach(function (item) {
+ var status = item.status,
+ property = item.property;
+ if (property) {
+ describe('#' + property, function () {
+ it('status ' + status + ' is for ' + property, function () {
+ alert.set('status', status);
+ expect(alert.get(property)).to.be.true;
+ var falseStates = statusCases.mapProperty('property').without(property).without('');
+ var falseStatuses = [];
+ falseStates.forEach(function (state) {
+ falseStatuses.push(alert.get(state));
+ });
+ expect(falseStatuses).to.eql([false, false, false]);
+ });
+ });
+ }
+ });
+
+ describe('#ignoredForServices', function () {
+ titles.forEach(function (item) {
+ it('should be true for ' + item, function () {
+ alert.set('title', item);
+ expect(alert.get('ignoredForServices')).to.be.true;
+ });
+ });
+ it('should be false', function () {
+ alert.set('title', 'title');
+ expect(alert.get('ignoredForServices')).to.be.false;
+ });
+ });
+
+ describe('#ignoredForHosts', function () {
+ ignoredCases.forEach(function (item) {
+ it('should be ' + item.result, function () {
+ alert.set('title', item.title);
+ expect(alert.get('ignoredForHosts')).to.equal(item.result);
+ });
+ });
+ });
+
+ describe('#timeSinceAlert', function () {
+ statusCases.forEach(function (item) {
+ var format = item.format;
+ it('should indicate ' + format + ' status duration', function () {
+ alert.setProperties({
+ lastTime: sampleTime,
+ status: item.status.toString()
+ });
+ expect(alert.get('timeSinceAlert')).to.have.string(format);
+ expect(alert.get('timeSinceAlert.length')).to.be.above(format.length);
+ alert.set('lastTime', 0);
+ expect(alert.get('timeSinceAlert')).to.equal(format);
+ });
+ });
+ it('should be empty', function () {
+ alert.set('lastTime', undefined);
+ expect(alert.get('timeSinceAlert')).to.be.empty;
+ });
+ });
+
+ describe('#makeTimeAtleastMinuteAgo', function () {
+ it('should set the minute-ago time', function () {
+ var time = App.dateTime() - 50000,
+ date = new Date(time - 10000);
+ alert.set('lastTime', time);
+ expect(alert.makeTimeAtleastMinuteAgo(alert.get('date'))).to.be.at.least(date);
+ });
+ it('should return the actual time', function () {
+ var time = App.dateTime() - 70000;
+ alert.set('lastTime', time);
+ expect(alert.makeTimeAtleastMinuteAgo(alert.get('date'))).to.eql(alert.get('date'));
+ });
+ });
+
+ describe('#timeSinceAlertDetails', function () {
+ it ('should return the appropriate string', function () {
+ alert.set('lastTime', sampleTime);
+ var occurred = Em.I18n.t('services.alerts.occurredOn').format('May 05 2014', alert.get('date').toLocaleTimeString());
+ var brChecked = Em.I18n.t('services.alerts.brLastCheck').format($.timeago(sampleTime));
+ var checked = Em.I18n.t('services.alerts.lastCheck').format($.timeago(sampleTime));
+ expect(alert.get('timeSinceAlertDetails')).to.equal(occurred);
+ alert.set('lastCheck', sampleTime / 1000);
+ expect(alert.get('timeSinceAlertDetails')).to.equal(occurred + brChecked);
+ alert.set('lastTime', undefined);
+ expect(alert.get('timeSinceAlertDetails')).to.equal(checked);
+ });
+ it ('should be empty', function () {
+ alert.set('lastCheck', undefined);
+ expect(alert.get('timeSinceAlertDetails')).to.be.empty;
+ });
+ });
+
+ describe('#serviceName', function () {
+ serviceTypeCases.forEach(function (item) {
+ it('should be ' + item.name, function () {
+ alert.set('serviceType', item.type);
+ expect(alert.get('serviceName')).to.equal(item.name);
+ });
+ });
+ });
+
+ describe('#serviceLink', function () {
+ serviceTypeCases.forEach(function (item) {
+ it('should be ' + item.link, function () {
+ alert.set('serviceType', item.type);
+ expect(alert.get('serviceLink')).to.equal(item.link);
+ });
+ });
+ });
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/82ffda43/ambari-web/test/models/authentication_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/authentication_test.js b/ambari-web/test/models/authentication_test.js
new file mode 100644
index 0000000..3e7f44d
--- /dev/null
+++ b/ambari-web/test/models/authentication_test.js
@@ -0,0 +1,91 @@
+/**
+ * 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('models/authentication');
+
+var form,
+ methods = [
+ {
+ name: 'method',
+ fields: ['primaryServer', 'searchBaseDn', 'usernameAttribute']
+ },
+ {
+ name: 'bindMethod',
+ fields: ['bindUser', 'password', 'passwordRetype']
+ }
+ ],
+ classCases = [
+ {
+ result: 0,
+ message: 'fail',
+ className: 'error'
+ },
+ {
+ result: 1,
+ message: 'success',
+ className: 'success'
+ }
+ ];
+
+describe('App.AuthenticationForm', function () {
+
+ beforeEach(function() {
+ form = App.AuthenticationForm.create();
+ });
+
+ methods.forEach(function (method) {
+ method.fields.forEach(function (field) {
+ describe('#' + field + '.isRequired', function () {
+ for (var i = 2; i--; ) {
+ it('should be ' + i + ' dependent on ' + method.name + ' value', function () {
+ form.getField(method.name).set('value', i);
+ expect(form.getField(field).get('isRequired')).to.equal(i);
+ });
+ }
+ });
+ });
+ });
+
+ describe('#testResult', function () {
+ it('should be 0 or 1', function () {
+ form.testConfiguration();
+ expect([0, 1]).to.include(Number(form.get('testResult')));
+ });
+ });
+
+ describe('#testConfigurationMessage', function () {
+ classCases.forEach(function (item) {
+ it('should indicate ' + item.message, function () {
+ form.set('testResult', item.result);
+ expect(form.get('testConfigurationMessage')).to.equal(Em.I18n.t('admin.authentication.form.test.' + item.message));
+ });
+ });
+ });
+
+ describe('#testConfigurationClass', function () {
+ classCases.forEach(function (item) {
+ it('should indicate ' + item.className, function () {
+ form.set('testResult', item.result);
+ expect(form.get('testConfigurationClass')).to.equal('text-' + item.className);
+ });
+ });
+ });
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/82ffda43/ambari-web/test/models/cluster_states_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/cluster_states_test.js b/ambari-web/test/models/cluster_states_test.js
new file mode 100644
index 0000000..01c634e
--- /dev/null
+++ b/ambari-web/test/models/cluster_states_test.js
@@ -0,0 +1,114 @@
+/**
+ * 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('models/cluster_states');
+
+var status = App.clusterStatus,
+ notInstalledStates = ['CLUSTER_NOT_CREATED_1', 'CLUSTER_DEPLOY_PREP_2', 'CLUSTER_INSTALLING_3', 'SERVICE_STARTING_3'],
+ values = {
+ clusterName: 'name',
+ clusterState: 'STACK_UPGRADING',
+ wizardControllerName: 'wizardStep0Controller',
+ localdb: {}
+ },
+ response = {
+ clusterState: 'DEFAULT',
+ clusterName: 'cluster'
+ },
+ newValue = {
+ clusterName: 'name',
+ clusterState: 'STACK_UPGRADING',
+ wizardControllerName: 'wizardStep0Controller'
+ };
+
+describe('App.clusterStatus', function () {
+
+ describe('#isInstalled', function () {
+ notInstalledStates.forEach(function (item) {
+ it('should be false', function () {
+ status.set('clusterState', item);
+ expect(status.get('isInstalled')).to.be.false;
+ });
+ });
+ it('should be true', function () {
+ status.set('clusterState', 'DEFAULT');
+ expect(status.get('isInstalled')).to.be.true;
+ });
+ });
+
+ describe('#value', function () {
+ it('should be set from properties', function () {
+ Em.keys(values).forEach(function (key) {
+ status.set(key, values[key]);
+ });
+ expect(status.get('value')).to.eql(values);
+ });
+ });
+
+ describe('#getUserPrefSuccessCallback', function () {
+ it('should set the cluster parameters', function () {
+ status.getUserPrefSuccessCallback(response);
+ Em.keys(response).forEach(function (key) {
+ expect(status.get(key)).to.equal(response[key]);
+ });
+ });
+ });
+
+ describe('#setClusterStatus', function () {
+
+ afterEach(function () {
+ App.get.restore();
+ });
+
+ it('should return false in test mode', function () {
+ sinon.stub(App, 'get', function(k) {
+ if (k === 'testMode') return true;
+ return Em.get(App, k);
+ });
+ expect(status.setClusterStatus()).to.be.false;
+ });
+
+ it('should set cluster status in non-test mode', function () {
+ sinon.stub(App, 'get', function(k) {
+ if (k === 'testMode') return false;
+ return Em.get(App, k);
+ });
+ var clusterStatus = status.setClusterStatus(newValue);
+ expect(clusterStatus).to.eql(newValue);
+ });
+
+ });
+
+ describe('#makeRequestAsync', function () {
+ it('should be false after synchronous updateFromServer', function () {
+ status.updateFromServer();
+ expect(status.get('makeRequestAsync')).to.be.false;
+ });
+ it('should be true after asynchronous updateFromServer', function () {
+ status.updateFromServer(true);
+ expect(status.get('makeRequestAsync')).to.be.true;
+ });
+ it('should be false after synchronous setClusterStatus with no opt specified', function () {
+ status.setClusterStatus({clusterName: 'name'});
+ expect(status.get('makeRequestAsync')).to.be.false;
+ });
+ });
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/82ffda43/ambari-web/test/models/config_group_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/config_group_test.js b/ambari-web/test/models/config_group_test.js
new file mode 100644
index 0000000..9c5b09f
--- /dev/null
+++ b/ambari-web/test/models/config_group_test.js
@@ -0,0 +1,154 @@
+/**
+ * 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');
+
+var modelSetup = require('test/init_model_test');
+require('models/config_group');
+require('models/host');
+
+var configGroup,
+ hostRecord,
+ hosts = [
+ Em.Object.create({
+ id: 'host0',
+ hostName: 'host0'
+ }),
+ Em.Object.create({
+ id: 'host1',
+ hostName: 'host1'
+ })
+ ],
+ host = {
+ id: 'host0',
+ host_name: 'host0'
+ },
+ properties = [
+ {
+ name: 'n0',
+ value: 'v0'
+ },
+ {
+ name: 'n1',
+ value: 'v1'
+ }
+ ],
+ setParentConfigGroup = function (configGroup, hosts) {
+ configGroup.set('parentConfigGroup', App.ConfigGroup.create());
+ configGroup.set('parentConfigGroup.hosts', hosts);
+ };
+
+describe('App.ConfigGroup', function () {
+
+ beforeEach(function () {
+ configGroup = App.ConfigGroup.create();
+ });
+
+ describe('#displayName', function () {
+ it('should equal name if maximum length is not exceeded', function () {
+ configGroup.set('name', 'n');
+ expect(configGroup.get('displayName')).to.equal(configGroup.get('name'));
+ });
+ it('should be shortened if maximum length is exceeded', function () {
+ var maxLength = App.config.CONFIG_GROUP_NAME_MAX_LENGTH;
+ for (var i = maxLength + 1, name = ''; i--; ) {
+ name += 'n';
+ }
+ configGroup.set('name', name);
+ expect(configGroup.get('displayName')).to.contain('...');
+ expect(configGroup.get('displayName')).to.have.length(2 * Math.floor(maxLength / 2) + 3);
+ });
+ });
+
+ describe('#displayNameHosts', function () {
+ it('should indicate the number of hosts', function () {
+ var displayName = configGroup.get('displayName');
+ configGroup.set('hosts', []);
+ expect(configGroup.get('displayNameHosts')).to.equal(displayName + ' (0)');
+ configGroup.set('hosts', hosts);
+ expect(configGroup.get('displayNameHosts')).to.equal(displayName + ' (2)');
+ });
+ });
+
+ describe('#availableHosts', function () {
+
+ beforeEach(function () {
+ App.clusterStatus.set('clusterState', 'DEFAULT');
+ App.store.load(App.Host, host);
+ hostRecord = App.Host.find().findProperty('hostName', 'host0');
+ setParentConfigGroup(configGroup, hosts);
+ });
+
+ afterEach(function () {
+ modelSetup.deleteRecord(hostRecord);
+ });
+
+ it('should return an empty array as default', function () {
+ configGroup.set('isDefault', true);
+ expect(configGroup.get('availableHosts')).to.eql([]);
+ });
+
+ it('should return an empty array if there are no unused hosts', function () {
+ configGroup.set('parentConfigGroup', App.ConfigGroup.create());
+ expect(configGroup.get('availableHosts')).to.eql([]);
+ });
+
+ it('should take hosts from parentConfigGroup', function () {
+ setParentConfigGroup(configGroup, hosts);
+ expect(configGroup.get('availableHosts')).to.have.length(2);
+ });
+ });
+
+ describe('#isAddHostsDisabled', function () {
+
+ beforeEach(function () {
+ hostRecord = App.Host.createRecord(host);
+ setParentConfigGroup(configGroup, hosts);
+ configGroup.set('isDefault', false);
+ configGroup.set('availableHosts', []);
+ });
+
+ afterEach(function () {
+ modelSetup.deleteRecord(hostRecord);
+ });
+
+ it('should be false', function () {
+ expect(configGroup.get('isAddHostsDisabled')).to.be.false;
+ });
+ it('should be true', function () {
+ App.clusterStatus.set('clusterState', 'DEFAULT');
+ configGroup.set('isDefault', true);
+ expect(configGroup.get('isAddHostsDisabled')).to.be.true;
+ configGroup.set('availableHosts', hosts);
+ expect(configGroup.get('isAddHostsDisabled')).to.be.true;
+ });
+ });
+
+ describe('#propertiesList', function () {
+ it('should be formed from properties', function () {
+ configGroup.set('properties', properties);
+ properties.forEach(function (item) {
+ Em.keys(item).forEach(function (prop) {
+ expect(configGroup.get('propertiesList')).to.contain(item[prop]);
+ });
+ });
+ expect(configGroup.get('propertiesList')).to.have.length(24);
+ });
+ });
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/82ffda43/ambari-web/test/models/dataset_job_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/dataset_job_test.js b/ambari-web/test/models/dataset_job_test.js
new file mode 100644
index 0000000..d7e64fa
--- /dev/null
+++ b/ambari-web/test/models/dataset_job_test.js
@@ -0,0 +1,138 @@
+/**
+ * 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');
+
+var modelSetup = require('test/init_model_test');
+require('models/dataset_job');
+
+var dataSetJob,
+ dataSetJobData = {
+ id: 'job',
+ name: 'job'
+ },
+ timeCases = [
+ {
+ property: 'startFormatted',
+ dateProperty: 'startDate'
+ },
+ {
+ property: 'endFormatted',
+ dateProperty: 'endDate'
+ }
+ ],
+ timeTestData = [
+ {
+ title: 'should calculate time period',
+ time: function () {
+ return App.dateTime();
+ },
+ result: 'less than a minute ago'
+ },
+ {
+ title: 'should be empty',
+ time: function () {
+ return 0;
+ },
+ result: ''
+ }
+ ],
+ healthCases = [
+ {
+ status: 'SUCCEEDED',
+ className: 'icon-ok'
+ },
+ {
+ status: 'SUSPENDED',
+ className: 'icon-cog'
+ },
+ {
+ status: 'WAITING',
+ className: 'icon-time'
+ },
+ {
+ status: 'RUNNING',
+ className: 'icon-play'
+ },
+ {
+ status: 'KILLED',
+ className: 'icon-exclamation-sign'
+ },
+ {
+ status: 'FAILED',
+ className: 'icon-warning-sign'
+ },
+ {
+ status: 'ERROR',
+ className: 'icon-remove'
+ },
+ {
+ status: '',
+ className: 'icon-question-sign'
+ }
+ ];
+
+describe('App.DataSetJob', function () {
+
+ beforeEach(function () {
+ dataSetJob = App.DataSetJob.createRecord(dataSetJobData);
+ });
+
+ afterEach(function () {
+ modelSetup.deleteRecord(dataSetJob);
+ });
+
+ describe('#statusFormatted', function () {
+ it('should be in lower case and capitalized', function () {
+ dataSetJob.set('status', 'RUNNING');
+ expect(dataSetJob.get('statusFormatted')).to.equal('Running');
+ });
+ });
+
+ describe('#isSuspended', function () {
+ it('should be false', function () {
+ dataSetJob.set('status', 'RUNNING');
+ expect(dataSetJob.get('isSuspended')).to.be.false;
+ });
+ it('should be true', function () {
+ dataSetJob.set('status', 'SUSPENDED');
+ expect(dataSetJob.get('isSuspended')).to.be.true;
+ });
+ });
+
+ timeCases.forEach(function (item) {
+ describe('#' + item.property, function () {
+ timeTestData.forEach(function (test) {
+ it(test.title, function () {
+ dataSetJob.set(item.dateProperty, test.time());
+ expect(dataSetJob.get(item.property)).to.equal(test.result);
+ });
+ });
+ });
+ });
+
+ describe('#healthClass', function () {
+ healthCases.forEach(function (item) {
+ it('should be ' + item.className, function () {
+ dataSetJob.set('status', item.status);
+ expect(dataSetJob.get('healthClass')).to.equal(item.className);
+ });
+ });
+ });
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/82ffda43/ambari-web/test/models/dataset_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/dataset_test.js b/ambari-web/test/models/dataset_test.js
new file mode 100644
index 0000000..1d66709
--- /dev/null
+++ b/ambari-web/test/models/dataset_test.js
@@ -0,0 +1,148 @@
+/**
+ * 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');
+
+var modelSetup = require('test/init_model_test');
+require('models/dataset');
+
+var dataset,
+ datasetData = {
+ id: 'dataset',
+ name: 'dataset'
+ },
+ statusCases = [
+ {
+ status: 'RUNNING',
+ property: 'isRunning'
+ },
+ {
+ status: 'SUSPENDED',
+ property: 'isSuspended'
+ },
+ {
+ status: 'SUBMITTED',
+ property: 'isSubmitted'
+ }
+ ],
+ healthCases = [
+ {
+ title: 'should be live',
+ data: {
+ datasetJobs: [
+ Em.Object.create({
+ status: 'SUCCESSFUL'
+ })
+ ]
+ },
+ className: 'health-status-LIVE',
+ icon: App.healthIconClassGreen
+ },
+ {
+ title: 'should be dead for failed first job',
+ data: {
+ datasetJobs: [
+ Em.Object.create({
+ status: 'SUSPENDED',
+ endDate: 1
+ }),
+ Em.Object.create({
+ status: 'FAILED',
+ endDate: 0
+ })
+ ]
+ },
+ className: 'health-status-DEAD-RED',
+ icon: App.healthIconClassRed
+ },
+ {
+ title: 'should be for no jobs',
+ data: {
+ datasetJobs: []
+ },
+ className: 'health-status-LIVE',
+ icon: App.healthIconClassGreen
+ }
+ ];
+
+describe('App.Dataset', function () {
+
+ beforeEach(function () {
+ dataset = App.Dataset.createRecord(datasetData);
+ });
+
+ afterEach(function () {
+ modelSetup.deleteRecord(dataset);
+ });
+
+ describe('#prefixedName', function () {
+ it('should add mirroring prefix before the name', function () {
+ dataset.set('name', 'name');
+ expect(dataset.get('prefixedName')).to.equal(App.mirroringDatasetNamePrefix + 'name');
+ });
+ });
+
+ describe('#statusFormatted', function () {
+ it('should be in lower case and capitalized', function () {
+ dataset.set('status', 'RUNNING');
+ expect(dataset.get('statusFormatted')).to.equal('Running');
+ });
+ });
+
+ statusCases.forEach(function (item) {
+ describe(item.property, function () {
+
+ beforeEach(function () {
+ dataset.set('status', item.status);
+ });
+
+ it('should be true', function () {
+ expect(dataset.get(item.property)).to.be.true;
+ });
+
+ it('others should be false', function () {
+ var falseProperties = statusCases.mapProperty('property').without(item.property);
+ var falseStates = [];
+ falseProperties.forEach(function (prop) {
+ falseStates.push(dataset.get(prop));
+ });
+ expect(falseStates).to.eql([false, false]);
+ });
+
+ });
+ });
+
+ describe('#healthClass', function () {
+ healthCases.forEach(function (item) {
+ it(item.title, function () {
+ dataset.reopen(item.data);
+ expect(dataset.get('healthClass')).to.equal(item.className);
+ });
+ });
+ });
+
+ describe('#healthIconClass', function () {
+ healthCases.forEach(function (item) {
+ it(item.title, function () {
+ dataset.reopen(item.data);
+ expect(dataset.get('healthIconClass')).to.equal(item.icon);
+ });
+ });
+ });
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/82ffda43/ambari-web/test/models/form_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/form_test.js b/ambari-web/test/models/form_test.js
new file mode 100644
index 0000000..3ba7c10
--- /dev/null
+++ b/ambari-web/test/models/form_test.js
@@ -0,0 +1,218 @@
+/**
+ * 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('models/form');
+
+var form,
+ field,
+ formField,
+ resultCases = [
+ {
+ text: Em.I18n.t('form.saveError'),
+ result: -1
+ },
+ {
+ text: Em.I18n.t('form.saveSuccess'),
+ result: 1
+ },
+ {
+ text: '',
+ result: 0
+ }
+ ],
+ displayTypeCases = [
+ {
+ type: 'checkbox',
+ classString: 'Checkbox'
+ },
+ {
+ type: 'select',
+ classString: 'Select'
+ },
+ {
+ type: 'textarea',
+ classString: 'TextArea'
+ },
+ {
+ type: 'password',
+ classString: 'TextField'
+ },
+ {
+ type: 'hidden',
+ classString: 'TextField'
+ }
+ ],
+ hiddenCases = [
+ {
+ displayType: 'password',
+ type: 'hidden',
+ value: false
+ },
+ {
+ displayType: 'hidden',
+ type: 'hidden',
+ value: true
+ }
+ ],
+ expectError = function (message) {
+ formField.validate();
+ expect(formField.get('errorMessage')).to.equal(message);
+ };
+
+describe('App.Form', function () {
+
+ beforeEach(function () {
+ form = App.Form.create({
+ fieldsOptions: [
+ {
+ name: 'field0',
+ value: 'value0',
+ isRequired: false
+ }
+ ]
+ });
+ field = form.get('fields').objectAt(0);
+ });
+
+ describe('#fields', function () {
+ it('should get data from formFields', function () {
+ var fields = form.get('fields');
+ expect(fields).to.have.length(1);
+ expect(field.get('name')).to.equal('field0');
+ });
+ });
+
+ describe('#field', function () {
+ it('should get data from formFields', function () {
+ var field0 = form.get('field.field0');
+ expect(form.get('field')).to.not.be.empty;
+ expect(field0.get('name')).to.equal('field0');
+ expect(field0.get('form')).to.eql(form);
+ });
+ });
+
+ describe('#getField', function () {
+ it('should get field0', function () {
+ expect(form.getField('field0')).to.eql(form.get('field.field0'));
+ });
+ it('should be empty', function () {
+ form.set('fields', []);
+ expect(form.getField()).to.be.empty;
+ });
+ });
+
+ describe('#isValid', function () {
+ it('should be true', function () {
+ field.set('isRequired', false);
+ expect(form.isValid()).to.be.true;
+ });
+ it('should be false', function () {
+ field.setProperties({
+ isRequired: true,
+ value: ''
+ });
+ expect(form.isValid()).to.be.false;
+ });
+ });
+
+ describe('#updateValues', function () {
+ it('should update field0 value', function () {
+ form.set('object', Em.Object.create({field0: 'value0upd'}));
+ expect(field.get('value')).to.equal('value0upd');
+ });
+ it('should empty password value', function () {
+ field.set('displayType', 'password');
+ form.set('object', Em.Object.create());
+ expect(field.get('value')).to.be.empty;
+ });
+ it('should clear values', function () {
+ form.set('object', []);
+ expect(field.get('value')).to.be.empty;
+ });
+ });
+
+ describe('#clearValues', function () {
+ it('should clear values', function () {
+ var field0 = form.get('fields').objectAt(0);
+ field0.set('value', 'value0');
+ form.clearValues();
+ expect(field0.get('value')).to.be.empty;
+ });
+ });
+
+ describe('#resultText', function () {
+ resultCases.forEach(function (item) {
+ it('should be ' + item.text, function () {
+ form.set('result', item.result);
+ expect(form.get('resultText')).to.equal(item.text);
+ });
+ });
+ });
+
+});
+
+describe('App.FormField', function () {
+
+ beforeEach(function () {
+ formField = App.FormField.create();
+ });
+
+ describe('#isValid', function () {
+ it('should be true', function () {
+ expect(formField.get('isValid')).to.be.true;
+ });
+ it('should be false', function () {
+ formField.set('errorMessage', 'error');
+ expect(formField.get('isValid')).to.be.false;
+ });
+ });
+
+ describe('#viewClass', function () {
+ displayTypeCases.forEach(function (item) {
+ it('should be ' + item.classString, function () {
+ formField.set('displayType', item.type);
+ expect(formField.get('viewClass').toString()).to.contain(item.classString);
+ });
+ });
+ });
+
+ describe('#validate', function () {
+ it('should return error message', function () {
+ formField.set('isRequired', true);
+ expectError('This is required');
+ });
+ it('should return empty error message', function () {
+ formField.set('isRequired', false);
+ expectError('');
+ formField.set('value', 'value');
+ expectError('');
+ });
+ });
+
+ describe('#isHiddenField', function () {
+ hiddenCases.forEach(function (item) {
+ it('should be ' + item.value, function () {
+ formField.setProperties(item);
+ expect(formField.get('isHiddenField')).to.equal(item.value);
+ });
+ });
+ });
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/82ffda43/ambari-web/test/models/hosts_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/hosts_test.js b/ambari-web/test/models/hosts_test.js
new file mode 100644
index 0000000..288d425
--- /dev/null
+++ b/ambari-web/test/models/hosts_test.js
@@ -0,0 +1,87 @@
+/**
+ * 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('models/hosts');
+
+var hostInfo,
+ statusCases = [
+ {
+ status: 'REGISTERED',
+ bootStatusForDisplay: 'Success',
+ bootBarColor: 'progress-success',
+ bootStatusColor: 'text-success',
+ isBootDone: true
+ },
+ {
+ status: 'FAILED',
+ bootStatusForDisplay: 'Failed',
+ bootBarColor: 'progress-danger',
+ bootStatusColor: 'text-error',
+ isBootDone: true
+ },
+ {
+ status: 'PENDING',
+ bootStatusForDisplay: 'Preparing',
+ bootBarColor: 'progress-info',
+ bootStatusColor: 'text-info',
+ isBootDone: false
+ },
+ {
+ status: 'RUNNING',
+ bootStatusForDisplay: 'Installing',
+ bootBarColor: 'progress-info',
+ bootStatusColor: 'text-info',
+ isBootDone: false
+ },
+ {
+ status: 'DONE',
+ bootStatusForDisplay: 'Registering',
+ bootBarColor: 'progress-info',
+ bootStatusColor: 'text-info',
+ isBootDone: false
+ },
+ {
+ status: 'REGISTERING',
+ bootStatusForDisplay: 'Registering',
+ bootBarColor: 'progress-info',
+ bootStatusColor: 'text-info',
+ isBootDone: false
+ }
+ ],
+ tests = ['bootStatusForDisplay', 'bootBarColor', 'bootStatusColor', 'isBootDone'];
+
+describe('App.HostInfo', function () {
+
+ beforeEach(function () {
+ hostInfo = App.HostInfo.create();
+ });
+
+ tests.forEach(function (property) {
+ describe('#' + property, function () {
+ statusCases.forEach(function (testCase) {
+ it('should be ' + testCase[property], function () {
+ hostInfo.set('bootStatus', testCase.status);
+ expect(hostInfo.get(property)).to.equal(testCase[property]);
+ });
+ });
+ });
+ });
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/82ffda43/ambari-web/test/models/job_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/job_test.js b/ambari-web/test/models/job_test.js
new file mode 100644
index 0000000..d49cfe9
--- /dev/null
+++ b/ambari-web/test/models/job_test.js
@@ -0,0 +1,60 @@
+/**
+ * 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');
+
+var modelSetup = require('test/init_model_test');
+require('models/job');
+
+var job,
+ jobData = {
+ id: 'job'
+ };
+
+describe('App.Job', function () {
+
+ beforeEach(function () {
+ job = App.Job.createRecord(jobData);
+ });
+
+ afterEach(function () {
+ modelSetup.deleteRecord(job);
+ });
+
+ describe('#duration', function () {
+ it('should convert elapsedTime into time format', function () {
+ job.set('elapsedTime', 1000);
+ expect(job.get('duration')).to.equal('1.00 secs');
+ });
+ });
+
+ describe('#inputFormatted', function () {
+ it('should convert input into bandwidth format', function () {
+ job.set('input', 1024);
+ expect(job.get('inputFormatted')).to.equal('1.0KB');
+ });
+ });
+
+ describe('#outputFormatted', function () {
+ it('should convert output into bandwidth format', function () {
+ job.set('output', 1024);
+ expect(job.get('outputFormatted')).to.equal('1.0KB');
+ });
+ });
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/82ffda43/ambari-web/test/models/run_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/run_test.js b/ambari-web/test/models/run_test.js
new file mode 100644
index 0000000..0478fb0
--- /dev/null
+++ b/ambari-web/test/models/run_test.js
@@ -0,0 +1,169 @@
+/**
+ * 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');
+
+var modelSetup = require('test/init_model_test');
+require('models/run');
+
+var run,
+ job,
+ runData = {
+ id: 'run'
+ },
+ jobData = {
+ id: 'job'
+ },
+ cases = [
+ {
+ id: 'pig_run',
+ type: 'Pig'
+ },
+ {
+ id: 'hive_run',
+ type: 'Hive'
+ },
+ {
+ id: 'mr_run',
+ type: 'MapReduce'
+ },
+ {
+ id: 'run_pig_hive_mr_id',
+ type: ''
+ }
+ ];
+
+describe('App.Run', function () {
+
+ beforeEach(function () {
+ run = App.Run.createRecord(runData);
+ });
+
+ afterEach(function () {
+ modelSetup.deleteRecord(run);
+ });
+
+ describe('#idFormatted', function () {
+ it('should shorten id to 20 characters', function () {
+ for (var i = 21, name = ''; i--; ) {
+ name += 'n';
+ }
+ run.set('id', name);
+ expect(run.get('idFormatted')).to.have.length(20);
+ });
+ });
+
+ describe('#jobs', function () {
+
+ beforeEach(function () {
+ job = App.Job.createRecord(jobData);
+ job.reopen({
+ run: runData
+ });
+ });
+
+ afterEach(function () {
+ modelSetup.deleteRecord(job);
+ });
+
+ it('should load corresponding jobs from the store', function () {
+ run.set('loadAllJobs', true);
+ expect(run.get('jobs')).to.have.length(1);
+ expect(run.get('jobs').objectAt(0).get('run.id')).to.equal('run');
+ });
+
+ });
+
+ describe('#duration', function () {
+ it('should convert elapsedTime into time format', function () {
+ run.set('elapsedTime', 1000);
+ expect(run.get('duration')).to.equal('1.00 secs');
+ });
+ });
+
+ describe('#isRunning', function () {
+ it('should be true', function () {
+ run.setProperties({
+ numJobsTotal: 5,
+ numJobsCompleted: 0
+ });
+ expect(run.get('isRunning')).to.be.true;
+ });
+ it('should be false', function () {
+ run.setProperties({
+ numJobsTotal: 5,
+ numJobsCompleted: 5
+ });
+ expect(run.get('isRunning')).to.be.false;
+ });
+ });
+
+ describe('#inputFormatted', function () {
+ it('should convert input into bandwidth format', function () {
+ run.set('input', 1024);
+ expect(run.get('inputFormatted')).to.equal('1.0KB');
+ });
+ });
+
+ describe('#outputFormatted', function () {
+ it('should convert output into bandwidth format', function () {
+ run.set('output', 1024);
+ expect(run.get('outputFormatted')).to.equal('1.0KB');
+ });
+ });
+
+ describe('#lastUpdateTime', function () {
+ it('should sum elapsedTime and startTime', function () {
+ run.setProperties({
+ elapsedTime: 1000,
+ startTime: 2000
+ });
+ expect(run.get('lastUpdateTime')).to.equal(3000);
+ });
+ });
+
+ describe('#lastUpdateTimeFormatted', function () {
+ it('should form date from lastUpdateTime', function () {
+ run.setProperties({
+ elapsedTime: 1000,
+ startTime: 100000000000
+ });
+ expect(run.get('lastUpdateTimeFormatted')).to.equal('Sat, Mar 03, 1973 09:46');
+ });
+ });
+
+ describe('#lastUpdateTimeFormattedShort', function () {
+ it('should form date and time from lastUpdateTime', function () {
+ run.setProperties({
+ elapsedTime: 1000,
+ startTime: 100000000000
+ });
+ expect(run.get('lastUpdateTimeFormattedShort')).to.equal('Sat Mar 03 1973');
+ });
+ });
+
+ describe('#type', function () {
+ cases.forEach(function (item) {
+ it('should be ' + (item.type ? item.type : 'empty'), function () {
+ run.set('id', item.id);
+ expect(run.get('type')).to.equal(item.type);
+ });
+ });
+ });
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/82ffda43/ambari-web/test/models/service_config_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/service_config_test.js b/ambari-web/test/models/service_config_test.js
new file mode 100644
index 0000000..b422862
--- /dev/null
+++ b/ambari-web/test/models/service_config_test.js
@@ -0,0 +1,617 @@
+/**
+ * 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('models/service_config');
+
+var serviceConfig,
+ serviceConfigCategory,
+ group,
+ serviceConfigProperty,
+ serviceConfigPropertyInit,
+ configsData = [
+ {
+ overrides: [
+ {
+ error: true,
+ errorMessage: 'error'
+ },
+ {
+ error: true
+ },
+ {}
+ ]
+ },
+ {
+ isValid: false,
+ isVisible: true
+ },
+ {
+ isValid: true,
+ isVisible: true
+ }, {
+ isValid: false,
+ isVisible: false
+ }
+ ],
+ configCategoriesData = [
+ Em.Object.create({
+ slaveErrorCount: 1
+ }),
+ Em.Object.create({
+ slaveErrorCount: 2
+ })
+ ],
+ nameCases = [
+ {
+ name: 'DataNode',
+ primary: 'DATANODE'
+ },
+ {
+ name: 'TaskTracker',
+ primary: 'TASKTRACKER'
+ },
+ {
+ name: 'RegionServer',
+ primary: 'HBASE_REGIONSERVER'
+ },
+ {
+ name: 'name',
+ primary: null
+ }
+ ],
+ components = [
+ {
+ name: 'NameNode',
+ master: true
+ },
+ {
+ name: 'SNameNode',
+ master: true
+ },
+ {
+ name: 'JobTracker',
+ master: true
+ },
+ {
+ name: 'HBase Master',
+ master: true
+ },
+ {
+ name: 'Oozie Master',
+ master: true
+ },
+ {
+ name: 'Hive Metastore',
+ master: true
+ },
+ {
+ name: 'WebHCat Server',
+ master: true
+ },
+ {
+ name: 'ZooKeeper Server',
+ master: true
+ },
+ {
+ name: 'Nagios',
+ master: true
+ },
+ {
+ name: 'Ganglia',
+ master: true
+ },
+ {
+ name: 'DataNode',
+ slave: true
+ },
+ {
+ name: 'TaskTracker',
+ slave: true
+ },
+ {
+ name: 'RegionServer',
+ slave: true
+ }
+ ],
+ masters = components.filterProperty('master'),
+ slaves = components.filterProperty('slave'),
+ groupsData = {
+ groups: [
+ Em.Object.create({
+ errorCount: 1
+ }),
+ Em.Object.create({
+ errorCount: 2
+ })
+ ]
+ },
+ groupNoErrorsData = [].concat(configsData.slice(2)),
+ groupErrorsData = [configsData[1]],
+ overridableFalseData = [
+ {
+ isOverridable: false
+ },
+ {
+ isEditable: false,
+ overrides: configsData[0].overrides
+ },
+ {
+ displayType: 'masterHost'
+ }
+ ],
+ overridableTrueData = [
+ {
+ isOverridable: true,
+ isEditable: true
+ }, {
+ isOverridable: true,
+ overrides: []
+ },
+ {
+ isOverridable: true
+ }
+ ],
+ overriddenFalseData = [
+ {
+ overrides: null,
+ isOriginalSCP: true
+ },
+ {
+ overrides: [],
+ isOriginalSCP: true
+ }
+ ],
+ overriddenTrueData = [
+ {
+ overrides: configsData[0].overrides
+ },
+ {
+ isOriginalSCP: false
+ }
+ ],
+ removableFalseData = [
+ {
+ isEditable: false
+ },
+ {
+ hasOverrides: true
+ },
+ {
+ isUserProperty: false,
+ isOriginalSCP: true
+ }
+ ],
+ removableTrueData = [
+ {
+ isEditable: true,
+ hasOverrides: false,
+ isUserProperty: true
+ },
+ {
+ isEditable: true,
+ hasOverrides: false,
+ isOriginalSCP: false
+ }
+ ],
+ initPropertyData = [
+ {
+ initial: {
+ displayType: 'password',
+ value: 'value'
+ },
+ result: {
+ retypedPassword: 'value'
+ }
+ },
+ {
+ initial: {
+ id: 'puppet var',
+ value: '',
+ defaultValue: 'default'
+ },
+ result: {
+ value: 'default'
+ }
+ }
+ ],
+ notDefaultFalseData = [
+ {
+ isEditable: false
+ },
+ {
+ defaultValue: null
+ },
+ {
+ value: 'value',
+ defaultValue: 'value'
+ }
+ ],
+ notDefaultTrueData = {
+ isEditable: true,
+ value: 'value',
+ defaultValue: 'default'
+ },
+ types = ['masterHost', 'slaveHosts', 'masterHosts', 'slaveHost', 'radio button'],
+ classCases = [
+ {
+ initial: {
+ displayType: 'checkbox'
+ },
+ viewClass: App.ServiceConfigCheckbox
+ },
+ {
+ initial: {
+ displayType: 'password'
+ },
+ viewClass: App.ServiceConfigPasswordField
+ },
+ {
+ initial: {
+ displayType: 'combobox'
+ },
+ viewClass: App.ServiceConfigComboBox
+ },
+ {
+ initial: {
+ displayType: 'radio button'
+ },
+ viewClass: App.ServiceConfigRadioButtons
+ },
+ {
+ initial: {
+ displayType: 'directories'
+ },
+ viewClass: App.ServiceConfigTextArea
+ },
+ {
+ initial: {
+ displayType: 'content'
+ },
+ viewClass: App.ServiceConfigTextAreaContent
+
+ },
+ {
+ initial: {
+ displayType: 'multiLine'
+ },
+ viewClass: App.ServiceConfigTextArea
+ },
+ {
+ initial: {
+ displayType: 'custom'
+ },
+ viewClass: App.ServiceConfigBigTextArea
+ },
+ {
+ initial: {
+ displayType: 'masterHost'
+ },
+ viewClass: App.ServiceConfigMasterHostView
+ },
+ {
+ initial: {
+ displayType: 'masterHosts'
+ },
+ viewClass: App.ServiceConfigMasterHostsView
+ },
+ {
+ initial: {
+ displayType: 'slaveHosts'
+ },
+ viewClass: App.ServiceConfigSlaveHostsView
+ },
+ {
+ initial: {
+ unit: true,
+ displayType: 'type'
+ },
+ viewClass: App.ServiceConfigTextFieldWithUnit
+ },
+ {
+ initial: {
+ unit: false,
+ displayType: 'type'
+ },
+ viewClass: App.ServiceConfigTextField
+ }
+ ];
+
+
+describe('App.ServiceConfig', function () {
+
+ beforeEach(function () {
+ serviceConfig = App.ServiceConfig.create();
+ });
+
+ describe('#errorCount', function () {
+ it('should be 0', function () {
+ serviceConfig.setProperties({
+ configs: [],
+ configCategories: []
+ });
+ expect(serviceConfig.get('errorCount')).to.equal(0);
+ });
+ it('should sum counts of all errors', function () {
+ serviceConfig.setProperties({
+ configs: configsData,
+ configCategories: configCategoriesData
+ });
+ expect(serviceConfig.get('errorCount')).to.equal(6);
+ });
+ });
+
+});
+
+describe('App.ServiceConfigCategory', function () {
+
+ beforeEach(function () {
+ serviceConfigCategory = App.ServiceConfigCategory.create();
+ });
+
+ describe('#primaryName', function () {
+ nameCases.forEach(function (item) {
+ it('should return ' + item.primary, function () {
+ serviceConfigCategory.set('name', item.name);
+ expect(serviceConfigCategory.get('primaryName')).to.equal(item.primary);
+ })
+ });
+ });
+
+ describe('#isForMasterComponent', function () {
+ masters.forEach(function (item) {
+ it('should be true for ' + item.name, function () {
+ serviceConfigCategory.set('name', item.name);
+ expect(serviceConfigCategory.get('isForMasterComponent')).to.be.true;
+ });
+ });
+ it('should be false', function () {
+ serviceConfigCategory.set('name', 'name');
+ expect(serviceConfigCategory.get('isForMasterComponent')).to.be.false;
+ });
+ });
+
+ describe('#isForSlaveComponent', function () {
+ slaves.forEach(function (item) {
+ it('should be true for ' + item.name, function () {
+ serviceConfigCategory.set('name', item.name);
+ expect(serviceConfigCategory.get('isForSlaveComponent')).to.be.true;
+ });
+ });
+ it('should be false', function () {
+ serviceConfigCategory.set('name', 'name');
+ expect(serviceConfigCategory.get('isForSlaveComponent')).to.be.false;
+ });
+ });
+
+ describe('#slaveErrorCount', function () {
+ it('should be 0', function () {
+ serviceConfigCategory.set('slaveConfigs', []);
+ expect(serviceConfigCategory.get('slaveErrorCount')).to.equal(0);
+ });
+ it('should sum all errorCount values', function () {
+ serviceConfigCategory.set('slaveConfigs', groupsData);
+ expect(serviceConfigCategory.get('slaveErrorCount')).to.equal(3);
+ });
+ });
+
+ describe('#isAdvanced', function () {
+ it('should be true', function () {
+ serviceConfigCategory.set('name', 'Advanced');
+ expect(serviceConfigCategory.get('isAdvanced')).to.be.true;
+ });
+ it('should be false', function () {
+ serviceConfigCategory.set('name', 'name');
+ expect(serviceConfigCategory.get('isAdvanced')).to.be.false;
+ });
+ });
+
+});
+
+describe('App.Group', function () {
+
+ beforeEach(function () {
+ group = App.Group.create();
+ });
+
+ describe('#errorCount', function () {
+ it('should be 0', function () {
+ group.set('properties', groupNoErrorsData);
+ expect(group.get('errorCount')).to.equal(0);
+ });
+ it('should be 1', function () {
+ group.set('properties', groupErrorsData);
+ expect(group.get('errorCount')).to.equal(1);
+ });
+ });
+
+});
+
+describe('App.ServiceConfigProperty', function () {
+
+ beforeEach(function () {
+ serviceConfigProperty = App.ServiceConfigProperty.create();
+ });
+
+ describe('#overrideErrorTrigger', function () {
+ it('should be an increment', function () {
+ serviceConfigProperty.set('overrides', configsData[0].overrides);
+ expect(serviceConfigProperty.get('overrideErrorTrigger')).to.equal(1);
+ serviceConfigProperty.set('overrides', []);
+ expect(serviceConfigProperty.get('overrideErrorTrigger')).to.equal(2);
+ });
+ });
+
+ describe('#isPropertyOverridable', function () {
+ overridableFalseData.forEach(function (item) {
+ it('should be false', function () {
+ Em.keys(item).forEach(function (prop) {
+ serviceConfigProperty.set(prop, item[prop]);
+ });
+ expect(serviceConfigProperty.get('isPropertyOverridable')).to.be.false;
+ });
+ });
+ overridableTrueData.forEach(function (item) {
+ it('should be true', function () {
+ Em.keys(item).forEach(function (prop) {
+ serviceConfigProperty.set(prop, item[prop]);
+ });
+ expect(serviceConfigProperty.get('isPropertyOverridable')).to.be.true;
+ });
+ });
+ });
+
+ describe('#isOverridden', function () {
+ overriddenFalseData.forEach(function (item) {
+ it('should be false', function () {
+ Em.keys(item).forEach(function (prop) {
+ serviceConfigProperty.set(prop, item[prop]);
+ });
+ expect(serviceConfigProperty.get('isOverridden')).to.be.false;
+ });
+ });
+ overriddenTrueData.forEach(function (item) {
+ it('should be true', function () {
+ Em.keys(item).forEach(function (prop) {
+ serviceConfigProperty.set(prop, item[prop]);
+ });
+ expect(serviceConfigProperty.get('isOverridden')).to.be.true;
+ });
+ });
+ });
+
+ describe('#isRemovable', function () {
+ removableFalseData.forEach(function (item) {
+ it('should be false', function () {
+ Em.keys(item).forEach(function (prop) {
+ serviceConfigProperty.set(prop, item[prop]);
+ });
+ expect(serviceConfigProperty.get('isRemovable')).to.be.false;
+ });
+ });
+ removableTrueData.forEach(function (item) {
+ it('should be true', function () {
+ Em.keys(item).forEach(function (prop) {
+ serviceConfigProperty.set(prop, item[prop]);
+ });
+ expect(serviceConfigProperty.get('isRemovable')).to.be.true;
+ });
+ });
+ });
+
+ describe('#init', function () {
+ initPropertyData.forEach(function (item) {
+ it('should set initial data', function () {
+ serviceConfigPropertyInit = App.ServiceConfigProperty.create(item.initial);
+ Em.keys(item.result).forEach(function (prop) {
+ expect(serviceConfigPropertyInit.get(prop)).to.equal(item.result[prop]);
+ });
+ });
+ });
+ });
+
+ describe('#isNotDefaultValue', function () {
+ notDefaultFalseData.forEach(function (item) {
+ it('should be false', function () {
+ Em.keys(item).forEach(function (prop) {
+ serviceConfigProperty.set(prop, item[prop]);
+ });
+ expect(serviceConfigProperty.get('isNotDefaultValue')).to.be.false;
+ });
+ });
+ it('should be true', function () {
+ Em.keys(notDefaultTrueData).forEach(function (prop) {
+ serviceConfigProperty.set(prop, notDefaultTrueData[prop]);
+ });
+ expect(serviceConfigProperty.get('isNotDefaultValue')).to.be.true;
+ });
+ });
+
+ describe('#cantBeUndone', function () {
+ types.forEach(function (item) {
+ it('should be true', function () {
+ serviceConfigProperty.set('displayType', item);
+ expect(serviceConfigProperty.get('cantBeUndone')).to.be.true;
+ });
+ });
+ it('should be false', function () {
+ serviceConfigProperty.set('displayType', 'type');
+ expect(serviceConfigProperty.get('cantBeUndone')).to.be.false;
+ });
+ });
+
+ describe('#setDefaultValue', function () {
+ it('should change the default value', function () {
+ serviceConfigProperty.set('defaultValue', 'value0');
+ serviceConfigProperty.setDefaultValue(/\d/, '1');
+ expect(serviceConfigProperty.get('defaultValue')).to.equal('value1');
+ });
+ });
+
+ describe('#isValid', function () {
+ it('should be true', function () {
+ serviceConfigProperty.set('errorMessage', '');
+ expect(serviceConfigProperty.get('isValid')).to.be.true;
+ });
+ it('should be false', function () {
+ serviceConfigProperty.set('errorMessage', 'message');
+ expect(serviceConfigProperty.get('isValid')).to.be.false;
+ });
+ });
+
+ describe('#viewClass', function () {
+ classCases.forEach(function (item) {
+ it ('should be ' + item.viewClass, function () {
+ Em.keys(item.initial).forEach(function (prop) {
+ serviceConfigProperty.set(prop, item.initial[prop]);
+ });
+ expect(serviceConfigProperty.get('viewClass')).to.eql(item.viewClass);
+ });
+ });
+ });
+
+ describe('#validate', function () {
+ it('not required', function () {
+ serviceConfigProperty.setProperties({
+ isRequired: false,
+ value: ''
+ });
+ expect(serviceConfigProperty.get('errorMessage')).to.be.empty;
+ expect(serviceConfigProperty.get('error')).to.be.false;
+ });
+ it('should validate', function () {
+ serviceConfigProperty.setProperties({
+ isRequired: true,
+ value: 'value'
+ });
+ expect(serviceConfigProperty.get('errorMessage')).to.be.empty;
+ expect(serviceConfigProperty.get('error')).to.be.false;
+ });
+ it('should fail', function () {
+ serviceConfigProperty.setProperties({
+ isRequired: true,
+ value: 'value'
+ });
+ serviceConfigProperty.set('value', '');
+ expect(serviceConfigProperty.get('errorMessage')).to.equal('This is required');
+ expect(serviceConfigProperty.get('error')).to.be.true;
+ });
+ });
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/82ffda43/ambari-web/test/models/service_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/service_test.js b/ambari-web/test/models/service_test.js
new file mode 100644
index 0000000..eb1f5ea
--- /dev/null
+++ b/ambari-web/test/models/service_test.js
@@ -0,0 +1,292 @@
+/**
+ * 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');
+
+var modelSetup = require('test/init_model_test');
+require('models/service');
+
+var service,
+ serviceData = {
+ id: 'service'
+ },
+ healthCases = [
+ {
+ status: 'STARTED',
+ health: 'green'
+ },
+ {
+ status: 'STARTING',
+ health: 'green-blinking'
+ },
+ {
+ status: 'INSTALLED',
+ health: 'red'
+ },
+ {
+ status: 'STOPPING',
+ health: 'red-blinking'
+ },
+ {
+ status: 'UNKNOWN',
+ health: 'yellow'
+ },
+ {
+ status: 'ANOTHER',
+ health: 'yellow'
+ }
+ ],
+ statusPropertiesCases = [
+ {
+ status: 'INSTALLED',
+ property: 'isStopped'
+ },
+ {
+ status: 'STARTED',
+ property: 'isStarted'
+ }
+ ],
+ services = [
+ {
+ name: 'HDFS',
+ configurable: true
+ },
+ {
+ name: 'YARN',
+ configurable: true
+ },
+ {
+ name: 'MAPREDUCE',
+ configurable: true
+ },
+ {
+ name: 'MAPREDUCE2',
+ configurable: true
+ },
+ {
+ name:'TEZ',
+ clientOnly: true,
+ configurable: true
+ },
+ {
+ name: 'HBASE',
+ configurable: true
+ },
+ {
+ name: 'HIVE',
+ configurable: true
+ },
+ {
+ name: 'HCATALOG',
+ clientOnly: true
+ },
+ {
+ name: 'WEBHCAT',
+ configurable: true
+ },
+ {
+ name: 'FLUME',
+ configurable: true
+ },
+ {
+ name: 'FALCON',
+ configurable: true
+ },
+ {
+ name: 'STORM',
+ configurable: true
+ },
+ {
+ name: 'OOZIE',
+ configurable: true
+ },
+ {
+ name: 'GANGLIA',
+ configurable: true
+ },
+ {
+ name: 'NAGIOS',
+ configurable: true
+ },
+ {
+ name: 'ZOOKEEPER',
+ configurable: true
+ },
+ {
+ name: 'PIG',
+ configurable: true,
+ clientOnly: true
+ },
+ {
+ name: 'SQOOP',
+ clientOnly: true
+ },
+ {
+ name: 'HUE',
+ configurable: true
+ }
+ ],
+ clientsOnly = services.filterProperty('clientOnly').mapProperty('name'),
+ configurable = services.filterProperty('configurable').mapProperty('name'),
+ hostComponentsDataFalse = [
+ [],
+ [
+ {
+ staleConfigs: false
+ }
+ ],
+ [
+ {
+ serviceName: 'HIVE',
+ staleConfigs: false
+ }
+ ]
+ ],
+ hostComponentsDataTrue = [
+ [
+ Em.Object.create({
+ staleConfigs: true,
+ displayName: 'service0'
+ })
+ ],
+ [
+ Em.Object.create({
+ host: {
+ publicHostName: 'host0'
+ },
+ staleConfigs: true,
+ displayName: 'service1'
+ })
+ ]
+ ],
+ restartData = {
+ host0: ['service0', 'service1']
+};
+
+describe('App.Service', function () {
+
+ beforeEach(function () {
+ service = App.Service.createRecord(serviceData);
+ });
+
+ afterEach(function () {
+ modelSetup.deleteRecord(service);
+ });
+
+ describe('#isInPassive', function () {
+ it('should be true', function () {
+ service.set('passiveState', 'ON');
+ expect(service.get('isInPassive')).to.be.true;
+ });
+ it('should be false', function () {
+ service.set('passiveState', 'OFF');
+ expect(service.get('isInPassive')).to.be.false;
+ });
+ });
+
+ describe('#healthStatus', function () {
+ healthCases.forEach(function (item) {
+ it('should be ' + item.health, function () {
+ service.set('workStatus', item.status);
+ expect(service.get('healthStatus')).to.equal(item.health);
+ });
+ });
+ });
+
+ statusPropertiesCases.forEach(function (item) {
+ var status = item.status,
+ property = item.property;
+ describe('#' + property, function () {
+ it('status ' + status + ' is for ' + property, function () {
+ service.set('workStatus', status);
+ expect(service.get(property)).to.be.true;
+ var falseStates = statusPropertiesCases.mapProperty('property').without(property);
+ var falseStatuses = [];
+ falseStates.forEach(function (state) {
+ falseStatuses.push(service.get(state));
+ });
+ expect(falseStatuses).to.eql([false]);
+ });
+ });
+ });
+
+ describe('#isClientsOnly', function () {
+ clientsOnly.forEach(function (item) {
+ it('should be true', function () {
+ service.set('serviceName', item);
+ expect(service.get('isClientsOnly')).to.be.true;
+ });
+ });
+ it('should be false', function () {
+ service.set('serviceName', 'HDFS');
+ expect(service.get('isClientsOnly')).to.be.false;
+ });
+ });
+
+ describe('#isConfigurable', function () {
+ configurable.forEach(function (item) {
+ it('should be true', function () {
+ service.set('serviceName', item);
+ expect(service.get('isConfigurable')).to.be.true;
+ });
+ });
+ it('should be false', function () {
+ service.set('serviceName', 'SQOOP');
+ expect(service.get('isConfigurable')).to.be.false;
+ });
+ });
+
+ describe('#displayName', function () {
+ services.forEach(function (item) {
+ var displayName = App.Service.DisplayNames[item.name];
+ it('should return ' + displayName, function () {
+ service.set('serviceName', item.name);
+ expect(service.get('displayName')).to.equal(displayName);
+ });
+ });
+ });
+
+ describe('#isRestartRequired', function () {
+ hostComponentsDataFalse.forEach(function (item) {
+ it('should be false', function () {
+ service.reopen({
+ hostComponents: item
+ });
+ expect(service.get('isRestartRequired')).to.be.false;
+ });
+ });
+ hostComponentsDataTrue.forEach(function (item) {
+ it('should be true', function () {
+ service.reopen({
+ hostComponents: item
+ });
+ expect(service.get('isRestartRequired')).to.be.true;
+ });
+ });
+ });
+
+ describe('#restartRequiredMessage', function () {
+ it('should form message for 2 services on 1 host', function () {
+ service.set('restartRequiredHostsAndComponents', restartData);
+ expect(service.get('restartRequiredMessage')).to.contain('host0');
+ expect(service.get('restartRequiredMessage')).to.contain('service0');
+ expect(service.get('restartRequiredMessage')).to.contain('service1');
+ });
+ });
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/82ffda43/ambari-web/test/models/stack_service_component_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/stack_service_component_test.js b/ambari-web/test/models/stack_service_component_test.js
new file mode 100644
index 0000000..8bb349b
--- /dev/null
+++ b/ambari-web/test/models/stack_service_component_test.js
@@ -0,0 +1,254 @@
+/**
+ * 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');
+
+var modelSetup = require('test/init_model_test');
+require('models/stack_service_component');
+
+var stackServiceComponent,
+ stackServiceComponentData = {
+ id: 'ssc'
+ },
+ components = [
+ {
+ name: 'NAMENODE',
+ isReassignable: true
+ },
+ {
+ name: 'SECONDARY_NAMENODE',
+ isReassignable: true
+ },
+ {
+ name: 'JOBTRACKER',
+ isReassignable: true
+ },
+ {
+ name: 'RESOURCEMANAGER',
+ isReassignable: true
+ },
+ {
+ name: 'SUPERVISOR',
+ isDeletable: true,
+ isRollinRestartAllowed: true,
+ isAddableToHost: true
+ },
+ {
+ name: 'HBASE_MASTER',
+ isDeletable: true,
+ isAddableToHost: true
+ },
+ {
+ name: 'DATANODE',
+ isDeletable: true,
+ isRollinRestartAllowed: true,
+ isDecommissionAllowed: true,
+ isAddableToHost: true
+ },
+ {
+ name: 'TASKTRACKER',
+ isDeletable: true,
+ isRollinRestartAllowed: true,
+ isDecommissionAllowed: true,
+ isAddableToHost: true
+ },
+ {
+ name: 'NODEMANAGER',
+ isDeletable: true,
+ isRollinRestartAllowed: true,
+ isDecommissionAllowed: true,
+ isAddableToHost: true
+ },
+ {
+ name: 'HBASE_REGIONSERVER',
+ isDeletable: true,
+ isRollinRestartAllowed: true,
+ isDecommissionAllowed: true,
+ isAddableToHost: true
+ },
+ {
+ name: 'GANGLIA_MONITOR',
+ isDeletable: true,
+ isAddableToHost: true
+ },
+ {
+ name: 'FLUME_HANDLER',
+ isRefreshConfigsAllowed: true
+ },
+ {
+ name: 'ZOOKEEPER_SERVER',
+ isAddableToHost: true
+ },
+ {
+ name: 'MYSQL_SERVER',
+ mastersNotShown: true
+ },
+ {
+ name: 'JOURNALNODE',
+ mastersNotShown: true
+ }
+ ],
+ reassignable = components.filterProperty('isReassignable').mapProperty('name'),
+ deletable = components.filterProperty('isDeletable').mapProperty('name'),
+ rollingRestartable = components.filterProperty('isRollinRestartAllowed').mapProperty('name'),
+ decommissionable = components.filterProperty('isDecommissionAllowed').mapProperty('name'),
+ refreshable = components.filterProperty('isRefreshConfigsAllowed').mapProperty('name'),
+ addable = components.filterProperty('isAddableToHost').mapProperty('name'),
+ mastersNotShown = components.filterProperty('mastersNotShown').mapProperty('name');
+
+describe('App.StackServiceComponent', function () {
+
+ beforeEach(function () {
+ stackServiceComponent = App.StackServiceComponent.createRecord(stackServiceComponentData);
+ });
+
+ afterEach(function () {
+ modelSetup.deleteRecord(stackServiceComponent);
+ });
+
+ describe('#displayName', function () {
+ components.forEach(function (item) {
+ var displayName = App.format.components[item.name];
+ it('should be ' + displayName, function () {
+ stackServiceComponent.set('componentName', item.name);
+ expect(stackServiceComponent.get('displayName')).to.equal(displayName);
+ });
+ });
+ });
+
+ describe('#isSlave', function () {
+ it('should be true', function () {
+ stackServiceComponent.set('componentCategory', 'SLAVE');
+ expect(stackServiceComponent.get('isSlave')).to.be.true;
+ });
+ it('should be false', function () {
+ stackServiceComponent.set('componentCategory', 'cc');
+ expect(stackServiceComponent.get('isSlave')).to.be.false;
+ });
+ });
+
+ describe('#isRestartable', function () {
+ it('should be true', function () {
+ stackServiceComponent.set('isClient', false);
+ expect(stackServiceComponent.get('isRestartable')).to.be.true;
+ });
+ it('should be false', function () {
+ stackServiceComponent.set('isClient', true);
+ expect(stackServiceComponent.get('isRestartable')).to.be.false;
+ });
+ });
+
+ describe('#isReassignable', function () {
+ reassignable.forEach(function (item) {
+ it('should be true', function () {
+ stackServiceComponent.set('componentName', item);
+ expect(stackServiceComponent.get('isReassignable')).to.be.true;
+ });
+ });
+ it('should be false', function () {
+ stackServiceComponent.set('componentName', 'name');
+ expect(stackServiceComponent.get('isReassignable')).to.be.false;
+ });
+ });
+
+ describe('#isDeletable', function () {
+ deletable.forEach(function (item) {
+ it('should be true', function () {
+ stackServiceComponent.set('componentName', item);
+ expect(stackServiceComponent.get('isDeletable')).to.be.true;
+ });
+ });
+ it('should be false', function () {
+ stackServiceComponent.set('componentName', 'name');
+ expect(stackServiceComponent.get('isDeletable')).to.be.false;
+ });
+ });
+
+ describe('#isRollinRestartAllowed', function () {
+ rollingRestartable.forEach(function (item) {
+ it('should be true', function () {
+ stackServiceComponent.set('componentName', item);
+ expect(stackServiceComponent.get('isRollinRestartAllowed')).to.be.true;
+ });
+ });
+ it('should be false', function () {
+ stackServiceComponent.set('componentName', 'name');
+ expect(stackServiceComponent.get('isRollinRestartAllowed')).to.be.false;
+ });
+ });
+
+ describe('#isDecommissionAllowed', function () {
+ decommissionable.forEach(function (item) {
+ it('should be true', function () {
+ stackServiceComponent.set('componentName', item);
+ expect(stackServiceComponent.get('isDecommissionAllowed')).to.be.true;
+ });
+ });
+ it('should be false', function () {
+ stackServiceComponent.set('componentName', 'name');
+ expect(stackServiceComponent.get('isDecommissionAllowed')).to.be.false;
+ });
+ });
+
+ describe('#isRefreshConfigsAllowed', function () {
+ refreshable.forEach(function (item) {
+ it('should be true', function () {
+ stackServiceComponent.set('componentName', item);
+ expect(stackServiceComponent.get('isRefreshConfigsAllowed')).to.be.true;
+ });
+ });
+ it('should be false', function () {
+ stackServiceComponent.set('componentName', 'name');
+ expect(stackServiceComponent.get('isRefreshConfigsAllowed')).to.be.false;
+ });
+ });
+
+ describe('#isAddableToHost', function () {
+ addable.forEach(function (item) {
+ it('should be true', function () {
+ stackServiceComponent.set('componentName', item);
+ expect(stackServiceComponent.get('isAddableToHost')).to.be.true;
+ });
+ });
+ it('should be false', function () {
+ stackServiceComponent.set('componentName', 'name');
+ expect(stackServiceComponent.get('isAddableToHost')).to.be.false;
+ });
+ });
+
+ describe('#isShownOnInstallerAssignMasterPage', function () {
+ mastersNotShown.forEach(function (item) {
+ it('should be false', function () {
+ stackServiceComponent.set('componentName', item);
+ expect(stackServiceComponent.get('isShownOnInstallerAssignMasterPage')).to.be.false;
+ });
+ });
+ it('should be true', function () {
+ stackServiceComponent.set('componentName', 'APP_TIMELINE_SERVER');
+ expect(stackServiceComponent.get('isShownOnInstallerAssignMasterPage')).to.be.true;
+ });
+ it('should be true', function () {
+ stackServiceComponent.setProperties({
+ componentName: 'name',
+ isMaster: true
+ });
+ expect(stackServiceComponent.get('isShownOnInstallerAssignMasterPage')).to.be.true;
+ });
+ });
+
+});