config_test.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867
  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. require('controllers/main/service/info/configs');
  20. var batchUtils = require('utils/batch_scheduled_requests');
  21. var mainServiceInfoConfigsController = null;
  22. function getController() {
  23. return App.MainServiceInfoConfigsController.create({
  24. dependentServiceNames: [],
  25. loadDependentConfigs: function () {
  26. return {done: Em.K}
  27. },
  28. loadConfigTheme: function () {
  29. return $.Deferred().resolve().promise();
  30. }
  31. });
  32. }
  33. describe("App.MainServiceInfoConfigsController", function () {
  34. beforeEach(function () {
  35. sinon.stub(App.themesMapper, 'generateAdvancedTabs').returns(Em.K);
  36. mainServiceInfoConfigsController = getController();
  37. });
  38. App.TestAliases.testAsComputedAlias(getController(), 'serviceConfigs', 'App.config.preDefinedServiceConfigs', 'array');
  39. afterEach(function() {
  40. App.themesMapper.generateAdvancedTabs.restore();
  41. });
  42. describe("#showSavePopup", function () {
  43. var tests = [
  44. {
  45. transitionCallback: false,
  46. callback: false,
  47. action: "onSave",
  48. m: "save configs without transitionCallback/callback",
  49. results: [
  50. {
  51. method: "restartServicePopup",
  52. called: true
  53. }
  54. ]
  55. },
  56. {
  57. transitionCallback: true,
  58. callback: true,
  59. action: "onSave",
  60. m: "save configs with transitionCallback/callback",
  61. results: [
  62. {
  63. method: "restartServicePopup",
  64. called: true
  65. }
  66. ]
  67. },
  68. {
  69. transitionCallback: false,
  70. callback: false,
  71. action: "onDiscard",
  72. m: "discard changes without transitionCallback/callback",
  73. results: [
  74. {
  75. method: "restartServicePopup",
  76. called: false
  77. }
  78. ]
  79. },
  80. {
  81. transitionCallback: false,
  82. callback: true,
  83. action: "onDiscard",
  84. m: "discard changes with callback",
  85. results: [
  86. {
  87. method: "restartServicePopup",
  88. called: false
  89. },
  90. {
  91. method: "callback",
  92. called: true
  93. },
  94. {
  95. field: "hash",
  96. value: "hash"
  97. }
  98. ]
  99. },
  100. {
  101. transitionCallback: true,
  102. callback: false,
  103. action: "onDiscard",
  104. m: "discard changes with transitionCallback",
  105. results: [
  106. {
  107. method: "restartServicePopup",
  108. called: false
  109. },
  110. {
  111. method: "transitionCallback",
  112. called: true
  113. }
  114. ]
  115. }
  116. ];
  117. beforeEach(function () {
  118. mainServiceInfoConfigsController.reopen({
  119. passwordConfigsAreChanged: false
  120. });
  121. sinon.stub(mainServiceInfoConfigsController, "get", function(key) {
  122. return key == 'isSubmitDisabled' ? false : Em.get(mainServiceInfoConfigsController, key);
  123. });
  124. sinon.stub(mainServiceInfoConfigsController, "restartServicePopup", Em.K);
  125. sinon.stub(mainServiceInfoConfigsController, "getHash", function () {
  126. return "hash"
  127. });
  128. });
  129. afterEach(function () {
  130. mainServiceInfoConfigsController.get.restore();
  131. mainServiceInfoConfigsController.restartServicePopup.restore();
  132. mainServiceInfoConfigsController.getHash.restore();
  133. });
  134. tests.forEach(function (t) {
  135. t.results.forEach(function (r) {
  136. describe(t.m + " " + r.method + " " + r.field, function () {
  137. beforeEach(function () {
  138. if (t.callback) {
  139. t.callback = sinon.stub();
  140. }
  141. if (t.transitionCallback) {
  142. t.transitionCallback = sinon.stub();
  143. }
  144. mainServiceInfoConfigsController.showSavePopup(t.transitionCallback, t.callback)[t.action]();
  145. });
  146. if (r.method) {
  147. if (r.method === 'callback') {
  148. it('callback is ' + (r.called ? '' : 'not') + ' called once', function () {
  149. expect(t.callback.calledOnce).to.equal(r.called);
  150. });
  151. }
  152. else {
  153. if (r.method === 'transitionCallback') {
  154. it('transitionCallback is ' + (r.called ? '' : 'not') + ' called once', function () {
  155. expect(t.transitionCallback.calledOnce).to.equal(r.called);
  156. });
  157. }
  158. else {
  159. it(r.method + ' is ' + (r.called ? '' : 'not') + ' called once', function () {
  160. expect(mainServiceInfoConfigsController[r.method].calledOnce).to.equal(r.called);
  161. });
  162. }
  163. }
  164. }
  165. else {
  166. if (r.field) {
  167. it(r.field + ' is equal to ' + r.value, function () {
  168. expect(mainServiceInfoConfigsController.get(r.field)).to.equal(r.value);
  169. });
  170. }
  171. }
  172. }, this);
  173. });
  174. }, this);
  175. });
  176. describe("#hasUnsavedChanges", function () {
  177. var cases = [
  178. {
  179. hash: null,
  180. hasUnsavedChanges: false,
  181. title: 'configs not rendered'
  182. },
  183. {
  184. hash: 'hash1',
  185. hasUnsavedChanges: true,
  186. title: 'with unsaved'
  187. },
  188. {
  189. hash: 'hash',
  190. hasUnsavedChanges: false,
  191. title: 'without unsaved'
  192. }
  193. ];
  194. beforeEach(function () {
  195. sinon.stub(mainServiceInfoConfigsController, "getHash", function () {
  196. return "hash"
  197. });
  198. });
  199. afterEach(function () {
  200. mainServiceInfoConfigsController.getHash.restore();
  201. });
  202. cases.forEach(function (item) {
  203. it(item.title, function () {
  204. mainServiceInfoConfigsController.set('hash', item.hash);
  205. expect(mainServiceInfoConfigsController.hasUnsavedChanges()).to.equal(item.hasUnsavedChanges);
  206. });
  207. });
  208. });
  209. describe("#showComponentsShouldBeRestarted", function () {
  210. var tests = [
  211. {
  212. input: {
  213. context: {
  214. restartRequiredHostsAndComponents: {
  215. 'publicHostName1': ['TaskTracker'],
  216. 'publicHostName2': ['JobTracker', 'TaskTracker']
  217. }
  218. }
  219. },
  220. components: "2 TaskTrackers, 1 JobTracker",
  221. text: Em.I18n.t('service.service.config.restartService.shouldBeRestarted').format(Em.I18n.t('common.components'))
  222. },
  223. {
  224. input: {
  225. context: {
  226. restartRequiredHostsAndComponents: {
  227. 'publicHostName1': ['TaskTracker']
  228. }
  229. }
  230. },
  231. components: "1 TaskTracker",
  232. text: Em.I18n.t('service.service.config.restartService.shouldBeRestarted').format(Em.I18n.t('common.component'))
  233. }
  234. ];
  235. beforeEach(function () {
  236. sinon.stub(mainServiceInfoConfigsController, "showItemsShouldBeRestarted", Em.K);
  237. });
  238. afterEach(function () {
  239. mainServiceInfoConfigsController.showItemsShouldBeRestarted.restore();
  240. });
  241. tests.forEach(function (t) {
  242. it("trigger showItemsShouldBeRestarted popup with components", function () {
  243. mainServiceInfoConfigsController.showComponentsShouldBeRestarted(t.input);
  244. expect(mainServiceInfoConfigsController.showItemsShouldBeRestarted.calledWith(t.components, t.text)).to.equal(true);
  245. });
  246. });
  247. });
  248. describe("#showHostsShouldBeRestarted", function () {
  249. var tests = [
  250. {
  251. input: {
  252. context: {
  253. restartRequiredHostsAndComponents: {
  254. 'publicHostName1': ['TaskTracker'],
  255. 'publicHostName2': ['JobTracker', 'TaskTracker']
  256. }
  257. }
  258. },
  259. hosts: "publicHostName1, publicHostName2",
  260. text: Em.I18n.t('service.service.config.restartService.shouldBeRestarted').format(Em.I18n.t('common.hosts'))
  261. },
  262. {
  263. input: {
  264. context: {
  265. restartRequiredHostsAndComponents: {
  266. 'publicHostName1': ['TaskTracker']
  267. }
  268. }
  269. },
  270. hosts: "publicHostName1",
  271. text: Em.I18n.t('service.service.config.restartService.shouldBeRestarted').format(Em.I18n.t('common.host'))
  272. }
  273. ];
  274. beforeEach(function () {
  275. sinon.stub(mainServiceInfoConfigsController, "showItemsShouldBeRestarted", Em.K);
  276. });
  277. afterEach(function () {
  278. mainServiceInfoConfigsController.showItemsShouldBeRestarted.restore();
  279. });
  280. tests.forEach(function (t) {
  281. it("trigger showItemsShouldBeRestarted popup with hosts", function () {
  282. mainServiceInfoConfigsController.showHostsShouldBeRestarted(t.input);
  283. expect(mainServiceInfoConfigsController.showItemsShouldBeRestarted.calledWith(t.hosts, t.text)).to.equal(true);
  284. });
  285. });
  286. });
  287. describe("#rollingRestartStaleConfigSlaveComponents", function () {
  288. var tests = [
  289. {
  290. componentName: {
  291. context: "ComponentName"
  292. },
  293. displayName: "displayName",
  294. passiveState: "ON"
  295. },
  296. {
  297. componentName: {
  298. context: "ComponentName1"
  299. },
  300. displayName: "displayName1",
  301. passiveState: "OFF"
  302. }
  303. ];
  304. beforeEach(function () {
  305. mainServiceInfoConfigsController.set("content", {displayName: "", passiveState: ""});
  306. sinon.stub(batchUtils, "launchHostComponentRollingRestart", Em.K);
  307. });
  308. afterEach(function () {
  309. batchUtils.launchHostComponentRollingRestart.restore();
  310. });
  311. tests.forEach(function (t) {
  312. it("trigger rollingRestartStaleConfigSlaveComponents", function () {
  313. mainServiceInfoConfigsController.set("content.displayName", t.displayName);
  314. mainServiceInfoConfigsController.set("content.passiveState", t.passiveState);
  315. mainServiceInfoConfigsController.rollingRestartStaleConfigSlaveComponents(t.componentName);
  316. expect(batchUtils.launchHostComponentRollingRestart.calledWith(t.componentName.context, t.displayName, t.passiveState == "ON", true)).to.equal(true);
  317. });
  318. });
  319. });
  320. describe("#restartAllStaleConfigComponents", function () {
  321. beforeEach(function () {
  322. sinon.stub(batchUtils, "restartAllServiceHostComponents", Em.K);
  323. });
  324. afterEach(function () {
  325. batchUtils.restartAllServiceHostComponents.restore();
  326. });
  327. it("trigger restartAllServiceHostComponents", function () {
  328. mainServiceInfoConfigsController.restartAllStaleConfigComponents().onPrimary();
  329. expect(batchUtils.restartAllServiceHostComponents.calledOnce).to.equal(true);
  330. });
  331. describe("trigger check last check point warning before triggering restartAllServiceHostComponents", function () {
  332. var mainConfigsControllerHdfsStarted = App.MainServiceInfoConfigsController.create({
  333. content: {
  334. serviceName: "HDFS",
  335. hostComponents: [{
  336. componentName: 'NAMENODE',
  337. workStatus: 'STARTED'
  338. }],
  339. restartRequiredHostsAndComponents: {
  340. "host1": ['NameNode'],
  341. "host2": ['DataNode', 'ZooKeeper']
  342. }
  343. }
  344. });
  345. var mainServiceItemController = App.MainServiceItemController.create({});
  346. beforeEach(function () {
  347. sinon.stub(mainServiceItemController, 'checkNnLastCheckpointTime', function() {
  348. return true;
  349. });
  350. sinon.stub(App.router, 'get', function(k) {
  351. if ('mainServiceItemController' === k) {
  352. return mainServiceItemController;
  353. }
  354. return Em.get(App.router, k);
  355. });
  356. mainConfigsControllerHdfsStarted.restartAllStaleConfigComponents();
  357. });
  358. afterEach(function () {
  359. mainServiceItemController.checkNnLastCheckpointTime.restore();
  360. App.router.get.restore();
  361. });
  362. it('checkNnLastCheckpointTime is called once', function () {
  363. expect(mainServiceItemController.checkNnLastCheckpointTime.calledOnce).to.equal(true);
  364. });
  365. });
  366. });
  367. describe("#doCancel", function () {
  368. beforeEach(function () {
  369. sinon.stub(Em.run, 'once', Em.K);
  370. });
  371. afterEach(function () {
  372. Em.run.once.restore();
  373. });
  374. it("should clear dependent configs", function() {
  375. mainServiceInfoConfigsController.set('groupsToSave', { HDFS: 'my cool group'});
  376. mainServiceInfoConfigsController.set('recommendations', Em.A([{name: 'prop_1'}]));
  377. mainServiceInfoConfigsController.doCancel();
  378. expect(App.isEmptyObject(mainServiceInfoConfigsController.get('recommendations'))).to.be.true;
  379. });
  380. });
  381. describe("#putChangedConfigurations", function () {
  382. var sc = [
  383. Em.Object.create({
  384. configs: [
  385. Em.Object.create({
  386. name: '_heapsize',
  387. value: '1024m'
  388. }),
  389. Em.Object.create({
  390. name: '_newsize',
  391. value: '1024m'
  392. }),
  393. Em.Object.create({
  394. name: '_maxnewsize',
  395. value: '1024m'
  396. })
  397. ]
  398. })
  399. ],
  400. scExc = [
  401. Em.Object.create({
  402. configs: [
  403. Em.Object.create({
  404. name: 'hadoop_heapsize',
  405. value: '1024m'
  406. }),
  407. Em.Object.create({
  408. name: 'yarn_heapsize',
  409. value: '1024m'
  410. }),
  411. Em.Object.create({
  412. name: 'nodemanager_heapsize',
  413. value: '1024m'
  414. }),
  415. Em.Object.create({
  416. name: 'resourcemanager_heapsize',
  417. value: '1024m'
  418. }),
  419. Em.Object.create({
  420. name: 'apptimelineserver_heapsize',
  421. value: '1024m'
  422. }),
  423. Em.Object.create({
  424. name: 'jobhistory_heapsize',
  425. value: '1024m'
  426. })
  427. ]
  428. })
  429. ];
  430. beforeEach(function () {
  431. sinon.stub(App.router, 'getClusterName', function() {
  432. return 'clName';
  433. });
  434. sinon.stub(App.ajax, "send", Em.K);
  435. });
  436. afterEach(function () {
  437. App.ajax.send.restore();
  438. App.router.getClusterName.restore();
  439. });
  440. it("ajax request to put cluster cfg", function () {
  441. mainServiceInfoConfigsController.set('stepConfigs', sc);
  442. expect(mainServiceInfoConfigsController.putChangedConfigurations([]));
  443. expect(App.ajax.send.calledOnce).to.be.true;
  444. });
  445. it('values should be parsed', function () {
  446. mainServiceInfoConfigsController.set('stepConfigs', sc);
  447. mainServiceInfoConfigsController.putChangedConfigurations([]);
  448. expect(mainServiceInfoConfigsController.get('stepConfigs')[0].get('configs').mapProperty('value').uniq()).to.eql(['1024m']);
  449. });
  450. it('values should not be parsed', function () {
  451. mainServiceInfoConfigsController.set('stepConfigs', scExc);
  452. mainServiceInfoConfigsController.putChangedConfigurations([]);
  453. expect(mainServiceInfoConfigsController.get('stepConfigs')[0].get('configs').mapProperty('value').uniq()).to.eql(['1024m']);
  454. });
  455. });
  456. describe("#isDirChanged", function() {
  457. describe("when service name is HDFS", function() {
  458. beforeEach(function() {
  459. mainServiceInfoConfigsController.set('content', Ember.Object.create ({ serviceName: 'HDFS' }));
  460. });
  461. describe("for hadoop 2", function() {
  462. var tests = [
  463. {
  464. it: "should set dirChanged to false if none of the properties exist",
  465. expect: false,
  466. config: Ember.Object.create ({})
  467. },
  468. {
  469. it: "should set dirChanged to true if dfs.namenode.name.dir is not default",
  470. expect: true,
  471. config: Ember.Object.create ({
  472. name: 'dfs.namenode.name.dir',
  473. isNotDefaultValue: true
  474. })
  475. },
  476. {
  477. it: "should set dirChanged to false if dfs.namenode.name.dir is default",
  478. expect: false,
  479. config: Ember.Object.create ({
  480. name: 'dfs.namenode.name.dir',
  481. isNotDefaultValue: false
  482. })
  483. },
  484. {
  485. it: "should set dirChanged to true if dfs.namenode.checkpoint.dir is not default",
  486. expect: true,
  487. config: Ember.Object.create ({
  488. name: 'dfs.namenode.checkpoint.dir',
  489. isNotDefaultValue: true
  490. })
  491. },
  492. {
  493. it: "should set dirChanged to false if dfs.namenode.checkpoint.dir is default",
  494. expect: false,
  495. config: Ember.Object.create ({
  496. name: 'dfs.namenode.checkpoint.dir',
  497. isNotDefaultValue: false
  498. })
  499. },
  500. {
  501. it: "should set dirChanged to true if dfs.datanode.data.dir is not default",
  502. expect: true,
  503. config: Ember.Object.create ({
  504. name: 'dfs.datanode.data.dir',
  505. isNotDefaultValue: true
  506. })
  507. },
  508. {
  509. it: "should set dirChanged to false if dfs.datanode.data.dir is default",
  510. expect: false,
  511. config: Ember.Object.create ({
  512. name: 'dfs.datanode.data.dir',
  513. isNotDefaultValue: false
  514. })
  515. }
  516. ];
  517. beforeEach(function() {
  518. sinon.stub(App, 'get').returns(true);
  519. });
  520. afterEach(function() {
  521. App.get.restore();
  522. });
  523. tests.forEach(function(test) {
  524. it(test.it, function() {
  525. mainServiceInfoConfigsController.set('stepConfigs', [Ember.Object.create ({ configs: [test.config], serviceName: 'HDFS' })]);
  526. expect(mainServiceInfoConfigsController.isDirChanged()).to.equal(test.expect);
  527. })
  528. });
  529. });
  530. });
  531. });
  532. describe("#formatConfigValues", function () {
  533. var t = {
  534. configs: [
  535. Em.Object.create({ name: "p1", value: " v1 v1 ", displayType: "" }),
  536. Em.Object.create({ name: "p2", value: true, displayType: "" }),
  537. Em.Object.create({ name: "p3", value: " d1 ", displayType: "directory" }),
  538. Em.Object.create({ name: "p4", value: " d1 d2 d3 ", displayType: "directories" }),
  539. Em.Object.create({ name: "p5", value: " v1 ", displayType: "password" }),
  540. Em.Object.create({ name: "p6", value: " v ", displayType: "host" }),
  541. Em.Object.create({ name: "javax.jdo.option.ConnectionURL", value: " v1 ", displayType: "string" }),
  542. Em.Object.create({ name: "oozie.service.JPAService.jdbc.url", value: " v1 ", displayType: "string" })
  543. ],
  544. result: [
  545. Em.Object.create({ name: "p1", value: " v1 v1", displayType: "" }),
  546. Em.Object.create({ name: "p2", value: "true", displayType: "" }),
  547. Em.Object.create({ name: "p3", value: "d1", displayType: "directory" }),
  548. Em.Object.create({ name: "p4", value: "d1,d2,d3", displayType: "directories" }),
  549. Em.Object.create({ name: "p5", value: " v1 ", displayType: "password" }),
  550. Em.Object.create({ name: "p6", value: "v", displayType: "host" }),
  551. Em.Object.create({ name: "javax.jdo.option.ConnectionURL", value: " v1", displayType: "string" }),
  552. Em.Object.create({ name: "oozie.service.JPAService.jdbc.url", value: " v1", displayType: "string" })
  553. ]
  554. };
  555. it("format config values", function () {
  556. mainServiceInfoConfigsController.formatConfigValues(t.configs);
  557. expect(t.configs).to.deep.equal(t.result);
  558. });
  559. });
  560. describe("#putConfigGroupChanges", function() {
  561. var t = {
  562. data: {
  563. ConfigGroup: {
  564. id: "id"
  565. }
  566. },
  567. request: [{
  568. ConfigGroup: {
  569. id: "id"
  570. }
  571. }]
  572. };
  573. beforeEach(function() {
  574. sinon.spy($,"ajax");
  575. });
  576. afterEach(function() {
  577. $.ajax.restore();
  578. });
  579. it("updates configs groups", function() {
  580. mainServiceInfoConfigsController.putConfigGroupChanges(t.data);
  581. expect(JSON.parse($.ajax.args[0][0].data)).to.deep.equal(t.request);
  582. });
  583. });
  584. describe("#checkOverrideProperty", function () {
  585. var tests = [{
  586. overrideToAdd: {
  587. name: "name1",
  588. filename: "filename1"
  589. },
  590. componentConfig: {
  591. configs: [
  592. {
  593. name: "name1",
  594. filename: "filename2"
  595. },
  596. {
  597. name: "name1",
  598. filename: "filename1"
  599. }
  600. ]
  601. },
  602. add: true,
  603. m: "add property"
  604. },
  605. {
  606. overrideToAdd: {
  607. name: "name1"
  608. },
  609. componentConfig: {
  610. configs: [
  611. {
  612. name: "name2"
  613. }
  614. ]
  615. },
  616. add: false,
  617. m: "don't add property, different names"
  618. },
  619. {
  620. overrideToAdd: {
  621. name: "name1",
  622. filename: "filename1"
  623. },
  624. componentConfig: {
  625. configs: [
  626. {
  627. name: "name1",
  628. filename: "filename2"
  629. }
  630. ]
  631. },
  632. add: false,
  633. m: "don't add property, different filenames"
  634. },
  635. {
  636. overrideToAdd: null,
  637. componentConfig: {},
  638. add: false,
  639. m: "don't add property, overrideToAdd is null"
  640. }];
  641. beforeEach(function() {
  642. sinon.stub(App.config,"createOverride", Em.K)
  643. });
  644. afterEach(function() {
  645. App.config.createOverride.restore();
  646. });
  647. tests.forEach(function(t) {
  648. it(t.m, function() {
  649. mainServiceInfoConfigsController.set("overrideToAdd", t.overrideToAdd);
  650. mainServiceInfoConfigsController.checkOverrideProperty(t.componentConfig);
  651. if(t.add) {
  652. expect(App.config.createOverride.calledWith(t.overrideToAdd)).to.equal(true);
  653. expect(mainServiceInfoConfigsController.get("overrideToAdd")).to.equal(null);
  654. } else {
  655. expect(App.config.createOverride.calledOnce).to.equal(false);
  656. }
  657. });
  658. });
  659. });
  660. describe("#trackRequest()", function () {
  661. after(function(){
  662. mainServiceInfoConfigsController.get('requestsInProgress').clear();
  663. });
  664. it("should set requestsInProgress", function () {
  665. mainServiceInfoConfigsController.get('requestsInProgress').clear();
  666. mainServiceInfoConfigsController.trackRequest({'request': {}});
  667. expect(mainServiceInfoConfigsController.get('requestsInProgress')[0]).to.eql({'request': {}});
  668. });
  669. });
  670. describe("#setCompareDefaultGroupConfig", function() {
  671. beforeEach(function() {
  672. sinon.stub(mainServiceInfoConfigsController, "getComparisonConfig").returns("compConfig");
  673. sinon.stub(mainServiceInfoConfigsController, "getMockComparisonConfig").returns("mockConfig");
  674. sinon.stub(mainServiceInfoConfigsController, "hasCompareDiffs").returns(true);
  675. });
  676. afterEach(function() {
  677. mainServiceInfoConfigsController.getComparisonConfig.restore();
  678. mainServiceInfoConfigsController.getMockComparisonConfig.restore();
  679. mainServiceInfoConfigsController.hasCompareDiffs.restore();
  680. });
  681. it("empty service config passed, expect that setCompareDefaultGroupConfig will not run anything", function() {
  682. expect(mainServiceInfoConfigsController.setCompareDefaultGroupConfig({}).compareConfigs.length).to.equal(0);
  683. });
  684. it("empty service config and comparison passed, expect that setCompareDefaultGroupConfig will not run anything", function() {
  685. expect(mainServiceInfoConfigsController.setCompareDefaultGroupConfig({},{}).compareConfigs).to.eql(["compConfig"]);
  686. });
  687. it("expect that serviceConfig.compareConfigs will be getMockComparisonConfig", function() {
  688. expect(mainServiceInfoConfigsController.setCompareDefaultGroupConfig({isUserProperty: true}, null)).to.eql({compareConfigs: ["mockConfig"], isUserProperty: true, isComparison: true, hasCompareDiffs: true});
  689. });
  690. it("expect that serviceConfig.compareConfigs will be getComparisonConfig", function() {
  691. expect(mainServiceInfoConfigsController.setCompareDefaultGroupConfig({isUserProperty: true}, {})).to.eql({compareConfigs: ["compConfig"], isUserProperty: true, isComparison: true, hasCompareDiffs: true});
  692. });
  693. it("expect that serviceConfig.compareConfigs will be getComparisonConfig (2)", function() {
  694. expect(mainServiceInfoConfigsController.setCompareDefaultGroupConfig({isReconfigurable: true}, {})).to.eql({compareConfigs: ["compConfig"], isReconfigurable: true, isComparison: true, hasCompareDiffs: true});
  695. });
  696. it("expect that serviceConfig.compareConfigs will be getComparisonConfig (3)", function() {
  697. expect(mainServiceInfoConfigsController.setCompareDefaultGroupConfig({isReconfigurable: true, isMock: true}, {})).to.eql({compareConfigs: ["compConfig"], isReconfigurable: true, isMock: true, isComparison: true, hasCompareDiffs: true});
  698. });
  699. it("property was created during upgrade and have no comparison, compare with 'Undefined' value should be created", function() {
  700. expect(mainServiceInfoConfigsController.setCompareDefaultGroupConfig({name: 'prop1', isUserProperty: false}, null)).to.eql({
  701. name: 'prop1', isUserProperty: false, compareConfigs: ["mockConfig"],
  702. isComparison: true, hasCompareDiffs: true
  703. });
  704. });
  705. });
  706. describe('#showSaveConfigsPopup', function () {
  707. var bodyView;
  708. describe('#bodyClass', function () {
  709. beforeEach(function() {
  710. sinon.stub(App.StackService, 'find').returns([{dependentServiceNames: []}]);
  711. sinon.stub(App.ajax, 'send', Em.K);
  712. // default implementation
  713. bodyView = mainServiceInfoConfigsController.showSaveConfigsPopup().get('bodyClass').create({
  714. parentView: Em.View.create()
  715. });
  716. });
  717. afterEach(function() {
  718. App.ajax.send.restore();
  719. App.StackService.find.restore();
  720. });
  721. describe('#componentsFilterSuccessCallback', function () {
  722. it('check components with unknown state', function () {
  723. bodyView = mainServiceInfoConfigsController.showSaveConfigsPopup('', true, '', {}, '', 'unknown', '').get('bodyClass').create({
  724. parentView: Em.View.create()
  725. });
  726. bodyView.componentsFilterSuccessCallback({
  727. items: [
  728. {
  729. ServiceComponentInfo: {
  730. total_count: 4,
  731. started_count: 2,
  732. installed_count: 1,
  733. component_name: 'c1'
  734. },
  735. host_components: [
  736. {HostRoles: {host_name: 'h1'}}
  737. ]
  738. }
  739. ]
  740. });
  741. var unknownHosts = bodyView.get('unknownHosts');
  742. expect(unknownHosts.length).to.equal(1);
  743. expect(unknownHosts[0]).to.eql({name: 'h1', components: 'C1'});
  744. });
  745. });
  746. });
  747. });
  748. describe('#errorsCount', function () {
  749. it('should ignore configs with widgets (enhanced configs)', function () {
  750. mainServiceInfoConfigsController.reopen({selectedService: Em.Object.create({
  751. configsWithErrors: Em.A([
  752. Em.Object.create({widget: {}}),
  753. Em.Object.create({widget: null})
  754. ])
  755. })});
  756. expect(mainServiceInfoConfigsController.get('errorsCount')).to.equal(1);
  757. });
  758. });
  759. describe('#_onLoadComplete', function () {
  760. beforeEach(function () {
  761. sinon.stub(Em.run, 'next', Em.K);
  762. mainServiceInfoConfigsController.setProperties({
  763. dataIsLoaded: false,
  764. versionLoaded: false,
  765. isInit: true
  766. });
  767. });
  768. afterEach(function () {
  769. Em.run.next.restore();
  770. });
  771. it('should update flags', function () {
  772. mainServiceInfoConfigsController._onLoadComplete();
  773. expect(mainServiceInfoConfigsController.get('dataIsLoaded')).to.be.true;
  774. expect(mainServiceInfoConfigsController.get('versionLoaded')).to.be.true;
  775. expect(mainServiceInfoConfigsController.get('isInit')).to.be.false;
  776. });
  777. });
  778. describe('#hasCompareDiffs', function () {
  779. it('should return false for `password`-configs', function () {
  780. var hasCompareDiffs = mainServiceInfoConfigsController.hasCompareDiffs({displayType: 'password'}, {});
  781. expect(hasCompareDiffs).to.be.false;
  782. });
  783. });
  784. });