assign_master_controller_test.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994
  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 App = require('app');
  19. var stringUtils = require('utils/string_utils');
  20. var numberUtils = require('utils/number_utils');
  21. var blueprintUtils = require('utils/blueprint');
  22. var testHelpers = require('test/helpers');
  23. require('models/stack_service_component');
  24. describe('App.AssignMasterOnStep7Controller', function () {
  25. var view;
  26. beforeEach(function () {
  27. view = App.AssignMasterOnStep7Controller.create();
  28. });
  29. describe("#content", function () {
  30. it("content is correct", function () {
  31. view.set('configWidgetContext.controller', Em.Object.create({
  32. content: {'name': 'name'}
  33. }));
  34. view.propertyDidChange('content');
  35. expect(view.get('content')).to.be.eql({'name': 'name'});
  36. });
  37. it("content is null", function () {
  38. view.set('configWidgetContext.controller', Em.Object.create({
  39. content: null
  40. }));
  41. view.propertyDidChange('content');
  42. expect(view.get('content')).to.be.empty;
  43. });
  44. });
  45. describe("#execute()", function () {
  46. var context = Em.Object.create({
  47. controller: {
  48. content: {}
  49. }
  50. });
  51. beforeEach(function() {
  52. sinon.stub(view, 'showPopup');
  53. sinon.stub(view, 'removeMasterComponent');
  54. sinon.stub(view, 'getPendingBatchRequests');
  55. });
  56. afterEach(function() {
  57. view.getPendingBatchRequests.restore();
  58. view.showPopup.restore();
  59. view.removeMasterComponent.restore();
  60. });
  61. it("should set configWidgetContext", function() {
  62. view.execute(context, 'ADD', {componentName: 'C1'});
  63. expect(view.get('configWidgetContext')).to.be.eql(context);
  64. });
  65. it("should set content", function() {
  66. view.execute(context, 'ADD', {componentName: 'C1'});
  67. expect(view.get('content')).to.be.eql({});
  68. });
  69. it("should set configActionComponent", function() {
  70. view.execute(context, 'ADD', {componentName: 'C1'});
  71. expect(view.get('configActionComponent')).to.be.eql({componentName: 'C1'});
  72. });
  73. it("should call showPopup when action is ADD", function() {
  74. view.execute(context, 'ADD', {componentName: 'C1'});
  75. expect(view.showPopup.calledWith({componentName: 'C1'})).to.be.true;
  76. });
  77. it("should call getPendingBatchRequests when action is ADD and HIVE_SERVER_INTERACTIVE", function() {
  78. view.execute(context, 'ADD', {componentName: 'HIVE_SERVER_INTERACTIVE'});
  79. expect(view.getPendingBatchRequests.calledWith({componentName: 'HIVE_SERVER_INTERACTIVE'})).to.be.true;
  80. });
  81. it("should call removeMasterComponent when action is DELETE", function() {
  82. view.execute(context, 'DELETE', {componentName: 'C1'});
  83. expect(view.removeMasterComponent.calledOnce).to.be.true;
  84. expect(view.get('mastersToCreate')).to.be.eql(['C1']);
  85. });
  86. });
  87. describe("#showAssignComponentPopup()", function () {
  88. beforeEach(function() {
  89. sinon.stub(view, 'loadMasterComponentHosts');
  90. sinon.stub(App.ModalPopup, 'show');
  91. });
  92. afterEach(function() {
  93. view.loadMasterComponentHosts.restore();
  94. App.ModalPopup.show.restore();
  95. });
  96. it("loadMasterComponentHosts should be called", function() {
  97. view.reopen({
  98. content: {
  99. controllerName: null
  100. }
  101. });
  102. view.showAssignComponentPopup();
  103. expect(view.loadMasterComponentHosts.calledOnce).to.be.true;
  104. expect(App.ModalPopup.show.calledOnce).to.be.true;
  105. });
  106. it("loadMasterComponentHosts should not be called", function() {
  107. view.reopen({
  108. content: {
  109. controllerName: 'ctrl1'
  110. }
  111. });
  112. view.showAssignComponentPopup();
  113. expect(view.loadMasterComponentHosts.called).to.be.false;
  114. expect(App.ModalPopup.show.calledOnce).to.be.true;
  115. });
  116. });
  117. describe("#showInstallServicesPopup()", function () {
  118. var mock = Em.Object.create({
  119. config: Em.Object.create({
  120. initialValue: 'init',
  121. value: '',
  122. displayName: 'c1'
  123. }),
  124. setValue: Em.K,
  125. toggleProperty: Em.K,
  126. sendRequestRorDependentConfigs: Em.K
  127. });
  128. beforeEach(function() {
  129. sinon.stub(stringUtils, 'getFormattedStringFromArray');
  130. sinon.stub(mock, 'setValue');
  131. sinon.stub(mock, 'toggleProperty');
  132. sinon.stub(mock, 'sendRequestRorDependentConfigs');
  133. sinon.spy(App.ModalPopup, 'show');
  134. });
  135. afterEach(function() {
  136. stringUtils.getFormattedStringFromArray.restore();
  137. mock.setValue.restore();
  138. mock.toggleProperty.restore();
  139. mock.sendRequestRorDependentConfigs.restore();
  140. App.ModalPopup.show.restore();
  141. });
  142. it("test", function() {
  143. view.set('configWidgetContext', mock);
  144. var popup = view.showInstallServicesPopup();
  145. expect(App.ModalPopup.show.calledOnce).to.be.true;
  146. popup.onPrimary();
  147. expect(mock.get('config.value')).to.be.equal('init');
  148. expect(mock.setValue.calledWith('init')).to.be.true;
  149. });
  150. });
  151. describe("#removeMasterComponent()", function () {
  152. var mock = {
  153. setDBProperty: Em.K
  154. };
  155. beforeEach(function() {
  156. sinon.stub(App.router, 'get').returns(mock);
  157. sinon.stub(mock, 'setDBProperty');
  158. sinon.stub(view, 'clearComponentsToBeAdded');
  159. sinon.stub(App.HostComponent, 'find').returns([
  160. Em.Object.create({
  161. componentName: 'C1',
  162. hostName: 'host1'
  163. })
  164. ]);
  165. });
  166. afterEach(function() {
  167. App.router.get.restore();
  168. mock.setDBProperty.restore();
  169. view.clearComponentsToBeAdded.restore();
  170. App.HostComponent.find.restore();
  171. });
  172. it("should set masterComponentHosts", function() {
  173. view.reopen({
  174. content: Em.Object.create({
  175. controllerName: 'ctrl1',
  176. masterComponentHosts: [
  177. {component: 'C1'},
  178. {component: 'C2'}
  179. ],
  180. componentsFromConfigs: ["C1","C2"],
  181. recommendationsHostGroups: {
  182. blueprint: {host_groups: [{name: 'host-group-1', components: [{name: 'C1'}, {name: 'C2'}]}]},
  183. blueprint_cluster_binding: {host_groups: [{name: 'host-group-1', hosts: [{fqdn: 'localhost'}]}]}
  184. }
  185. }),
  186. configWidgetContext: {
  187. config: Em.Object.create()
  188. }
  189. });
  190. view.set('mastersToCreate', ['C2']);
  191. view.removeMasterComponent();
  192. expect(view.get('content.masterComponentHosts')).to.be.eql([{component: 'C1'}]);
  193. expect(view.get('content.recommendationsHostGroups').blueprint).to.be.eql({host_groups: [{name: 'host-group-1', components: [{name: 'C1'}]}]});
  194. });
  195. it("should call clearComponentsToBeAdded when controllerName is null", function() {
  196. view.setProperties({
  197. content: Em.Object.create(),
  198. mastersToCreate: ['C1'],
  199. configWidgetContext: {
  200. config: Em.Object.create()
  201. }
  202. });
  203. view.removeMasterComponent();
  204. expect(view.clearComponentsToBeAdded.calledWith('C1')).to.be.true;
  205. expect(App.get('componentToBeDeleted')).to.be.eql(Em.Object.create({
  206. componentName: 'C1',
  207. hostName: 'host1'
  208. }));
  209. });
  210. });
  211. describe("#renderHostInfo()", function () {
  212. beforeEach(function() {
  213. sinon.stub(view, 'getHosts').returns([]);
  214. });
  215. afterEach(function() {
  216. view.getHosts.restore();
  217. });
  218. it("should make general request to get hosts", function() {
  219. view.reopen({
  220. content: Em.Object.create({
  221. controllerName: 'name'
  222. })
  223. });
  224. view.renderHostInfo();
  225. var args = testHelpers.findAjaxRequest('name', 'hosts.high_availability.wizard');
  226. expect(args).exists;
  227. });
  228. it("should make request for installer to get hosts", function() {
  229. view.reopen({
  230. content: Em.Object.create({
  231. controllerName: 'installerController'
  232. })
  233. });
  234. view.renderHostInfo();
  235. var args = testHelpers.findAjaxRequest('name', 'hosts.info.install');
  236. expect(args).exists;
  237. });
  238. });
  239. describe("#loadMasterComponentHosts()", function () {
  240. beforeEach(function() {
  241. sinon.stub(App.HostComponent, 'find').returns([
  242. Em.Object.create({
  243. componentName: 'C1'
  244. }),
  245. Em.Object.create({
  246. componentName: 'C2'
  247. })
  248. ]);
  249. sinon.stub(App, 'get').returns(['C2']);
  250. });
  251. afterEach(function() {
  252. App.get.restore();
  253. App.HostComponent.find.restore();
  254. });
  255. it("should set master components", function() {
  256. view.loadMasterComponentHosts();
  257. expect(view.get('masterComponentHosts').mapProperty('component')).to.be.eql(['C2']);
  258. });
  259. });
  260. describe("#getAllMissingDependentServices()", function () {
  261. beforeEach(function() {
  262. sinon.stub(App.StackServiceComponent, 'find').returns(Em.Object.create({
  263. stackService: Em.Object.create({
  264. requiredServices: ['S1', 'S2']
  265. })
  266. }));
  267. sinon.stub(App.Service, 'find').returns([
  268. {serviceName: 'S1'}
  269. ]);
  270. sinon.stub(App.StackService, 'find', function(input) {
  271. return Em.Object.create({displayName: input});
  272. });
  273. });
  274. afterEach(function() {
  275. App.StackServiceComponent.find.restore();
  276. App.Service.find.restore();
  277. App.StackService.find.restore();
  278. });
  279. it("test", function() {
  280. view.set('configActionComponent', Em.Object.create({
  281. componentName: 'C1'
  282. }));
  283. expect(view.getAllMissingDependentServices()).to.be.eql(['S2']);
  284. });
  285. });
  286. describe('#getPendingBatchRequests', function() {
  287. it('App.ajax.send should be called', function() {
  288. view.getPendingBatchRequests({componentName: 'C1'});
  289. var args = testHelpers.findAjaxRequest('name', 'request_schedule.get.pending');
  290. expect(args[0]).to.be.eql({
  291. name : 'request_schedule.get.pending',
  292. sender: view,
  293. error : 'pendingBatchRequestsAjaxError',
  294. success: 'pendingBatchRequestsAjaxSuccess',
  295. data: {
  296. hostComponent: {componentName: 'C1'}
  297. }
  298. });
  299. });
  300. });
  301. describe('#pendingBatchRequestsAjaxError', function() {
  302. beforeEach(function() {
  303. sinon.stub(App, 'showAlertPopup');
  304. });
  305. afterEach(function() {
  306. App.showAlertPopup.restore();
  307. });
  308. it('should call showAlertPopup, invalid JSON', function() {
  309. view.pendingBatchRequestsAjaxError({responseText: null});
  310. expect(App.showAlertPopup.calledWith(
  311. Em.I18n.t('services.service.actions.run.yarnRefreshQueues.error'),
  312. Em.I18n.t('services.service.actions.run.yarnRefreshQueues.error'),
  313. null
  314. )).to.be.true;
  315. });
  316. it('should call showAlertPopup, valid JSON', function() {
  317. view.pendingBatchRequestsAjaxError({responseText: '{"message":"foo"}'});
  318. expect(App.showAlertPopup.calledWith(
  319. Em.I18n.t('services.service.actions.run.yarnRefreshQueues.error'),
  320. Em.I18n.t('services.service.actions.run.yarnRefreshQueues.error') + 'foo',
  321. null
  322. )).to.be.true;
  323. });
  324. });
  325. describe('#pendingBatchRequestsAjaxSuccess', function() {
  326. var configWidgetContext = Em.Object.create({
  327. config: Em.Object.create({
  328. initialValue: 'iv1',
  329. value: 'v1'
  330. }),
  331. controller: {
  332. forceUpdateBoundaries: false
  333. },
  334. setValue: sinon.spy(),
  335. sendRequestRorDependentConfigs: sinon.spy()
  336. });
  337. beforeEach(function() {
  338. this.mock = sinon.stub(view, 'shouldShowAlertOnBatchRequest');
  339. sinon.stub(App, 'showAlertPopup', function() {
  340. arguments[2].apply({hide: Em.K});
  341. });
  342. sinon.stub(view, 'showPopup');
  343. view.set('configWidgetContext', configWidgetContext);
  344. });
  345. afterEach(function() {
  346. this.mock.restore();
  347. App.showAlertPopup.restore();
  348. view.showPopup.restore();
  349. });
  350. it('showPopup should be called', function() {
  351. this.mock.returns(false);
  352. view.pendingBatchRequestsAjaxSuccess({}, {}, {hostComponent: {componentName: 'C1'}});
  353. expect(view.showPopup.calledWith({componentName: 'C1'})).to.be.true;
  354. });
  355. describe('showAlertPopup should be called', function() {
  356. beforeEach(function() {
  357. this.mock.returns(true);
  358. view.pendingBatchRequestsAjaxSuccess({}, {}, {hostComponent: {componentName: 'C1'}});
  359. });
  360. it('App.showAlertPopup is called', function () {
  361. expect(App.showAlertPopup.calledWith(
  362. Em.I18n.t('services.service.actions.hsi.alertPopup.header'),
  363. Em.I18n.t('services.service.actions.hsi.alertPopup.body')
  364. )).to.be.true;
  365. });
  366. it('config value is correct', function () {
  367. expect(configWidgetContext.get('config.value')).to.be.equal('iv1');
  368. });
  369. it('forceUpdateBoundaries is true', function () {
  370. expect(configWidgetContext.get('controller.forceUpdateBoundaries')).to.be.true;
  371. });
  372. it('configWidgetContext.setValue is called', function () {
  373. expect(configWidgetContext.setValue.calledWith('iv1')).to.be.true;
  374. });
  375. it('configWidgetContext.sendRequestRorDependentConfigs is called', function () {
  376. expect(configWidgetContext.sendRequestRorDependentConfigs.calledWith(
  377. configWidgetContext.get('config')
  378. )).to.be.true;
  379. });
  380. });
  381. });
  382. describe('#shouldShowAlertOnBatchRequest', function() {
  383. var testCases = [
  384. {
  385. input: {},
  386. expected: false
  387. },
  388. {
  389. input: {
  390. items: []
  391. },
  392. expected: false
  393. },
  394. {
  395. input: {
  396. items: [
  397. {
  398. RequestSchedule: {
  399. batch: {
  400. batch_requests: [
  401. {
  402. request_type: 'ADD',
  403. request_uri: ''
  404. }
  405. ]
  406. }
  407. }
  408. }
  409. ]
  410. },
  411. expected: false
  412. },
  413. {
  414. input: {
  415. items: [
  416. {
  417. RequestSchedule: {
  418. batch: {
  419. batch_requests: [
  420. {
  421. request_type: 'DELETE',
  422. request_uri: 'HIVE_SERVER_INTERACTIVE'
  423. }
  424. ]
  425. }
  426. }
  427. }
  428. ]
  429. },
  430. expected: true
  431. }
  432. ];
  433. testCases.forEach(function(test) {
  434. it('should return ' + test.expected + ' when data = ' + JSON.stringify(test.input), function() {
  435. expect(view.shouldShowAlertOnBatchRequest(test.input)).to.be.equal(test.expected);
  436. });
  437. });
  438. });
  439. describe('#updateComponent and showAddControl should be false for component', function() {
  440. beforeEach(function() {
  441. sinon.stub(App.StackServiceComponent, 'find').returns([
  442. Em.Object.create({
  443. componentName: 'C1',
  444. stackService: Em.Object.create({
  445. isInstalled: false
  446. })
  447. })
  448. ]);
  449. });
  450. afterEach(function() {
  451. App.StackServiceComponent.find.restore();
  452. });
  453. it('showRemoveControl ', function() {
  454. var component = Em.Object.create({
  455. component_name: 'C1',
  456. showAddControl: true,
  457. showRemoveControl: true
  458. });
  459. view.setProperties({
  460. mastersToCreate: [],
  461. selectedServicesMasters: [ component, {component_name: 'C2'} ]
  462. });
  463. view.updateComponent('C1');
  464. expect(component.get('showAddControl')).to.be.false;
  465. expect(component.get('showRemoveControl')).to.be.false;
  466. });
  467. });
  468. describe('#saveRecommendationsHostGroups', function() {
  469. beforeEach(function() {
  470. sinon.stub(view, 'getSelectedHostName').returns('host1');
  471. });
  472. afterEach(function() {
  473. view.getSelectedHostName.restore();
  474. });
  475. it('should add component to recommendations', function() {
  476. var recommendationsHostGroups = {
  477. blueprint_cluster_binding: {
  478. host_groups: [
  479. {
  480. name: 'g1',
  481. hosts: [
  482. {
  483. fqdn: 'host1'
  484. }
  485. ]
  486. }
  487. ]
  488. },
  489. blueprint: {
  490. host_groups: [
  491. {
  492. name: 'g1',
  493. components: []
  494. }
  495. ]
  496. }
  497. };
  498. view.reopen({
  499. mastersToCreate: ['C1'],
  500. content: Em.Object.create({
  501. recommendationsHostGroups: recommendationsHostGroups
  502. })
  503. });
  504. view.saveRecommendationsHostGroups();
  505. expect(view.get('content.recommendationsHostGroups')).to.be.eql(Object.assign(recommendationsHostGroups, {
  506. blueprint: {
  507. host_groups: [
  508. {
  509. name: 'g1',
  510. components: [{name: 'C1'}]
  511. }
  512. ]
  513. }
  514. }));
  515. });
  516. });
  517. describe('#setGlobalComponentToBeAdded', function() {
  518. it('should set componentToBeAdded', function() {
  519. view.setGlobalComponentToBeAdded('C1', 'host1');
  520. expect(App.get('componentToBeAdded')).to.be.eql(Em.Object.create({
  521. componentName: 'C1',
  522. hostNames: ['host1']
  523. }));
  524. });
  525. });
  526. describe('#clearComponentsToBeDeleted', function() {
  527. it('should clear componentToBeDeleted', function() {
  528. App.set('componentToBeDeleted', Em.Object.create({
  529. componentName: 'C1'
  530. }));
  531. view.clearComponentsToBeDeleted('C1');
  532. expect(App.get('componentToBeDeleted')).to.be.empty;
  533. });
  534. });
  535. describe('#clearComponentsToBeAdded', function() {
  536. it('should clear componentToBeAdded', function() {
  537. App.set('componentToBeAdded', Em.Object.create({
  538. componentName: 'C1'
  539. }));
  540. view.clearComponentsToBeAdded('C1');
  541. expect(App.get('componentToBeAdded')).to.be.empty;
  542. });
  543. });
  544. describe('#showPopup', function() {
  545. beforeEach(function() {
  546. this.mock = sinon.stub(view, 'getAllMissingDependentServices');
  547. sinon.stub(view, 'showInstallServicesPopup');
  548. sinon.stub(view, 'showAssignComponentPopup');
  549. });
  550. afterEach(function() {
  551. this.mock.restore();
  552. view.showInstallServicesPopup.restore();
  553. view.showAssignComponentPopup.restore();
  554. });
  555. it('showAssignComponentPopup should be called', function() {
  556. this.mock.returns([]);
  557. view.showPopup({componentName: 'C1'});
  558. expect(view.get('mastersToCreate')).to.be.eql(['C1']);
  559. expect(view.showAssignComponentPopup.calledOnce).to.be.true;
  560. });
  561. it('showInstallServicesPopup should be called', function() {
  562. this.mock.returns([{}]);
  563. view.reopen({
  564. content: Em.Object.create()
  565. });
  566. view.showPopup({componentName: 'C1'});
  567. expect(view.showInstallServicesPopup.calledWith([{}])).to.be.true;
  568. });
  569. });
  570. describe('#submit', function() {
  571. var configWidgetContext = Em.Object.create({
  572. controller: {
  573. forceUpdateBoundaries: false,
  574. stepConfigs: [
  575. Em.Object.create({
  576. serviceName: 'S1',
  577. configs: []
  578. }),
  579. Em.Object.create({
  580. serviceName: 'MISC',
  581. configs: []
  582. })
  583. ],
  584. selectedService: {
  585. serviceName: 'S1'
  586. }
  587. },
  588. config: Em.Object.create({
  589. configAction: {
  590. dependencies: []
  591. }
  592. })
  593. });
  594. beforeEach(function() {
  595. sinon.stub(view, 'resolveDependencies');
  596. sinon.stub(view, 'saveMasterComponentHosts');
  597. sinon.stub(view, 'saveRecommendationsHostGroups');
  598. sinon.stub(view, 'setGlobalComponentToBeAdded');
  599. sinon.stub(view, 'clearComponentsToBeDeleted');
  600. sinon.stub(App, 'get').returns({
  601. getKDCSessionState: Em.clb
  602. });
  603. sinon.stub(view, 'getSelectedHostName').returns('host1');
  604. view.setProperties({
  605. configWidgetContext: configWidgetContext,
  606. configActionComponent: { componentName: 'C1'},
  607. popup: {
  608. hide: sinon.spy()
  609. }
  610. });
  611. });
  612. afterEach(function() {
  613. App.get.restore();
  614. view.resolveDependencies.restore();
  615. view.clearComponentsToBeDeleted.restore();
  616. view.setGlobalComponentToBeAdded.restore();
  617. view.saveRecommendationsHostGroups.restore();
  618. view.saveMasterComponentHosts.restore();
  619. view.getSelectedHostName.restore();
  620. });
  621. it('saveMasterComponentHosts should be called when controllerName defined', function() {
  622. view.reopen({
  623. content: {
  624. controllerName: 'ctrl1'
  625. }
  626. });
  627. view.submit();
  628. expect(view.saveMasterComponentHosts.calledOnce).to.be.true;
  629. });
  630. it('saveRecommendationsHostGroups should be called when controllerName defined', function() {
  631. view.reopen({
  632. content: {
  633. controllerName: 'ctrl1'
  634. }
  635. });
  636. view.submit();
  637. expect(view.saveRecommendationsHostGroups.calledOnce).to.be.true;
  638. });
  639. it('setGlobalComponentToBeAdded should be called when controllerName undefined', function() {
  640. view.reopen({
  641. content: {
  642. controllerName: undefined
  643. }
  644. });
  645. view.submit();
  646. expect(view.setGlobalComponentToBeAdded.calledWith('C1', 'host1')).to.be.true;
  647. });
  648. it('clearComponentsToBeDeleted should be called when controllerName undefined', function() {
  649. view.reopen({
  650. content: {
  651. controllerName: undefined
  652. }
  653. });
  654. view.submit();
  655. expect(view.clearComponentsToBeDeleted.calledWith('C1')).to.be.true;
  656. });
  657. it('resolveDependencies should be called', function() {
  658. view.submit();
  659. expect(view.resolveDependencies.calledWith([], [])).to.be.true;
  660. });
  661. it('hide should be called', function() {
  662. view.submit();
  663. expect(view.get('popup').hide.calledOnce).to.be.true;
  664. });
  665. it('configActionComponent should be set', function() {
  666. view.submit();
  667. expect(view.get('configWidgetContext.config.configActionComponent')).to.be.eql({
  668. componentName: 'C1',
  669. hostName: 'host1'
  670. });
  671. });
  672. });
  673. describe('#resolveDependencies', function() {
  674. var initializer = {
  675. setup: sinon.spy(),
  676. initialValue: sinon.stub().returns({value: 'val1'}),
  677. cleanup: sinon.spy()
  678. };
  679. var dependencies = {
  680. properties: [
  681. {
  682. name: 'p1',
  683. fileName: 'file1.xml',
  684. nameTemplate: '{{bar}}',
  685. isHostsList: true,
  686. isHostsArray: false
  687. }
  688. ],
  689. initializer: {
  690. name: 'i1',
  691. setupKeys: ['bar']
  692. }
  693. };
  694. var context = Em.Object.create({
  695. controller: {
  696. selectedService: {
  697. serviceName: 'S1'
  698. }
  699. }
  700. });
  701. var serviceConfigs = [
  702. Em.Object.create({
  703. name: 'foo',
  704. filename: 'file1.xml',
  705. value: 'val1'
  706. })
  707. ];
  708. beforeEach(function() {
  709. sinon.stub(view, 'getDependenciesForeignKeys').returns({
  710. bar: 'foo'
  711. });
  712. sinon.stub(App, 'get').returns(initializer);
  713. sinon.stub(view, 'getMasterComponents');
  714. sinon.stub(view, 'saveRecommendations');
  715. sinon.stub(App.config, 'updateHostsListValue');
  716. sinon.stub(App.config, 'get').returns({
  717. 'file1.xml': Em.Object.create({
  718. serviceName: 'S1'
  719. })
  720. });
  721. view.resolveDependencies(dependencies, serviceConfigs, context);
  722. });
  723. afterEach(function() {
  724. App.config.get.restore();
  725. view.getDependenciesForeignKeys.restore();
  726. App.get.restore();
  727. view.getMasterComponents.restore();
  728. view.saveRecommendations.restore();
  729. App.config.updateHostsListValue.restore();
  730. });
  731. it('initializer.setup should be called', function() {
  732. expect(initializer.setup.calledWith({bar: 'foo'})).to.be.true;
  733. });
  734. it('initializer.setup initialValue be called', function() {
  735. expect(initializer.initialValue.calledWith({
  736. name: 'foo',
  737. fileName: 'file1.xml'
  738. })).to.be.true;
  739. });
  740. it('initializer.cleanup should be called', function() {
  741. expect(initializer.cleanup.called).to.be.true;
  742. });
  743. it('saveRecommendations should be called', function() {
  744. expect(view.saveRecommendations.calledWith(context)).to.be.true;
  745. });
  746. it('App.config.updateHostsListValue should be called', function() {
  747. expect(App.config.updateHostsListValue.getCall(0).args).to.be.eql([
  748. {
  749. foo: 'val1'
  750. },
  751. 'file1.xml',
  752. 'foo',
  753. undefined,
  754. false
  755. ]);
  756. });
  757. });
  758. describe('#saveMasterComponentHosts', function() {
  759. var mockCtrl = {
  760. saveMasterComponentHosts: sinon.spy(),
  761. loadMasterComponentHosts: sinon.spy()
  762. };
  763. beforeEach(function() {
  764. sinon.stub(App.router, 'get').returns(mockCtrl);
  765. view.reopen({
  766. content: Em.Object.create({
  767. componentsFromConfigs: []
  768. })
  769. });
  770. view.set('mastersToCreate', [
  771. {}
  772. ]);
  773. });
  774. afterEach(function() {
  775. App.router.get.restore();
  776. });
  777. it('saveMasterComponentHosts should be called', function() {
  778. view.saveMasterComponentHosts();
  779. expect(mockCtrl.saveMasterComponentHosts.calledWith(view, true)).to.be.true;
  780. });
  781. it('loadMasterComponentHosts should be called', function() {
  782. view.saveMasterComponentHosts();
  783. expect(mockCtrl.loadMasterComponentHosts.calledWith(true)).to.be.true;
  784. });
  785. it('componentsFromConfigs should be set', function() {
  786. view.saveMasterComponentHosts();
  787. expect(view.get('content.componentsFromConfigs')).to.be.eql([{}]);
  788. });
  789. });
  790. describe('#getSelectedHostName', function() {
  791. it('should return host of component', function() {
  792. view.set('selectedServicesMasters', [
  793. {
  794. component_name: 'C1',
  795. selectedHost: 'host1'
  796. }
  797. ]);
  798. expect(view.getSelectedHostName('C1')).to.be.equal('host1');
  799. });
  800. });
  801. describe('#saveRecommendations', function() {
  802. var mockCtrl = {
  803. loadRecommendationsSuccess: sinon.spy(),
  804. wizardController: {
  805. name: 'installerController'
  806. }
  807. };
  808. var context = Em.Object.create({
  809. controller: mockCtrl
  810. });
  811. it('loadRecommendationsSuccess should be called', function() {
  812. view.set('configWidgetContext', {
  813. config: Em.Object.create({
  814. fileName: 'foo.xml',
  815. name: 'bar',
  816. initialValue: 'iv1'
  817. })
  818. });
  819. view.saveRecommendations(context, {});
  820. expect(mockCtrl.loadRecommendationsSuccess.getCall(0).args).to.be.eql([
  821. {
  822. resources: [
  823. {
  824. recommendations: {
  825. blueprint: {
  826. configurations: {}
  827. }
  828. }
  829. }
  830. ]
  831. }, null, {
  832. dataToSend: {
  833. changed_configurations: [{
  834. type: 'foo',
  835. name: 'bar',
  836. old_value: 'iv1'
  837. }]
  838. }
  839. }
  840. ]);
  841. });
  842. });
  843. describe('#getDependenciesForeignKeys', function() {
  844. var dependencies = {
  845. foreignKeys: [
  846. {
  847. fileName: 'foo.xml',
  848. propertyName: 'c1',
  849. key: 'k1'
  850. }
  851. ]
  852. };
  853. var serviceConfigs = [
  854. Em.Object.create({
  855. filename: 'foo.xml',
  856. name: 'c1',
  857. value: 'val1'
  858. })
  859. ];
  860. it('should return foreignKeys map', function() {
  861. expect(view.getDependenciesForeignKeys(dependencies, serviceConfigs)).to.be.eql({
  862. k1: 'val1'
  863. });
  864. });
  865. });
  866. describe('#getMasterComponents', function() {
  867. var dependencies = {
  868. initializer: {
  869. componentNames: ['C1']
  870. }
  871. };
  872. var context = Em.Object.create({
  873. controller: {
  874. content: {
  875. masterComponentHosts: [
  876. {
  877. component: 'C1',
  878. hostName: 'host2'
  879. }
  880. ]
  881. }
  882. }
  883. });
  884. beforeEach(function() {
  885. sinon.stub(blueprintUtils, 'getComponentForHosts').returns({
  886. host1: ['C1']
  887. });
  888. });
  889. afterEach(function() {
  890. blueprintUtils.getComponentForHosts.restore();
  891. });
  892. it('should return master components when controllerName undefined', function() {
  893. view.set('content.controllerName', undefined);
  894. expect(view.getMasterComponents(dependencies, context)).to.be.eql([
  895. {
  896. component: 'C1',
  897. hostName: 'host1',
  898. isInstalled: true
  899. }
  900. ]);
  901. });
  902. it('should return master components when controllerName valid', function() {
  903. view.set('content.controllerName', 'ctrl1');
  904. expect(view.getMasterComponents(dependencies, context)).to.be.eql([
  905. {
  906. component: 'C1',
  907. hostName: 'host2',
  908. isInstalled: true
  909. }
  910. ]);
  911. });
  912. });
  913. });