AMBARI-25149. Cover all not covered common views
diff --git a/ambari-web/app/assets/test/tests.js b/ambari-web/app/assets/test/tests.js
index 760a27d..6e6ad3a 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -456,6 +456,10 @@
'test/views/common/form/field_view_test',
'test/views/common/form/manage_kdc_credentials_form_test',
'test/views/common/log_file_search_view_test',
+ 'test/views/common/log_search_ui_link_view_test',
+ 'test/views/common/log_tail_view_test',
+ 'test/views/common/not-scrollable-textarea_test',
+ 'test/views/common/service_restart_view_test',
'test/views/common/search_box_view_test',
'test/views/wizard/step3/hostLogPopupBody_view_test',
'test/views/wizard/step3/hostWarningPopupBody_view_test',
diff --git a/ambari-web/app/views/common/log_tail_view.js b/ambari-web/app/views/common/log_tail_view.js
index 4bc8c89..5ec87a3 100644
--- a/ambari-web/app/views/common/log_tail_view.js
+++ b/ambari-web/app/views/common/log_tail_view.js
@@ -231,5 +231,4 @@
if (!this.get('pollLogs') || this.get('pollLogTimeoutId') === null) return;
clearTimeout(this.get('pollLogTimeoutId'));
}
-
});
diff --git a/ambari-web/test/views/common/log_search_ui_link_view_test.js b/ambari-web/test/views/common/log_search_ui_link_view_test.js
new file mode 100644
index 0000000..1bf8c00
--- /dev/null
+++ b/ambari-web/test/views/common/log_search_ui_link_view_test.js
@@ -0,0 +1,66 @@
+/**
+ * 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');
+
+describe('App.LogSearchUILinkView', function() {
+ var view;
+ beforeEach(function () {
+ view = App.LogSearchUILinkView.create({});
+ });
+
+ describe('#content', function () {
+ it('should keep LOGSEARCH service if it present', function () {
+ var servicesArr = [
+ Em.Object.create({serviceName: 'HDFS'}),
+ Em.Object.create({serviceName: 'LOGSEARCH'}),
+ Em.Object.create({serviceName: 'HIVE'}),
+ ];
+ sinon.stub(App.Service, 'find').returns(servicesArr);
+ expect(view.get('content')).to.be.eql(servicesArr[1]);
+ App.Service.find.restore();
+ });
+
+ it('should keep null if LOGSEARCH is not present', function () {
+ var servicesArr = [
+ Em.Object.create({serviceName: 'HDFS'}),
+ Em.Object.create({serviceName: 'HIVE'}),
+ ];
+ sinon.stub(App.Service, 'find').returns(servicesArr);
+ expect(view.get('content')).to.be.equal(undefined);
+ App.Service.find.restore();
+ });
+ });
+
+ describe('#formatedLink', function () {
+ it('should be false if quickLinks is empty', function () {
+ view.set('quickLinks', []);
+ expect(view.get('formatedLink')).to.be.equal(false);
+ });
+
+ it('should be equal to url of quickLink of logsearch and quiclLinksParams', function () {
+ view.set('quickLinks', [
+ Em.Object.create({'label': 'Log Search UI', url: 'http://logsearchling.com'}),
+ Em.Object.create({'label': 'test 1', url: 'http://test1.com'}),
+ Em.Object.create({'label': 'test 2', url: 'http://test2.com'}),
+ ]);
+ view.set('linkQueryParams', '?param1=p1¶m2=p2');
+ expect(view.get('formatedLink')).to.be.equal('http://logsearchling.com?param1=p1¶m2=p2');
+ });
+ });
+});
\ No newline at end of file
diff --git a/ambari-web/test/views/common/log_tail_view_test.js b/ambari-web/test/views/common/log_tail_view_test.js
new file mode 100644
index 0000000..e1dd842
--- /dev/null
+++ b/ambari-web/test/views/common/log_tail_view_test.js
@@ -0,0 +1,385 @@
+/**
+ * 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');
+
+describe('App.LogTailView', function() {
+ var view;
+ beforeEach(function () {
+ view = App.LogTailView.create({});
+ });
+
+ describe('#didInsertElement', function () {
+ beforeEach(function () {
+ sinon.stub(view, 'infiniteScrollInit');
+ sinon.stub(view, 'fetchRows').returns({then: function () {}});
+ sinon.stub(view, 'subscribeResize');
+ });
+
+ afterEach(function () {
+ view.infiniteScrollInit.restore();
+ view.fetchRows.restore();
+ view.subscribeResize.restore();
+ });
+
+ it('should call infiniteScrollInit', function () {
+ view.didInsertElement();
+ expect(view.infiniteScrollInit.calledOnce).to.be.true;
+ });
+
+ it('should call fetchRows', function () {
+ view.didInsertElement();
+ expect(view.fetchRows.calledOnce).to.be.true;
+ });
+
+ it('should call subscribeResize', function () {
+ view.didInsertElement();
+ expect(view.subscribeResize.calledOnce).to.be.true;
+ });
+ });
+
+ describe('#_infiniteScrollHandler', function () {
+ beforeEach(function () {
+ sinon.stub(view, 'fetchRows').returns({then: function () {}});
+ });
+
+ afterEach(function () {
+ view.fetchRows.restore();
+ });
+
+ it('should do nothing if scrollTop is not equal to 0', function () {
+ view._infiniteScrollHandler({target: {}});
+ expect(view.fetchRows.called).to.be.false;
+ });
+
+ it('should do nothing if scrollTop is not equal to 0 noOldLogs is true and oldLogsIsFetching is false', function () {
+ sinon.stub(window, '$').returns({
+ scrollTop: function () {
+ return 0;
+ },
+ get: function () {
+ return {
+ clientHeight: 100
+ }
+ },
+ prop: function () {
+ return 15;
+ },
+ trigger: function () {
+ }
+ });
+ view.set('noOldLogs', true);
+ view.set('oldLogsIsFetching', false);
+ view._infiniteScrollHandler({target: {}});
+ expect(view.fetchRows.called).to.be.false;
+ window.$.restore();
+ });
+
+ it('should call fetchRows if scrollTop is not equal to 0 noOldLogs is false and oldLogsIsFetching is false', function () {
+ sinon.stub(window, '$').returns({
+ scrollTop: function () {
+ return 0;
+ },
+ get: function () {
+ return {
+ clientHeight: 100
+ }
+ },
+ prop: function () {
+ return 15;
+ },
+ trigger: function () {
+ }
+ });
+ view.set('noOldLogs', false);
+ view.set('oldLogsIsFetching', false);
+ view._infiniteScrollHandler({target: {}});
+ expect(view.fetchRows.called).to.be.true;
+ window.$.restore();
+ });
+ });
+
+ describe('#willDestroyElement', function () {
+ it('should call stopLogPolling unsubscribeResize and clear log rows', function () {
+ sinon.stub(view, 'stopLogPolling');
+ sinon.stub(view, 'unsubscribeResize');
+ var logRows = view.get('logRows');
+ sinon.stub(logRows, 'clear');
+ view.willDestroyElement();
+ expect(view.stopLogPolling.called).to.be.true;
+ expect(view.unsubscribeResize.called).to.be.true;
+ expect(logRows.clear.called).to.be.true;
+ view.stopLogPolling.restore();
+ view.unsubscribeResize.restore();
+ logRows.clear.restore();
+ });
+ });
+
+ describe('#unsubscribeResize', function () {
+ var $ = {off: function () {}};
+ beforeEach(function () {
+ sinon.stub($, 'off');
+ sinon.stub(window, '$').returns($);
+ });
+
+ afterEach(function () {
+ $.off.restore();
+ window.$.restore();
+ });
+
+ it('should do nothing if autoResize is false', function () {
+ view.set('autoResize', false);
+ view.unsubscribeResize();
+ expect($.off.called).to.be.false;
+ });
+
+ it('should call off if autoResize is true', function () {
+ view.set('autoResize', true);
+ view.unsubscribeResize();
+ expect($.off.called).to.be.true;
+ });
+ });
+
+ describe('#subscribeResize', function () {
+ var $ = {on: function () {}};
+ beforeEach(function () {
+ sinon.stub($, 'on');
+ sinon.stub(view, 'resizeHandler')
+ sinon.stub(window, '$').returns($);
+ });
+
+ afterEach(function () {
+ $.on.restore();
+ view.resizeHandler.restore();
+ window.$.restore();
+ });
+
+ it('should do nothing if autoResize is false', function () {
+ view.set('autoResize', false);
+ view.subscribeResize();
+ expect($.on.called).to.be.false;
+ expect(view.resizeHandler.called).to.be.false;
+ });
+
+ it('should call on and resizeHandler if autoResize is true', function () {
+ view.set('autoResize', true);
+ view.subscribeResize();
+ expect($.on.called).to.be.true;
+ expect(view.resizeHandler.called).to.be.true;
+ });
+ });
+
+ describe('#fetchRowsSuccess', function () {
+ beforeEach(function () {
+ sinon.stub(view, 'infiniteScrollSetDataAvailable');
+ });
+
+ afterEach(function () {
+ view.infiniteScrollSetDataAvailable.restore();
+ });
+
+ it('should call infiniteScrollSetDataAvailable and return empty array if logList is not available', function () {
+ var result = view.fetchRowsSuccess({});
+ expect(result).to.be.eql([]);
+ expect(view.infiniteScrollSetDataAvailable.called).to.be.true;
+ });
+
+ it('should call infiniteScrollSetDataAvailable and return empty array if logList is empty array', function () {
+ var result = view.fetchRowsSuccess({logList: []});
+ expect(result).to.be.eql([]);
+ expect(view.infiniteScrollSetDataAvailable.called).to.be.true;
+ });
+
+ it('should remap data correctly if logList in not empty', function () {
+ var logList = [
+ {
+ log_message: 'test_msg',
+ logtime: 1549533600141,
+ level: 1,
+ id: 1
+ }
+ ];
+ var result = view.fetchRowsSuccess({logList: logList});
+ expect(result).to.be.eql([Em.Object.create({
+ logMessage: 'test_msg',
+ level: 1,
+ id: 1,
+ logtime: 1549533600141,
+ logtimeFormatted: '2019-02-07 13:00:00,141'
+ })]);
+ });
+ });
+
+ describe('#refreshContent', function () {
+ beforeEach(function () {
+ var respData = [{
+ log_message: 'test_msg',
+ level: 1,
+ id: 1,
+ logtime: 1549533600141,
+ }, {
+ log_message: 'test_msg2',
+ level: 1,
+ id: 2,
+ logtime: 1549533600141,
+ },{
+ log_message: 'test_msg3',
+ level: 1,
+ id: 3,
+ logtime: 1549533600139,
+ }];
+ sinon.stub(view, 'fetchRows').returns({then: function (f) {
+ f({logList: respData});
+ }});
+ sinon.stub(view, 'appendLogRows');
+ sinon.stub(view, 'saveLastTimestamp');
+ });
+
+ afterEach(function () {
+ view.fetchRows.restore();
+ view.appendLogRows.restore();
+ view.saveLastTimestamp.restore();
+ });
+
+ it('should not call fetchRows if refreshEnd is false', function () {
+ view.set('refreshEnd', false);
+ view.refreshContent();
+ expect(view.fetchRows.called).to.be.false;
+ });
+
+ it('should call fetchRows and refresh content correctly if refreshEnd is true', function () {
+ view.set('refreshEnd', true);
+ view.set('lastLogTime', 1549533600140)
+ view.set('logRows', [Em.Object.create({
+ id: 1
+ })]);
+ view.refreshContent();
+ expect(view.fetchRows.called).to.be.true;
+ expect(view.appendLogRows.called).to.be.true;
+ expect(view.saveLastTimestamp.called).to.be.true;
+ expect(view.get('refreshEnd')).to.be.true;
+ });
+ });
+
+ describe('#saveLastTimestamp', function () {
+ it('should set 0 if no logworks or they are empty', function () {
+ view.saveLastTimestamp([]);
+ expect(view.get('lastLogTime')).to.be.equal(0);
+ });
+
+ it('should set first logtime to lastLogTime', function () {
+ view.saveLastTimestamp([Em.Object.create({logtime: 1}), Em.Object.create({logtime: 2})]);
+ expect(view.get('lastLogTime')).to.be.equal(1);
+ });
+ });
+
+ describe('#currentPage', function () {
+ it('should return start index and page size', function () {
+ view.set('selectedTailCount', 20);
+ expect(view.currentPage()).to.be.eql({
+ startIndex: 0,
+ pageSize: 20
+ });
+ });
+ });
+
+ describe('#nextPage', function() {
+ it('should increase startIndex on selectedTaiCount and return start index and page size', function() {
+ view.set('selectedTailCount', 20);
+ view.set('startIndex', 1);
+ expect(view.nextPage()).to.be.eql({
+ startIndex: 21,
+ pageSize: 20
+ });
+ });
+
+ it('should and return start index not less than 0 and page size', function() {
+ view.set('selectedTailCount', 20);
+ view.set('startIndex', -30);
+ expect(view.nextPage()).to.be.eql({
+ startIndex: 0,
+ pageSize: 20
+ });
+ });
+ });
+
+ describe('#oldestLogs', function () {
+ it('should return log rows length as start index and current page size', function () {
+ view.set('logRows', [{}, {}]);
+ view.set('selectedTailCount', 20);
+ expect(view.oldestLogs()).to.be.eql({
+ startIndex: 2,
+ pageSize: 20
+ });
+ });
+ });
+
+ describe('#startLogPolling', function () {
+ beforeEach(function () {
+ view.set('pollLogTimeoutId', null);
+ });
+
+ it('should do nothing if no pollLogs', function () {
+ view.set('pollLogs', null);
+ expect(view.get('pollLogTimeoutId')).to.be.equal(null);
+ });
+
+ it('should do nothing if state is destroyed', function () {
+ view.set('pollLogs', [{}]);
+ view.set('state', 'destroyed');
+ expect(view.get('pollLogTimeoutId')).to.be.equal(null);
+ });
+
+ it('should start polling if pollLogs are available and state is not destroyed', function () {
+ view.set('pollLogs', [{}]);
+ view.set('state', '');
+ expect(view.get('pollLogTimeoutId')).to.be.truthy;
+ });
+ });
+
+ describe('#stopLogPolling', function () {
+ beforeEach(function () {
+ sinon.stub(window, 'clearTimeout');
+ });
+
+ afterEach(function () {
+ window.clearTimeout.restore();
+ });
+
+ it('should do nothing if no pollLogs', function () {
+ view.set('pollLogs', null);
+ view.stopLogPolling();
+ expect(window.clearTimeout.called).to.be.false;
+ });
+
+ it('should do nothing if pollLogTimeoutId is null', function () {
+ view.set('pollLogs', [{}]);
+ view.set('pollLogTimeoutId', null);
+ view.stopLogPolling();
+ expect(window.clearTimeout.called).to.be.false;
+ });
+
+ it('should clear timeout if pollLogTimeoutId and pollLogs', function () {
+ view.set('pollLogs', [{}]);
+ view.set('pollLogTimeoutId', 1);
+ view.stopLogPolling();
+ expect(window.clearTimeout.called).to.be.true;
+ expect(window.clearTimeout.calledWith(1)).to.be.true;
+ });
+ });
+});
\ No newline at end of file
diff --git a/ambari-web/test/views/common/not-scrollable-textarea_test.js b/ambari-web/test/views/common/not-scrollable-textarea_test.js
new file mode 100644
index 0000000..cadd4e9
--- /dev/null
+++ b/ambari-web/test/views/common/not-scrollable-textarea_test.js
@@ -0,0 +1,55 @@
+/**
+ * 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');
+
+describe('App.NotScrollableTextArea', function() {
+ var view;
+ var $ = {select: function () {}, val: function () {}, height: function () {}};
+ beforeEach(function () {
+ view = App.NotScrollableTextArea.create({});
+ sinon.stub($, 'select');
+ sinon.stub($, 'height');
+ sinon.stub(view, '$').returns($);
+ });
+
+ afterEach(function () {
+ $.select.restore();
+ $.height.restore();
+ view.$.restore();
+ });
+
+ describe('#didInsertElement', function () {
+ it('should call fitHeight and select methods', function () {
+ sinon.stub(view, 'fitHeight');
+ view.didInsertElement();
+ expect(view.fitHeight.called).to.be.true;
+ expect($.select.called).to.be.true;
+ view.fitHeight.restore();
+ });
+ });
+
+ describe('#fitHeight', function () {
+ it('should run next height', function () {
+ sinon.stub(Em.run, 'next');
+ view.set('value', 1);
+ expect(Em.run.next.called).to.be.true;
+ Em.run.next.restore();
+ });
+ });
+});
\ No newline at end of file
diff --git a/ambari-web/test/views/common/service_restart_view_test.js b/ambari-web/test/views/common/service_restart_view_test.js
new file mode 100644
index 0000000..d8e35f5
--- /dev/null
+++ b/ambari-web/test/views/common/service_restart_view_test.js
@@ -0,0 +1,97 @@
+/**
+ * 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');
+
+describe('App.ServiceRestartView', function() {
+ var view;
+ beforeEach(function () {
+ view = App.ServiceRestartView.create({});
+ view.initDefaultConfigs();
+ });
+
+ describe('#initDefaultConfigs', function () {
+ it('should set correct default configs', function () {
+ expect(view.get('useRolling')).to.be.true;
+ expect(view.get('showAdvancedOptions')).to.be.false;
+ expect(view.get('showBatchRackOptions')).to.be.false;
+ expect(view.get('batchesOfHosts')).to.be.true;
+ expect(view.get('noOfHostsInBatch')).to.be.equal(10);
+ expect(view.get('batchIntervalHosts')).to.be.equal(120);
+ expect(view.get('percentRackStarted')).to.be.equal(100);
+ expect(view.get('batchIntervalRacks')).to.be.equal(120);
+ expect(view.get('isRetryChecked')).to.be.true;
+ expect(view.get('noOfRetriesPerHost')).to.be.equal(2);
+ expect(view.get('maxFailuresTolerated')).to.be.equal(10);
+ expect(view.get('maxFailuresBatch')).to.be.equal(2);
+ expect(view.get('maxFailuresRack')).to.be.equal(2);
+ expect(view.get('suppressAlerts')).to.be.true;
+ expect(view.get('pauseAfterFirst')).to.be.false;
+ });
+ });
+
+ describe('#getRestartConfigs', function () {
+ it('should return batchInterval as batchIntervalHosts if batchesOfHosts', function () {
+ var result = view.getRestartConfigs();
+ expect(result).to.be.eql(Em.Object.create({
+ batchInterval: view.get('batchIntervalHosts'),
+ maxFailures: view.get('maxFailuresTolerated'),
+ maxFailuresPerBatch: view.get('maxFailuresTolerated'),
+ }));
+ });
+
+ it('should return batchInterval as batchIntervalRacks if no batchesOfHosts', function () {
+ view.set('batchesOfHosts', false);
+ view.set('batchIntervalRacks', 95);
+ var result = view.getRestartConfigs();
+ expect(result).to.be.eql(Em.Object.create({
+ batchInterval: view.get('batchIntervalRacks'),
+ maxFailures: view.get('maxFailuresTolerated'),
+ maxFailuresPerBatch: view.get('maxFailuresTolerated'),
+ }));
+ });
+ });
+
+ describe('#getNoOfHosts', function () {
+ it('should return noOfHostsInBatch if batchesOfHosts is truthly', function () {
+ var result = view.getNoOfHosts();
+ expect(result).to.be.equal(view.get('noOfHostsInBatch'));
+ });
+
+ it('should return correct value if batchesOfHosts is falsy', function () {
+ view.set('batchesOfHosts', false);
+ view.set('componentHostRackInfoMap', {
+ test: {
+ size: function () { return 200}
+ }
+ });
+ var result = view.getNoOfHosts('test');
+ expect(result).to.be.equal(50);
+ });
+ });
+
+ describe('#toggleAdvancedOptions', function () {
+ it('should toggle showAdvancedOptions', function () {
+ view.set('showAdvancedOptions', true);
+ view.toggleAdvancedOptions();
+ expect(view.get('showAdvancedOptions')).to.be.false;
+ view.toggleAdvancedOptions();
+ expect(view.get('showAdvancedOptions')).to.be.true;
+ });
+ });
+});
\ No newline at end of file