config_recommendation_parser_test.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  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 helpers = require('test/helpers');
  20. describe('App.ConfigRecommendationParser', function() {
  21. var mixinObject = Em.Controller.extend(App.ConfigRecommendationParser, {});
  22. var instanceObject = mixinObject.create({});
  23. var recommendationObject = {
  24. 'fileName1': {
  25. 'properties': {
  26. 'p1': 'v1'
  27. },
  28. 'property_attributes': {
  29. 'p2': {
  30. 'delete': true
  31. },
  32. 'p3': {
  33. 'maximum': 100,
  34. 'minimum': 1
  35. }
  36. }
  37. }
  38. };
  39. var configs = [
  40. Em.Object.create({
  41. name: 'p1',
  42. filename: 'fileName1'
  43. }),
  44. Em.Object.create({
  45. name: 'p2',
  46. filename: 'fileName1'
  47. }),
  48. Em.Object.create({
  49. name: 'p3',
  50. filename: 'fileName1'
  51. })
  52. ];
  53. beforeEach(function() {
  54. instanceObject.set('stepConfigs', []);
  55. });
  56. describe('#parseRecommendations', function() {
  57. describe('#recommendartion parsed', function() {
  58. beforeEach(function() {
  59. instanceObject.reopen({
  60. updateCallback: Em.K,
  61. removeCallback: Em.K,
  62. updateBoundariesCallback: Em.K
  63. });
  64. sinon.stub(App.configsCollection, 'getConfigByName', function(name, fileName) {
  65. return { name: name, filename: fileName };
  66. });
  67. sinon.stub(instanceObject, 'allowUpdateProperty').returns(true);
  68. sinon.spy(instanceObject, 'updateCallback');
  69. sinon.spy(instanceObject, 'removeCallback');
  70. sinon.spy(instanceObject, 'updateBoundariesCallback');
  71. instanceObject.parseRecommendations(recommendationObject, configs, null, null,
  72. instanceObject.updateCallback, instanceObject.removeCallback, instanceObject.updateBoundariesCallback);
  73. });
  74. afterEach(function() {
  75. App.configsCollection.getConfigByName.restore();
  76. instanceObject.allowUpdateProperty.restore();
  77. instanceObject.updateCallback.restore();
  78. instanceObject.removeCallback.restore();
  79. instanceObject.updateBoundariesCallback.restore();
  80. });
  81. it('updateCallback', function() {
  82. expect(instanceObject.updateCallback.calledWith(configs[0], 'v1', null, null)).to.be.true;
  83. });
  84. it('removeCallback', function() {
  85. expect(instanceObject.removeCallback.calledWith(configs[1], configs, null, null)).to.be.true;
  86. });
  87. it('updateBoundariesCallback maximum', function() {
  88. expect(instanceObject.updateBoundariesCallback.calledWith({ name: 'p3', filename: 'fileName1' },
  89. 'maximum', 100, 'p3', 'fileName1', null)).to.be.true;
  90. });
  91. it('updateBoundariesCallback minimum', function() {
  92. expect(instanceObject.updateBoundariesCallback.calledWith({ name: 'p3', filename: 'fileName1' },
  93. 'minimum', 1, 'p3', 'fileName1', null)).to.be.true;
  94. });
  95. });
  96. it('#recommendation parsing failed', function() {
  97. expect(instanceObject.parseRecommendations.bind(instanceObject, null)).to.throw(App.ObjectTypeError);
  98. });
  99. it('#recommendation parsing failed', function() {
  100. expect(instanceObject.parseRecommendations.bind(instanceObject, {}, null)).to.throw(App.ArrayTypeError);
  101. });
  102. it('#recommendation parsing failed', function() {
  103. expect(instanceObject.parseRecommendations.bind(instanceObject, {}, [Em.Object.create({name: 'cfg1'})])).to.throw(App.FunctionTypeError);
  104. });
  105. });
  106. describe('#addByRecommendations', function(){
  107. var _recommendationObject = {
  108. 'file-name': {
  109. 'properties': {
  110. 'p1': 'v1'
  111. }
  112. }
  113. };
  114. var stepConfig = App.ServiceConfig.create({
  115. serviceName: 'serviceName1',
  116. configs: []
  117. });
  118. var cases = [
  119. {
  120. m: 'allowUpdateProperty true',
  121. allowUpdateProperty: true
  122. },
  123. {
  124. m: 'allowUpdateProperty false',
  125. allowUpdateProperty: false
  126. }
  127. ];
  128. cases.forEach(function (c) {
  129. describe('non error case', function() {
  130. beforeEach(function() {
  131. sinon.stub(App.config, 'getStepConfigForProperty').returns(stepConfig);
  132. sinon.stub(instanceObject, 'allowUpdateProperty').returns(c.allowUpdateProperty);
  133. sinon.stub(instanceObject, '_createNewProperty').returns(App.ServiceConfigProperty.create({
  134. 'name': 'p1',
  135. 'filename': 'file-name'
  136. }));
  137. instanceObject.addByRecommendations(_recommendationObject, []);
  138. });
  139. afterEach(function() {
  140. App.config.getStepConfigForProperty.restore();
  141. instanceObject.allowUpdateProperty.restore();
  142. instanceObject._createNewProperty.restore();
  143. });
  144. if (c.allowUpdateProperty) {
  145. it ('adds new property', function() {
  146. expect(instanceObject._createNewProperty.calledWith('p1', 'file-name', 'serviceName1', 'v1', [])).to.be.true;
  147. expect(stepConfig.get('configs.0.name')).to.equal('p1');
  148. expect(stepConfig.get('configs.0.filename')).to.equal('file-name');
  149. });
  150. } else {
  151. it('does not add property error', function() {
  152. expect(instanceObject._createNewProperty.called).to.be.false;
  153. });
  154. }
  155. });
  156. });
  157. it('throws error', function() {
  158. expect(instanceObject.addByRecommendations.bind(instanceObject, null)).to.throw(App.ObjectTypeError);
  159. });
  160. });
  161. describe('#_updateConfigByRecommendation', function() {
  162. var cases = [
  163. {
  164. 'allowUpdateProperty': true,
  165. 'updateInitialOnRecommendations': true,
  166. 'm': 'allowUpdateProperty and update init on recommendation',
  167. 'result': {
  168. 'recommendedValue': 'recommendedValue',
  169. 'value': 'recommendedValue',
  170. 'initialValue': 'recommendedValue'
  171. }
  172. },
  173. {
  174. 'allowUpdateProperty': true,
  175. 'updateInitialOnRecommendations': false,
  176. 'm': 'allowUpdateProperty and do not update init on recommendation',
  177. 'result': {
  178. 'recommendedValue': 'recommendedValue',
  179. 'value': 'recommendedValue',
  180. 'initialValue': null
  181. }
  182. },
  183. {
  184. 'allowUpdateProperty': false,
  185. 'updateInitialOnRecommendations': false,
  186. 'm': 'do not allowUpdateProperty and do not update init on recommendation',
  187. 'result': {
  188. 'recommendedValue': 'recommendedValue',
  189. 'value': null,
  190. 'initialValue': null
  191. }
  192. }
  193. ];
  194. cases.forEach(function(c) {
  195. describe('update recommendation', function() {
  196. beforeEach(function() {
  197. sinon.spy(instanceObject, 'applyRecommendation');
  198. sinon.stub(instanceObject, 'allowUpdateProperty').returns(c.allowUpdateProperty);
  199. sinon.stub(instanceObject, 'updateInitialOnRecommendations').returns(c.updateInitialOnRecommendations);
  200. });
  201. afterEach(function() {
  202. instanceObject.allowUpdateProperty.restore();
  203. instanceObject.updateInitialOnRecommendations.restore();
  204. instanceObject.applyRecommendation.restore();
  205. });
  206. it(c.m, function() {
  207. expect(instanceObject._updateConfigByRecommendation({
  208. 'recommendedValue': null,
  209. 'value': null,
  210. 'initialValue': null
  211. }, 'recommendedValue')).to.eql(c.result);
  212. });
  213. if(c.allowUpdateProperty) {
  214. it('runs applyRecommendation', function() {
  215. instanceObject._updateConfigByRecommendation({}, 'recommendedValue');
  216. expect(instanceObject.applyRecommendation.calledOnce).to.be.true;
  217. });
  218. }
  219. });
  220. });
  221. it('throws error for configs', function() {
  222. expect(instanceObject._updateConfigByRecommendation.bind(instanceObject, null)).to.throw(App.ObjectTypeError);
  223. });
  224. });
  225. describe('#_createNewProperty', function() {
  226. beforeEach(function() {
  227. sinon.spy(instanceObject, 'applyRecommendation');
  228. sinon.stub(instanceObject, '_getCoreProperties').returns({
  229. 'value': 'recommendedValue',
  230. 'recommendedValue': 'recommendedValue',
  231. 'initialValue': 'initialValue',
  232. 'savedValue': null
  233. });
  234. sinon.stub(App.config, 'getDefaultConfig', function(name, fileName, coreObject) {
  235. coreObject.name = name;
  236. coreObject.filename = fileName;
  237. return coreObject;
  238. });
  239. });
  240. afterEach(function() {
  241. instanceObject.applyRecommendation.restore();
  242. instanceObject._getCoreProperties.restore();
  243. App.config.getDefaultConfig.restore();
  244. });
  245. it('adds new config', function() {
  246. var res = {
  247. 'value': 'recommendedValue',
  248. 'recommendedValue': 'recommendedValue',
  249. 'savedValue': null,
  250. 'name': 'name',
  251. 'filename': 'fileName',
  252. 'errorMessage': ''
  253. };
  254. var test = instanceObject._createNewProperty('name', 'fileName', 'recommendedValue', null);
  255. helpers.nestedExpect([res], [test]);
  256. expect(instanceObject.applyRecommendation.calledOnce).to.be.true;
  257. });
  258. it('throws error for name/fileName/serviceName', function() {
  259. expect(instanceObject._createNewProperty.bind(instanceObject)).to.throw(App.NotNullTypeError);
  260. expect(instanceObject._createNewProperty.bind(instanceObject, 'name')).to.throw(App.NotNullTypeError);
  261. });
  262. });
  263. describe('#_removeConfigByRecommendation', function() {
  264. beforeEach(function() {
  265. sinon.spy(instanceObject, 'applyRecommendation');
  266. });
  267. afterEach(function() {
  268. instanceObject.applyRecommendation.restore();
  269. });
  270. it('removes config', function() {
  271. var configCollection = [
  272. {'name': 'cfg1'},
  273. {'name': 'cfg2'}
  274. ];
  275. instanceObject._removeConfigByRecommendation(configCollection[0], configCollection);
  276. expect(configCollection[0]).to.eql({'name': 'cfg2'});
  277. expect(instanceObject.applyRecommendation.calledOnce).to.be.true;
  278. });
  279. it('throws error', function() {
  280. expect(instanceObject._removeConfigByRecommendation.bind(instanceObject, null)).to.throw(App.ObjectTypeError);
  281. });
  282. it('throws error (2)', function() {
  283. expect(instanceObject._removeConfigByRecommendation.bind(instanceObject, {}, null)).to.throw(App.ArrayTypeError);
  284. });
  285. });
  286. describe('#_updateBoundaries', function() {
  287. it('sets appropriate attribute', function() {
  288. expect(instanceObject._updateBoundaries({}, 'attr1', 'v1')).to.eql({ valueAttributes: {'attr1': 'v1'}});
  289. });
  290. });
  291. describe('#_getCoreProperties', function() {
  292. var cases = [
  293. {
  294. 'useInitialValue': true,
  295. 'updateInitialOnRecommendations': true,
  296. 'm': 'use init and update init on recommendation',
  297. 'result': {
  298. 'value': 'recommendedValue',
  299. 'recommendedValue': 'recommendedValue',
  300. 'initialValue': 'recommendedValue',
  301. 'savedValue': null,
  302. 'isNotSaved': false
  303. }
  304. },
  305. {
  306. 'useInitialValue': true,
  307. 'updateInitialOnRecommendations': false,
  308. 'm': 'use init and do not update init on recommendation',
  309. 'result': {
  310. 'value': 'recommendedValue',
  311. 'recommendedValue': 'recommendedValue',
  312. 'initialValue': 'initValue',
  313. 'savedValue': null,
  314. 'isNotSaved': false
  315. }
  316. },
  317. {
  318. 'useInitialValue': false,
  319. 'updateInitialOnRecommendations': false,
  320. 'm': 'do not use init and do not update init on recommendation',
  321. 'result': {
  322. 'value': 'recommendedValue',
  323. 'recommendedValue': 'recommendedValue',
  324. 'initialValue': 'initValue',
  325. 'savedValue': 'initValue',
  326. 'isNotSaved': false
  327. }
  328. }
  329. ];
  330. cases.forEach(function(c) {
  331. describe('get core object for different cases', function() {
  332. beforeEach(function() {
  333. sinon.stub(instanceObject, 'useInitialValue').returns(c.useInitialValue);
  334. sinon.stub(instanceObject, 'updateInitialOnRecommendations').returns(c.updateInitialOnRecommendations);
  335. });
  336. afterEach(function() {
  337. instanceObject.useInitialValue.restore();
  338. instanceObject.updateInitialOnRecommendations.restore();
  339. });
  340. it(c.m, function() {
  341. expect(instanceObject._getCoreProperties('serviceName', 'recommendedValue', 'initValue')).to.eql(c.result);
  342. })
  343. })
  344. });
  345. });
  346. describe('#_getInitialFromRecommendations', function() {
  347. beforeEach(function() {
  348. instanceObject.set('recommendations', [
  349. {
  350. propertyName: 'p1',
  351. propertyFileName: 'f1',
  352. configGroup: 'Default',
  353. initialValue: 'initValue'
  354. }
  355. ])
  356. });
  357. it('get init value from recommendations', function() {
  358. expect(instanceObject._getInitialFromRecommendations('p1','f1')).to.equal('initValue');
  359. });
  360. it('recommendation does not exist', function() {
  361. expect(instanceObject._getInitialFromRecommendations('p2','f2')).to.equal(null);
  362. });
  363. });
  364. describe('#_getInitialValue', function() {
  365. beforeEach(function() {
  366. sinon.stub(instanceObject, 'useInitialValue', function(serviceName) {
  367. return serviceName !== 'serviceNameInstalled'
  368. })
  369. });
  370. afterEach(function() {
  371. instanceObject.useInitialValue.restore();
  372. });
  373. it('use initialValue', function() {
  374. expect(instanceObject._getInitialValue({
  375. serviceName: 'serviceNameNotInstalled',
  376. initialValue: 'initV',
  377. savedValue: 'savedV'
  378. })).to.equal('initV');
  379. });
  380. it('use savedValue', function() {
  381. expect(instanceObject._getInitialValue({
  382. serviceName: 'serviceNameInstalled',
  383. initialValue: 'initV',
  384. savedValue: 'savedV'
  385. })).to.equal('savedV');
  386. });
  387. it('wrong params', function() {
  388. expect(instanceObject._getInitialValue()).to.be.null;
  389. });
  390. });
  391. describe('#updateInitialOnRecommendations', function() {
  392. it('default value for updateInitialOnRecommendations is true', function() {
  393. expect(instanceObject.updateInitialOnRecommendations()).to.be.false;
  394. })
  395. });
  396. describe('#useInitialValue', function() {
  397. it('default value for useInitialValue is false', function() {
  398. expect(instanceObject.useInitialValue()).to.be.false;
  399. })
  400. });
  401. describe('#allowUpdateProperty', function() {
  402. var cases = [{
  403. saveRecommended: true
  404. },{
  405. saveRecommended: false
  406. }];
  407. cases.forEach(function(c) {
  408. describe('allowUpdateProperty based on saveRecommended:' + c.saveRecommended, function() {
  409. beforeEach(function() {
  410. sinon.stub(instanceObject, 'getRecommendation').returns({saveRecommended: c.saveRecommended});
  411. });
  412. afterEach(function() {
  413. instanceObject.getRecommendation.restore();
  414. });
  415. it('default value for allowUpdateProperty is true', function() {
  416. expect(instanceObject.allowUpdateProperty()).to.equal(c.saveRecommended);
  417. });
  418. });
  419. });
  420. it('default value for allowUpdateProperty is true', function() {
  421. expect(instanceObject.allowUpdateProperty()).to.be.true;
  422. });
  423. });
  424. describe('#_configHasInitialValue', function() {
  425. it('throws error when config is null', function() {
  426. expect(instanceObject._configHasInitialValue.bind(instanceObject, null)).to.throw(App.ObjectTypeError);
  427. });
  428. it('throws error when config is not object', function() {
  429. expect(instanceObject._configHasInitialValue.bind(instanceObject, 'not object')).to.throw(App.ObjectTypeError);
  430. });
  431. it('returns true if initial and saved value is defined', function() {
  432. expect(instanceObject._configHasInitialValue({'savedValue': 'some', 'initialValue': 'most of all the same'})).to.be.true;
  433. });
  434. it('returns false if saved value is not defined', function() {
  435. expect(instanceObject._configHasInitialValue({'savedValue': null, 'initialValue': 'some'})).to.be.false;
  436. });
  437. it('returns false if initial value is not defined', function() {
  438. expect(instanceObject._configHasInitialValue({'savedValue': 'some', 'initialValue': null })).to.be.false;
  439. });
  440. });
  441. describe('#addModifiedFileName', function() {
  442. it('throws error when filename is not defined', function() {
  443. expect(instanceObject.addModifiedFileName.bind(instanceObject, null)).to.throw(App.NotNullTypeError);
  444. });
  445. it('add new file name', function() {
  446. instanceObject.set('modifiedFileNames', ['someFile']);
  447. instanceObject.addModifiedFileName('otherFile');
  448. expect(instanceObject.get('modifiedFileNames').join(',')).to.be.equal('someFile,otherFile');
  449. });
  450. it('do not add file that already in list', function() {
  451. instanceObject.set('modifiedFileNames', ['someFile']);
  452. instanceObject.addModifiedFileName('someFile');
  453. expect(instanceObject.get('modifiedFileNames').join(',')).to.be.equal('someFile');
  454. });
  455. });
  456. });