step4_test.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  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',
  25. '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 MapReduce2 isSelected to true when YARN is selected',
  122. condition: {
  123. 'YARN': true,
  124. 'HBASE': true,
  125. 'ZOOKEEPER': true,
  126. 'HIVE': true,
  127. 'MAPREDUCE2': true
  128. },
  129. result: {
  130. 'MAPREDUCE2': true
  131. }
  132. },
  133. {
  134. title: 'should set MapReduce2 isSelected to false when YARN is not selected',
  135. condition: {
  136. 'YARN': false,
  137. 'HBASE': true,
  138. 'ZOOKEEPER': true,
  139. 'HIVE': false,
  140. 'MAPREDUCE2': true
  141. },
  142. result: {
  143. 'MAPREDUCE2': false
  144. }
  145. },
  146. {
  147. title: 'should set MAPREDUCE2 isSelected to true when YARN is selected',
  148. condition: {
  149. 'HBASE': true,
  150. 'ZOOKEEPER': true,
  151. 'HIVE': false,
  152. 'YARN': true,
  153. 'MAPREDUCE2': true
  154. },
  155. result: {
  156. 'MAPREDUCE2': true
  157. }
  158. },
  159. {
  160. title: 'should set MAPREDUCE2 isSelected to false when YARN is not selected',
  161. condition: {
  162. 'HBASE': true,
  163. 'ZOOKEEPER': true,
  164. 'HIVE': true,
  165. 'YARN': false,
  166. 'MAPREDUCE2': true
  167. },
  168. result: {
  169. 'MAPREDUCE2': false
  170. }
  171. }
  172. ];
  173. testCases.forEach(function(testCase){
  174. it(testCase.title, function () {
  175. controller.clear();
  176. for(var id in testCase.condition) {
  177. controller.pushObject(Ember.Object.create({
  178. 'serviceName':id, 'isSelected': testCase.condition[id], 'canBeSelected': true, 'isInstalled': false,
  179. coSelectedServices: function() {
  180. return App.StackService.coSelected[this.get('serviceName')] || [];
  181. }.property('serviceName')
  182. }));
  183. }
  184. controller.setGroupedServices();
  185. for(var service in testCase.result) {
  186. expect(controller.findProperty('serviceName', service).get('isSelected')).to.equal(testCase.result[service]);
  187. }
  188. });
  189. }, this);
  190. });
  191. describe('#addValidationError()', function() {
  192. var tests = [
  193. {
  194. errorObjects: [
  195. {
  196. id: 'serviceCheck_ZOOKEEPER',
  197. shouldBeAdded: true
  198. },
  199. {
  200. id: 'serviceCheck_YARN',
  201. shouldBeAdded: true
  202. }
  203. ],
  204. expectedIds: ['serviceCheck_ZOOKEEPER', 'serviceCheck_YARN']
  205. },
  206. {
  207. errorObjects: [
  208. {
  209. id: 'fsCheck',
  210. shouldBeAdded: true
  211. },
  212. {
  213. id: 'fsCheck',
  214. shouldBeAdded: false
  215. }
  216. ],
  217. expectedIds: ['fsCheck']
  218. }
  219. ];
  220. beforeEach(function() {
  221. controller.clear();
  222. controller.set('errorStack', []);
  223. });
  224. tests.forEach(function(test) {
  225. var message = 'Erorrs {0} thrown. errorStack property should contains ids: {1}'
  226. .format(test.errorObjects.mapProperty('id').join(', '), test.expectedIds.join(', '));
  227. it(message, function() {
  228. test.errorObjects.forEach(function(errorObject) {
  229. expect(controller.addValidationError(errorObject)).to.equal(errorObject.shouldBeAdded);
  230. });
  231. expect(controller.get('errorStack').mapProperty('id')).to.eql(test.expectedIds);
  232. });
  233. })
  234. });
  235. describe('#validate()', function() {
  236. var tests = [
  237. {
  238. services: ['HDFS','ZOOKEEPER'],
  239. errorsExpected: []
  240. },
  241. {
  242. services: ['ZOOKEEPER'],
  243. errorsExpected: []
  244. },
  245. {
  246. services: ['HDFS'],
  247. errorsExpected: ['serviceCheck_ZOOKEEPER']
  248. },
  249. {
  250. services: ['HDFS', 'TEZ', 'ZOOKEEPER'],
  251. errorsExpected: ['serviceCheck_YARN']
  252. },
  253. {
  254. services: ['HDFS', 'ZOOKEEPER', 'FALCON', 'NAGIOS'],
  255. errorsExpected: ['serviceCheck_OOZIE']
  256. },
  257. {
  258. services: ['HDFS', 'ZOOKEEPER', 'GANGLIA', 'NAGIOS', 'HIVE'],
  259. errorsExpected: ['serviceCheck_YARN']
  260. },
  261. {
  262. services: ['HDFS', 'GLUSTERFS', 'ZOOKEEPER', 'HIVE'],
  263. errorsExpected: ['serviceCheck_YARN', 'multipleDFS']
  264. },
  265. {
  266. services: ['HDFS','ZOOKEEPER', 'NAGIOS', 'GANGLIA'],
  267. errorsExpected: []
  268. }
  269. ];
  270. tests.forEach(function(test) {
  271. var message = '{0} selected validation should be {1}, errors with ids: {2} present'
  272. .format(test.services.join(','), !!test.validationPassed ? 'passed' : 'failed', test.errorsExpected.join(','));
  273. it(message, function() {
  274. controller.clear();
  275. controller.set('content', generateSelectedServicesContent(test.services));
  276. controller.validate();
  277. expect(controller.get('errorStack').mapProperty('id')).to.be.eql(test.errorsExpected);
  278. });
  279. })
  280. });
  281. describe('#onPrimaryPopupCallback()', function() {
  282. var c;
  283. var tests = [
  284. {
  285. services: ['HDFS','ZOOKEEPER'],
  286. confirmPopupCount: 0,
  287. errorsExpected: []
  288. },
  289. {
  290. services: ['ZOOKEEPER'],
  291. confirmPopupCount: 0,
  292. errorsExpected: []
  293. },
  294. {
  295. services: ['HDFS', 'GLUSTERFS', 'ZOOKEEPER', 'HIVE'],
  296. confirmPopupCount: 2,
  297. errorsExpected: ['serviceCheck_YARN', 'serviceCheck_TEZ', 'multipleDFS']
  298. },
  299. {
  300. services: ['HDFS','ZOOKEEPER', 'NAGIOS', 'GANGLIA'],
  301. confirmPopupCount: 0,
  302. errorsExpected: []
  303. }
  304. ];
  305. beforeEach(function() {
  306. c = App.WizardStep4Controller.create({});
  307. sinon.stub(App.router, 'send', Em.K);
  308. sinon.stub(c, 'submit', Em.K);
  309. sinon.spy(c, 'onPrimaryPopupCallback');
  310. });
  311. afterEach(function() {
  312. App.router.send.restore();
  313. c.submit.restore();
  314. c.onPrimaryPopupCallback.restore();
  315. });
  316. tests.forEach(function(test) {
  317. var message = 'Selected services: {0}. {1} errors should be confirmed'
  318. .format(test.services.join(', '), test.confirmPopupCount);
  319. it(message, function() {
  320. var runValidations = function() {
  321. c.serviceDependencyValidation();
  322. c.fileSystemServiceValidation();
  323. };
  324. c.set('content', generateSelectedServicesContent(test.services));
  325. runValidations();
  326. // errors count validation
  327. expect(c.get('errorStack.length')).to.equal(test.confirmPopupCount);
  328. // if errors detected than it should be shown
  329. if (test.errorsExpected) {
  330. test.errorsExpected.forEach(function(error, index, errors) {
  331. // validate current error
  332. var currentErrorObject = c.get('errorStack').findProperty('isShown', false);
  333. if (currentErrorObject) {
  334. expect(error).to.be.equal(currentErrorObject.id);
  335. // show current error
  336. var popup = c.showError(currentErrorObject);
  337. // submit popup
  338. popup.onPrimary();
  339. // onPrimaryPopupCallback should be called
  340. expect(c.onPrimaryPopupCallback.called).to.equal(true);
  341. // submit called
  342. expect(c.submit.called).to.equal(true);
  343. if (c.get('errorStack').length) {
  344. // current error isShown flag changed to true
  345. expect(currentErrorObject.isShown).to.equal(true);
  346. }
  347. runValidations();
  348. }
  349. });
  350. }
  351. });
  352. });
  353. });
  354. describe('#needToAddServicePopup', function() {
  355. Em.A([
  356. {
  357. m: 'one service',
  358. services: {selected: true, serviceName: 's1'},
  359. content: [Em.Object.create({serviceName: 's1', isSelected: false})],
  360. e: [true]
  361. },
  362. {
  363. m: 'many services',
  364. services: [{selected: true, serviceName: 's1'}, {selected: false, serviceName: 's2'}],
  365. content: [Em.Object.create({serviceName: 's1', isSelected: false}),
  366. Em.Object.create({serviceName: 's2', isSelected: true})],
  367. e: [true, false]
  368. }
  369. ]).forEach(function (test) {
  370. it(test.m, function () {
  371. sinon.stub(controller, 'submit', Em.K);
  372. controller.set('content', test.content);
  373. controller.needToAddServicePopup(test.services, '').onPrimary();
  374. expect(controller.submit.calledOnce).to.equal(true);
  375. expect(controller.mapProperty('isSelected')).to.eql(test.e);
  376. controller.submit.restore();
  377. });
  378. });
  379. });
  380. describe('#submit', function() {
  381. var c;
  382. var tests = [
  383. {
  384. isSubmitDisabled: true,
  385. validate: false,
  386. userCanProceed: false
  387. },
  388. {
  389. isSubmitDisabled: false,
  390. validate: false,
  391. userCanProceed: false
  392. },
  393. {
  394. isSubmitDisabled: false,
  395. validate: true,
  396. userCanProceed: true
  397. }
  398. ];
  399. beforeEach(function() {
  400. c = App.WizardStep4Controller.create();
  401. sinon.stub(App.router, 'send', Em.K);
  402. });
  403. afterEach(function() {
  404. App.router.send.restore();
  405. });
  406. tests.forEach(function(test) {
  407. var messageFormat = [
  408. test.isSubmitDisabled ? 'disabled' : 'enabled',
  409. test.validate ? 'success' : 'failed',
  410. test.userCanProceed ? '' : 'not'
  411. ];
  412. var message = String.prototype.format.apply('Submit btn: {0}. Validation: {1}. Can{2} move to the next step.', messageFormat);
  413. it(message, function() {
  414. c.reopen({
  415. isSubmitDisabled: test.isSubmitDisabled,
  416. validate: function() { return test.validate; }
  417. });
  418. c.clear();
  419. c.submit();
  420. expect(App.router.send.calledOnce).to.equal(test.userCanProceed);
  421. });
  422. })
  423. });
  424. describe('#dependencies', function() {
  425. var tests = [
  426. {
  427. services: ['HDFS'],
  428. dependencies: ['ZOOKEEPER']
  429. },
  430. {
  431. services: ['STORM'],
  432. dependencies: ['ZOOKEEPER']
  433. }
  434. ];
  435. tests.forEach(function(test) {
  436. var message = '{0} dependency should be {1}'.format(test.services.join(','), test.dependencies.join(','));
  437. it(message, function() {
  438. controller.clear();
  439. controller.set('content', generateSelectedServicesContent(test.services));
  440. var dependentServicesTest = [];
  441. test.services.forEach(function(serviceName) {
  442. var service = controller.filterProperty('serviceName', serviceName);
  443. service.forEach(function(item) {
  444. var dependencies = item.get('requiredServices');
  445. if(!!dependencies) {
  446. dependentServicesTest = dependentServicesTest.concat(dependencies);
  447. }
  448. });
  449. });
  450. expect(dependentServicesTest).to.be.eql(test.dependencies);
  451. });
  452. })
  453. });
  454. });