step4_test.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. var Ember = require('ember');
  19. var App = require('app');
  20. var modelSetup = require('test/init_model_test');
  21. require('controllers/wizard/step4_controller');
  22. describe('App.WizardStep4Controller', function () {
  23. var services = [
  24. 'HDFS', 'MAPREDUCE', 'NAGIOS', 'GANGLIA', 'OOZIE', 'HIVE', 'HBASE', 'PIG', 'SCOOP', 'ZOOKEEPER', 'HCATALOG',
  25. 'WEBHCAT', 'YARN', 'MAPREDUCE2', 'FALCON', 'TEZ', 'STORM'
  26. ];
  27. var controller = App.WizardStep4Controller.create();
  28. var generateSelectedServicesContent = function(selectedServiceNames) {
  29. var allServices = services.slice(0);
  30. modelSetup.setupStackServiceComponent();
  31. if (selectedServiceNames.contains('GLUSTERFS')) allServices.push('GLUSTERFS');
  32. allServices = allServices.map(function(serviceName) {
  33. return [Ember.Object.create({
  34. 'serviceName': serviceName,
  35. 'isSelected': false,
  36. 'canBeSelected': true,
  37. 'isInstalled': false,
  38. isPrimaryDFS: serviceName == 'HDFS',
  39. isDFS: ['HDFS','GLUSTERFS'].contains(serviceName),
  40. isMonitoringService: ['NAGIOS','GANGLIA'].contains(serviceName),
  41. requiredServices: App.StackService.find(serviceName).get('requiredServices'),
  42. displayNameOnSelectServicePage: App.format.role(serviceName),
  43. coSelectedServices: function() {
  44. return App.StackService.coSelected[this.get('serviceName')] || [];
  45. }.property('serviceName')
  46. })];
  47. }).reduce(function(current, prev) { return current.concat(prev); });
  48. selectedServiceNames.forEach(function(serviceName) {
  49. allServices.findProperty('serviceName', serviceName).set('isSelected', true);
  50. });
  51. return allServices;
  52. };
  53. services.forEach(function(serviceName, index){
  54. controller.pushObject(Ember.Object.create({
  55. 'serviceName':serviceName, 'isSelected': true, 'isHiddenOnSelectServicePage': false, 'isInstalled': false, 'isDisabled': 'HDFS' === serviceName, isDFS: 'HDFS' === serviceName
  56. }));
  57. });
  58. describe('#isSubmitDisabled', function () {
  59. it('should return false if at least one selected service is not installed', function () {
  60. expect(controller.get('isSubmitDisabled')).to.equal(false);
  61. });
  62. it('should return true if all selected services are already installed', function () {
  63. controller.setEach('isInstalled', true);
  64. controller.findProperty('serviceName', 'HDFS').set('isSelected', false);
  65. expect(controller.get('isSubmitDisabled')).to.equal(true);
  66. });
  67. });
  68. describe('#isAll', function () {
  69. it('should return true if all services are selected', function () {
  70. controller.setEach('isInstalled', false);
  71. controller.findProperty('serviceName', 'HDFS').set('isSelected', true);
  72. expect(controller.get('isAll')).to.equal(true);
  73. });
  74. it('should return false if at least one service is not selected', function () {
  75. controller.findProperty('serviceName', 'HDFS').set('isSelected', false);
  76. expect(controller.get('isAll')).to.equal(false);
  77. });
  78. });
  79. describe('#isMinimum', function () {
  80. it('should return true if there are no services selected, except disabled', function () {
  81. controller.setEach('isSelected', false);
  82. expect(controller.get('isMinimum')).to.equal(true);
  83. });
  84. it('should return false if at least one service is selected, except disabled', function () {
  85. controller.findProperty('serviceName', 'MAPREDUCE').set('isSelected', true);
  86. expect(controller.get('isMinimum')).to.equal(false);
  87. });
  88. });
  89. describe('#selectAll()', function () {
  90. it('should select all services', function () {
  91. controller.setEach('isSelected', false);
  92. controller.selectAll();
  93. expect(controller.filterProperty('canBeSelected', true).everyProperty('isSelected', true)).to.equal(true);
  94. });
  95. });
  96. describe('#selectMinimum()', function () {
  97. it('should set isSelected false for all services', function () {
  98. controller.setEach('isSelected', true);
  99. controller.selectMinimum();
  100. expect(controller.findProperty('serviceName', 'HDFS').get('isSelected')).to.equal(false);
  101. expect(controller.filterProperty('isDisabled', false).everyProperty('isSelected', false)).to.equal(true);
  102. });
  103. });
  104. describe('#multipleDFSs()', function () {
  105. it('should return true if HDFS is selected and GLUSTERFS is selected', function () {
  106. controller.set('content', generateSelectedServicesContent(['HDFS', 'GLUSTERFS']));
  107. expect(controller.multipleDFSs()).to.equal(true);
  108. });
  109. it('should return false if HDFS is not selected and GLUSTERFS is selected', function () {
  110. controller.set('content', generateSelectedServicesContent(['GLUSTERFS']));
  111. expect(controller.multipleDFSs()).to.equal(false);
  112. });
  113. it('should return false if HDFS is selected and GLUSTERFS is not selected', function () {
  114. controller.set('content', generateSelectedServicesContent(['HDFS']));
  115. expect(controller.multipleDFSs()).to.equal(false);
  116. });
  117. });
  118. describe('#setGroupedServices()', function () {
  119. var testCases = [
  120. {
  121. title: 'should set HCATALOG and WEBHCAT isSelected to true when HIVE is selected',
  122. condition: {
  123. 'HBASE': true,
  124. 'ZOOKEEPER': true,
  125. 'HIVE': true,
  126. 'HCATALOG': true,
  127. 'WEBHCAT': true
  128. },
  129. result: {
  130. 'HCATALOG': true,
  131. 'WEBHCAT': true
  132. }
  133. },
  134. {
  135. title: 'should set HCATALOG and WEBHCAT isSelected to false when HIVE is not selected',
  136. condition: {
  137. 'HBASE': true,
  138. 'ZOOKEEPER': true,
  139. 'HIVE': false,
  140. 'HCATALOG': true,
  141. 'WEBHCAT': true
  142. },
  143. result: {
  144. 'HCATALOG': false,
  145. 'WEBHCAT': false
  146. }
  147. },
  148. {
  149. title: 'should set MAPREDUCE2 isSelected to true when YARN is selected',
  150. condition: {
  151. 'HBASE': true,
  152. 'ZOOKEEPER': true,
  153. 'HIVE': false,
  154. 'HCATALOG': true,
  155. 'WEBHCAT': true,
  156. 'YARN': true,
  157. 'MAPREDUCE2': true
  158. },
  159. result: {
  160. 'MAPREDUCE2': true,
  161. 'HCATALOG': false,
  162. 'WEBHCAT': false
  163. }
  164. },
  165. {
  166. title: 'should set MAPREDUCE2 isSelected to false when YARN is not selected',
  167. condition: {
  168. 'HBASE': true,
  169. 'ZOOKEEPER': true,
  170. 'HIVE': true,
  171. 'HCATALOG': true,
  172. 'WEBHCAT': true,
  173. 'YARN': false,
  174. 'MAPREDUCE2': true
  175. },
  176. result: {
  177. 'MAPREDUCE2': false,
  178. 'HCATALOG': true,
  179. 'WEBHCAT': true
  180. }
  181. }
  182. ];
  183. testCases.forEach(function(testCase){
  184. it(testCase.title, function () {
  185. controller.clear();
  186. for(var id in testCase.condition) {
  187. controller.pushObject(Ember.Object.create({
  188. 'serviceName':id, 'isSelected': testCase.condition[id], 'canBeSelected': true, 'isInstalled': false,
  189. coSelectedServices: function() {
  190. return App.StackService.coSelected[this.get('serviceName')] || [];
  191. }.property('serviceName')
  192. }));
  193. }
  194. controller.setGroupedServices();
  195. for(var service in testCase.result) {
  196. expect(controller.findProperty('serviceName', service).get('isSelected')).to.equal(testCase.result[service]);
  197. }
  198. });
  199. }, this);
  200. });
  201. describe('#addValidationError()', function() {
  202. var tests = [
  203. {
  204. errorObjects: [
  205. {
  206. id: 'serviceCheck_ZOOKEEPER',
  207. shouldBeAdded: true
  208. },
  209. {
  210. id: 'serviceCheck_YARN',
  211. shouldBeAdded: true
  212. }
  213. ],
  214. expectedIds: ['serviceCheck_ZOOKEEPER', 'serviceCheck_YARN']
  215. },
  216. {
  217. errorObjects: [
  218. {
  219. id: 'fsCheck',
  220. shouldBeAdded: true
  221. },
  222. {
  223. id: 'fsCheck',
  224. shouldBeAdded: false
  225. }
  226. ],
  227. expectedIds: ['fsCheck']
  228. }
  229. ];
  230. beforeEach(function() {
  231. controller.clear();
  232. controller.set('errorStack', []);
  233. });
  234. tests.forEach(function(test) {
  235. var message = 'Erorrs {0} thrown. errorStack property should contains ids: {1}'
  236. .format(test.errorObjects.mapProperty('id').join(', '), test.expectedIds.join(', '));
  237. it(message, function() {
  238. test.errorObjects.forEach(function(errorObject) {
  239. expect(controller.addValidationError(errorObject)).to.equal(errorObject.shouldBeAdded);
  240. });
  241. expect(controller.get('errorStack').mapProperty('id')).to.eql(test.expectedIds);
  242. });
  243. })
  244. });
  245. describe('#validate()', function() {
  246. var tests = [
  247. {
  248. services: ['HDFS','ZOOKEEPER'],
  249. errorsExpected: ['monitoringCheck']
  250. },
  251. {
  252. services: ['ZOOKEEPER'],
  253. errorsExpected: ['monitoringCheck']
  254. },
  255. {
  256. services: ['HDFS'],
  257. errorsExpected: ['serviceCheck_ZOOKEEPER', 'monitoringCheck']
  258. },
  259. {
  260. services: ['HDFS', 'TEZ', 'ZOOKEEPER'],
  261. errorsExpected: ['serviceCheck_YARN', 'monitoringCheck']
  262. },
  263. {
  264. services: ['HDFS', 'ZOOKEEPER', 'FALCON', 'NAGIOS'],
  265. errorsExpected: ['serviceCheck_OOZIE', 'monitoringCheck']
  266. },
  267. {
  268. services: ['HDFS', 'ZOOKEEPER', 'GANGLIA', 'NAGIOS', 'HIVE'],
  269. errorsExpected: ['serviceCheck_YARN']
  270. },
  271. {
  272. services: ['HDFS', 'GLUSTERFS', 'ZOOKEEPER', 'HIVE'],
  273. errorsExpected: ['serviceCheck_YARN', 'multipleDFS', 'monitoringCheck']
  274. },
  275. {
  276. services: ['HDFS','ZOOKEEPER', 'NAGIOS', 'GANGLIA'],
  277. errorsExpected: []
  278. }
  279. ];
  280. tests.forEach(function(test) {
  281. var message = '{0} selected validation should be {1}, errors with ids: {2} present'
  282. .format(test.services.join(','), !!test.validationPassed ? 'passed' : 'failed', test.errorsExpected.join(','));
  283. it(message, function() {
  284. controller.clear();
  285. controller.set('content', generateSelectedServicesContent(test.services));
  286. controller.validate();
  287. expect(controller.get('errorStack').mapProperty('id')).to.be.eql(test.errorsExpected);
  288. });
  289. })
  290. });
  291. describe('#onPrimaryPopupCallback()', function() {
  292. var c;
  293. var tests = [
  294. {
  295. services: ['HDFS','ZOOKEEPER'],
  296. confirmPopupCount: 1,
  297. errorsExpected: ['monitoringCheck']
  298. },
  299. {
  300. services: ['ZOOKEEPER'],
  301. confirmPopupCount: 1,
  302. errorsExpected: ['monitoringCheck']
  303. },
  304. {
  305. services: ['HDFS', 'GLUSTERFS', 'ZOOKEEPER', 'HIVE'],
  306. confirmPopupCount: 3,
  307. errorsExpected: ['serviceCheck_YARN', 'serviceCheck_TEZ', 'multipleDFS', 'monitoringCheck']
  308. },
  309. {
  310. services: ['HDFS','ZOOKEEPER', 'NAGIOS', 'GANGLIA'],
  311. confirmPopupCount: 0,
  312. errorsExpected: []
  313. }
  314. ];
  315. beforeEach(function() {
  316. c = App.WizardStep4Controller.create({});
  317. sinon.stub(App.router, 'send', Em.K);
  318. sinon.stub(c, 'submit', Em.K);
  319. sinon.spy(c, 'onPrimaryPopupCallback');
  320. });
  321. afterEach(function() {
  322. App.router.send.restore();
  323. c.submit.restore();
  324. c.onPrimaryPopupCallback.restore();
  325. });
  326. tests.forEach(function(test) {
  327. var message = 'Selected services: {0}. {1} errors should be confirmed'
  328. .format(test.services.join(', '), test.confirmPopupCount);
  329. it(message, function() {
  330. var runValidations = function() {
  331. c.serviceDependencyValidation();
  332. c.fileSystemServiceValidation();
  333. c.serviceMonitoringValidation();
  334. }
  335. c.set('content', generateSelectedServicesContent(test.services));
  336. runValidations();
  337. // errors count validation
  338. expect(c.get('errorStack.length')).to.equal(test.confirmPopupCount);
  339. // if errors detected than it should be shown
  340. if (test.errorsExpected) {
  341. test.errorsExpected.forEach(function(error, index, errors) {
  342. // validate current error
  343. var currentErrorObject = c.get('errorStack').findProperty('isShown', false);
  344. if (currentErrorObject) {
  345. expect(error).to.be.equal(currentErrorObject.id);
  346. // show current error
  347. var popup = c.showError(currentErrorObject);
  348. // submit popup
  349. popup.onPrimary();
  350. // onPrimaryPopupCallback should be called
  351. expect(c.onPrimaryPopupCallback.called).to.equal(true);
  352. // submit called
  353. expect(c.submit.called).to.equal(true);
  354. if (c.get('errorStack').length) {
  355. // current error isShown flag changed to true
  356. expect(currentErrorObject.isShown).to.equal(true);
  357. }
  358. runValidations();
  359. }
  360. });
  361. }
  362. });
  363. });
  364. });
  365. describe('#needToAddServicePopup', function() {
  366. Em.A([
  367. {
  368. m: 'one service',
  369. services: {selected: true, serviceName: 's1'},
  370. content: [Em.Object.create({serviceName: 's1', isSelected: false})],
  371. e: [true]
  372. },
  373. {
  374. m: 'many services',
  375. services: [{selected: true, serviceName: 's1'}, {selected: false, serviceName: 's2'}],
  376. content: [Em.Object.create({serviceName: 's1', isSelected: false}),
  377. Em.Object.create({serviceName: 's2', isSelected: true})],
  378. e: [true, false]
  379. }
  380. ]).forEach(function (test) {
  381. it(test.m, function () {
  382. sinon.stub(controller, 'submit', Em.K);
  383. controller.set('content', test.content);
  384. controller.needToAddServicePopup(test.services, '').onPrimary();
  385. expect(controller.submit.calledOnce).to.equal(true);
  386. expect(controller.mapProperty('isSelected')).to.eql(test.e);
  387. controller.submit.restore();
  388. });
  389. });
  390. });
  391. describe('#submit', function() {
  392. var c;
  393. var tests = [
  394. {
  395. isSubmitDisabled: true,
  396. validate: false,
  397. userCanProceed: false
  398. },
  399. {
  400. isSubmitDisabled: false,
  401. validate: false,
  402. userCanProceed: false
  403. },
  404. {
  405. isSubmitDisabled: false,
  406. validate: true,
  407. userCanProceed: true
  408. }
  409. ];
  410. beforeEach(function() {
  411. c = App.WizardStep4Controller.create();
  412. sinon.stub(App.router, 'send', Em.K);
  413. });
  414. afterEach(function() {
  415. App.router.send.restore();
  416. });
  417. tests.forEach(function(test) {
  418. var messageFormat = [
  419. test.isSubmitDisabled ? 'disabled' : 'enabled',
  420. test.validate ? 'success' : 'failed',
  421. test.userCanProceed ? '' : 'not'
  422. ];
  423. var message = String.prototype.format.apply('Submit btn: {0}. Validation: {1}. Can{2} move to the next step.', messageFormat);
  424. it(message, function() {
  425. c.reopen({
  426. isSubmitDisabled: test.isSubmitDisabled,
  427. validate: function() { return test.validate; }
  428. });
  429. c.clear();
  430. c.submit();
  431. expect(App.router.send.calledOnce).to.equal(test.userCanProceed);
  432. });
  433. })
  434. });
  435. describe('#dependencies', function() {
  436. var tests = [
  437. {
  438. services: ['HDFS'],
  439. dependencies: ['ZOOKEEPER']
  440. },
  441. {
  442. services: ['STORM'],
  443. dependencies: ['ZOOKEEPER']
  444. }
  445. ];
  446. tests.forEach(function(test) {
  447. var message = '{0} dependency should be {1}'.format(test.services.join(','), test.dependencies.join(','));
  448. it(message, function() {
  449. controller.clear();
  450. controller.set('content', generateSelectedServicesContent(test.services));
  451. var dependentServicesTest = [];
  452. test.services.forEach(function(serviceName) {
  453. var service = controller.filterProperty('serviceName', serviceName);
  454. service.forEach(function(item) {
  455. var dependencies = item.get('requiredServices');
  456. if(!!dependencies) {
  457. dependentServicesTest = dependentServicesTest.concat(dependencies);
  458. }
  459. });
  460. });
  461. expect(dependentServicesTest).to.be.eql(test.dependencies);
  462. });
  463. })
  464. });
  465. });