helper_test.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  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('utils/helper');
  20. var O = Em.Object;
  21. describe('utils/helper', function() {
  22. describe('String helpers', function() {
  23. describe('#trim()', function(){
  24. it('should replace first space', function() {
  25. expect(' as d f'.trim()).to.be.equal('as d f');
  26. });
  27. });
  28. describe('#endsWith()', function() {
  29. it('`abcd` ends with `d`', function(){
  30. expect('abcd'.endsWith('d')).to.be.true;
  31. });
  32. it('`abcd` doesn\'t end with `f`', function(){
  33. expect('abcd'.endsWith('f')).to.be.false;
  34. });
  35. });
  36. describe('#contains()', function() {
  37. it('`abc` contains b', function(){
  38. expect('abc'.contains('b')).to.be.true;
  39. });
  40. it('`abc` doesn\'t contain d', function() {
  41. expect('abc'.contains('d')).to.be.false;
  42. });
  43. });
  44. describe('#capitalize()',function() {
  45. it('`abc d` should start with `A`', function() {
  46. expect('abc d'.capitalize()).to.be.equal('Abc d');
  47. });
  48. });
  49. describe('#findIn()', function(){
  50. var obj = {
  51. a: {
  52. a1: 'AVal1'
  53. },
  54. b: 'BVal',
  55. c: {
  56. c1: {
  57. c2: 'Cval2'
  58. },
  59. b: 'BVal'
  60. }
  61. };
  62. var testValue = function(key, value) {
  63. it('key `' + key + '` should have `' + JSON.stringify(value) + '` value', function() {
  64. expect(key.findIn(obj)).to.eql(value);
  65. });
  66. };
  67. it('expect return `null` on non-object input', function(){
  68. expect('a'.findIn('b')).to.null;
  69. });
  70. testValue('a', obj.a);
  71. testValue('c2', obj.c.c1.c2);
  72. testValue('b', obj.b);
  73. testValue('d', null);
  74. });
  75. describe('#format()', function(){
  76. it('should replace string correctly', function(){
  77. expect("{0} world{1}".format("Hello","!")).to.be.equal("Hello world!");
  78. });
  79. });
  80. describe('#highlight()', function() {
  81. var str = "Hello world! I want to highlight this word!";
  82. it('should highlight `word` with default template', function() {
  83. var result = str.highlight(['word']);
  84. expect(result).to.be.equal("Hello world! I want to highlight this <b>word</b>!");
  85. });
  86. it('should highlight `world` and `word` with template `<span class="yellow">{0}</span>`', function() {
  87. var result = str.highlight(["world", "word"], '<span class="yellow">{0}</span>');
  88. expect(result).to.be.equal('Hello <span class="yellow">world</span>! I want to highlight this <span class="yellow">word</span>!')
  89. });
  90. var str2 = "First word, second word";
  91. it('should highlight `word` multiply times with default template', function() {
  92. var result = str2.highlight(["word"]);
  93. expect(result).to.be.equal("First <b>word</b>, second <b>word</b>");
  94. });
  95. });
  96. });
  97. describe('Number helpers', function(){
  98. describe('#toDaysHoursMinutes()', function(){
  99. var time = 1000000000;
  100. var minute = 1000*60;
  101. var hour = 60*minute;
  102. var day = 24*hour;
  103. var result = time.toDaysHoursMinutes();
  104. var testDays = Math.floor(time/day);
  105. it('should correct convert days', function(){
  106. expect(testDays).to.eql(result.d);
  107. });
  108. it('should correct convert hours', function(){
  109. expect(Math.floor((time - testDays * day)/hour)).to.eql(result.h);
  110. });
  111. it('should correct convert minutes', function(){
  112. expect(((time - Math.floor((time - testDays*day)/hour)*hour - testDays*day)/minute).toFixed(2)).to.eql(result.m);
  113. });
  114. });
  115. });
  116. describe('Array helpers', function(){
  117. var tests = Em.A([
  118. {
  119. m: 'plain objects, no nesting',
  120. array: [{a: 1}, {a: 2}, {a: 3}],
  121. property: 'a',
  122. callback3: function (item) {
  123. return Em.get(item, 'a');
  124. },
  125. e1: {1: {a: 1}, 2: {a: 2}, 3: {a: 3}},
  126. e2: {1: true, 2: true, 3: true},
  127. e3: {1: 1, 2: 2, 3: 3}
  128. },
  129. {
  130. m: 'plain objects, nesting',
  131. array: [{a: {a: 1}}, {a: {a: 2}}, {a:{a: 3}}],
  132. property: 'a.a',
  133. callback3: function (item) {
  134. return Em.get(item, 'a.a');
  135. },
  136. e1: {1: {a: {a: 1}}, 2: {a: {a: 2}}, 3: {a: {a: 3}}},
  137. e2: {1: true, 2: true, 3: true},
  138. e3: {1: 1, 2: 2, 3: 3}
  139. },
  140. {
  141. m: 'Ember objects, no nesting',
  142. array: [O.create({a: 1}), O.create({a: 2}), O.create({a: 3})],
  143. property: 'a',
  144. callback3: function (item) {
  145. return Em.get(item, 'a');
  146. },
  147. e1: {1: O.create({a: 1}), 2: O.create({a: 2}), 3: O.create({a: 3})},
  148. e2: {1: true, 2: true, 3: true},
  149. e3: {1: 1, 2: 2, 3: 3}
  150. },
  151. {
  152. m: 'Ember objects, nesting',
  153. array: [O.create({a: {a: 1}}), O.create({a: {a: 2}}), O.create({a: {a: 3}})],
  154. property: 'a.a',
  155. callback3: function (item) {
  156. return Em.get(item, 'a.a');
  157. },
  158. e1: {1: O.create({a: {a: 1}}), 2: O.create({a: {a: 2}}), 3: O.create({a: {a: 3}})},
  159. e2: {1: true, 2: true, 3: true},
  160. e3: {1: 1, 2: 2, 3: 3}
  161. }
  162. ]);
  163. describe('#sortPropertyLight()', function(){
  164. var testable = [
  165. { a: 2 },
  166. { a: 1 },
  167. { a: 6},
  168. { a: 64},
  169. { a: 3},
  170. { a: 3}
  171. ];
  172. var result = testable.sortPropertyLight('a');
  173. it('should return array with same length', function(){
  174. expect(testable.length).to.eql(result.length);
  175. });
  176. it('should sort array', function() {
  177. expect(result.mapProperty('a')).to.be.eql([1, 2, 3, 3, 6, 64]);
  178. });
  179. it('should try to sort without throwing exception', function(){
  180. expect(testable.sortPropertyLight(['a'])).to.ok;
  181. });
  182. });
  183. describe('#toMapByProperty', function () {
  184. tests.forEach(function (test) {
  185. it(test.m, function () {
  186. expect(test.array.toMapByProperty(test.property)).to.eql(test.e1);
  187. });
  188. });
  189. });
  190. describe('#toWickMapByProperty', function () {
  191. tests.forEach(function (test) {
  192. it(test.m, function () {
  193. expect(test.array.toWickMapByProperty(test.property)).to.eql(test.e2);
  194. });
  195. });
  196. });
  197. describe('#toMapByCallback', function () {
  198. tests.forEach(function (test) {
  199. it(test.m, function () {
  200. expect(test.array.toMapByCallback(test.property, test.callback3)).to.eql(test.e3);
  201. });
  202. });
  203. });
  204. describe('#toWickMap', function () {
  205. it('should convert to wick map', function () {
  206. expect([1,2,3].toWickMap()).to.eql({1: true, 2: true, 3: true});
  207. });
  208. });
  209. });
  210. describe('App helpers', function(){
  211. var appendDiv = function() {
  212. $('body').append('<div id="tooltip-test"></div>');
  213. };
  214. var removeDiv = function() {
  215. $('body').remove('#tooltip-test');
  216. };
  217. describe('#isEmptyObject', function(){
  218. it('should return true on empty object', function() {
  219. expect(App.isEmptyObject({})).to.be.true;
  220. });
  221. it('should return false on non-empty object', function() {
  222. expect(App.isEmptyObject({ a: 1 })).to.be.false;
  223. });
  224. });
  225. describe('#tooltip()', function() {
  226. beforeEach(appendDiv);
  227. afterEach(removeDiv);
  228. it('should add tooltip', function() {
  229. App.tooltip($('#tooltip-test'));
  230. expect($('#tooltip-test').data('tooltip').enabled).to.be.true;
  231. });
  232. });
  233. describe('#popover()', function() {
  234. beforeEach(appendDiv);
  235. afterEach(removeDiv);
  236. it('should add popover', function() {
  237. App.popover($('#tooltip-test'));
  238. expect($('#tooltip-test').data('popover').enabled).to.be.true;
  239. });
  240. });
  241. describe('#App.format', function(){
  242. describe('#commandDetail()', function() {
  243. var command = "GANGLIA_MONITOR STOP";
  244. var ignored = "DECOMMISSION, NAMENODE";
  245. var removeString = "SERVICE/HDFS STOP";
  246. var nagiosState = "nagios_update_ignore ACTIONEXECUTE";
  247. var installRepo = "install_packages ACTIONEXECUTE";
  248. it('should convert command to readable info', function() {
  249. expect(App.format.commandDetail(command)).to.be.equal(' Ganglia Monitor Stop');
  250. });
  251. it('should ignore decommission command', function(){
  252. expect(App.format.commandDetail(ignored)).to.be.equal(' NameNode');
  253. });
  254. it('should remove SERVICE string from command', function(){
  255. expect(App.format.commandDetail(removeString)).to.be.equal(' HDFS Stop');
  256. });
  257. it('should return maintenance message', function() {
  258. expect(App.format.commandDetail(nagiosState)).to.be.equal(' Toggle Maintenance Mode');
  259. });
  260. it('should return install repo message', function() {
  261. expect(App.format.commandDetail(installRepo)).to.be.equal(Em.I18n.t('common.installRepo.task'));
  262. });
  263. });
  264. describe('#taskStatus()', function(){
  265. var testable = [
  266. { status: 'PENDING', expectable: 'pending'},
  267. { status: 'QUEUED', expectable: 'queued'},
  268. { status: 'COMPLETED', expectable: 'completed'}
  269. ];
  270. testable.forEach(function(testObj){
  271. it('should convert `' + testObj.status + '` to `' + testObj.expectable + '`', function(){
  272. expect(App.format.taskStatus(testObj.status)).to.eql(testObj.expectable);
  273. });
  274. });
  275. });
  276. describe('#normalizeNameBySeparators()', function() {
  277. var testMessage = '`{0}` should be converted to `{1}`';
  278. var tests = {
  279. 'APP_TIMELINE_SERVER': 'App Timeline Server',
  280. 'app_timeline_server': 'App Timeline Server',
  281. 'APP-TIMELINE-SERVER': 'App Timeline Server',
  282. 'app-timeline-server': 'App Timeline Server',
  283. 'APP TIMELINE SERVER': 'App Timeline Server',
  284. 'app timeline server': 'App Timeline Server',
  285. 'FALCON': 'Falcon',
  286. 'falcon': 'Falcon'
  287. };
  288. Object.keys(tests).forEach(function (inputName) {
  289. it(testMessage.format(inputName, tests[inputName]), function() {
  290. expect(App.format.normalizeNameBySeparators(inputName, ["-", "_", " "])).to.eql(tests[inputName]);
  291. });
  292. });
  293. });
  294. describe('#normalizeName()', function() {
  295. var testMessage = '`{0}` should be converted to `{1}`';
  296. var tests = {
  297. 'APP_TIMELINE_SERVER': 'App Timeline Server',
  298. 'DATANODE': 'DataNode',
  299. 'DECOMMISSION_DATANODE': 'Update Exclude File',
  300. 'DRPC_SERVER': 'DRPC Server',
  301. 'FALCON': 'Falcon',
  302. 'FALCON_CLIENT': 'Falcon Client',
  303. 'FALCON_SERVER': 'Falcon Server',
  304. 'FALCON_SERVICE_CHECK': 'Falcon Service Check',
  305. 'FLUME_HANDLER': 'Flume',
  306. 'FLUME_SERVICE_CHECK': 'Flume Service Check',
  307. 'GANGLIA_MONITOR': 'Ganglia Monitor',
  308. 'GANGLIA_SERVER': 'Ganglia Server',
  309. 'GLUSTERFS_CLIENT': 'GLUSTERFS Client',
  310. 'GLUSTERFS_SERVICE_CHECK': 'GLUSTERFS Service Check',
  311. 'GMETAD_SERVICE_CHECK': 'Gmetad Service Check',
  312. 'GMOND_SERVICE_CHECK': 'Gmond Service Check',
  313. 'HADOOP_CLIENT': 'Hadoop Client',
  314. 'HBASE_CLIENT': 'HBase Client',
  315. 'HBASE_MASTER': 'HBase Master',
  316. 'HBASE_REGIONSERVER': 'RegionServer',
  317. 'HBASE_SERVICE_CHECK': 'HBase Service Check',
  318. 'HCAT': 'HCat Client',
  319. 'HDFS': 'HDFS',
  320. 'HDFS_CLIENT': 'HDFS Client',
  321. 'HDFS_SERVICE_CHECK': 'HDFS Service Check',
  322. 'HISTORYSERVER': 'History Server',
  323. 'HIVE_CLIENT': 'Hive Client',
  324. 'HIVE_METASTORE': 'Hive Metastore',
  325. 'HIVE_SERVER': 'HiveServer2',
  326. 'HIVE_SERVICE_CHECK': 'Hive Service Check',
  327. 'HUE_SERVER': 'Hue Server',
  328. 'JAVA_JCE': 'Java JCE',
  329. 'JOBTRACKER': 'JobTracker',
  330. 'JOBTRACKER_SERVICE_CHECK': 'JobTracker Service Check',
  331. 'JOURNALNODE': 'JournalNode',
  332. 'KERBEROS_ADMIN_CLIENT': 'Kerberos Admin Client',
  333. 'KERBEROS_CLIENT': 'Kerberos Client',
  334. 'KERBEROS_SERVER': 'Kerberos Server',
  335. 'MAPREDUCE2_CLIENT': 'MapReduce2 Client',
  336. 'MAPREDUCE2_SERVICE_CHECK': 'MapReduce2 Service Check',
  337. 'MYSQL_SERVER': 'MySQL Server',
  338. 'NAMENODE': 'NameNode',
  339. 'NAMENODE_SERVICE_CHECK': 'NameNode Service Check',
  340. 'NIMBUS': 'Nimbus',
  341. 'NODEMANAGER': 'NodeManager',
  342. 'OOZIE_CLIENT': 'Oozie Client',
  343. 'OOZIE_SERVER': 'Oozie Server',
  344. 'OOZIE_SERVICE_CHECK': 'Oozie Service Check',
  345. 'PIG': 'Pig',
  346. 'PIG_SERVICE_CHECK': 'Pig Service Check',
  347. 'RESOURCEMANAGER': 'ResourceManager',
  348. 'SECONDARY_NAMENODE': 'SNameNode',
  349. 'SQOOP': 'Sqoop',
  350. 'SQOOP_SERVICE_CHECK': 'Sqoop Service Check',
  351. 'STORM_REST_API': 'Storm REST API Server',
  352. 'STORM_SERVICE_CHECK': 'Storm Service Check',
  353. 'STORM_UI_SERVER': 'Storm UI Server',
  354. 'SUPERVISOR': 'Supervisor',
  355. 'TASKTRACKER': 'TaskTracker',
  356. 'TEZ_CLIENT': 'Tez Client',
  357. 'WEBHCAT_SERVER': 'WebHCat Server',
  358. 'YARN_CLIENT': 'YARN Client',
  359. 'YARN_SERVICE_CHECK': 'YARN Service Check',
  360. 'ZKFC': 'ZKFailoverController',
  361. 'ZOOKEEPER_CLIENT': 'ZooKeeper Client',
  362. 'ZOOKEEPER_QUORUM_SERVICE_CHECK': 'ZK Quorum Service Check',
  363. 'ZOOKEEPER_SERVER': 'ZooKeeper Server',
  364. 'ZOOKEEPER_SERVICE_CHECK': 'ZooKeeper Service Check',
  365. 'CLIENT': 'Client'
  366. };
  367. Object.keys(tests).forEach(function (inputName) {
  368. it(testMessage.format(inputName, tests[inputName]), function() {
  369. expect(App.format.normalizeName(inputName)).to.eql(tests[inputName]);
  370. });
  371. });
  372. });
  373. describe('#kdcErrorMsg()', function() {
  374. var tests = [
  375. {
  376. r: "1 Missing KDC administrator credentials. and some text",
  377. f: "Missing KDC administrator credentials."
  378. },
  379. {
  380. r: "2 Invalid KDC administrator credentials. and some text",
  381. f: "Invalid KDC administrator credentials."
  382. },
  383. {
  384. r: "3 Failed to find a KDC for the specified realm - kadmin and some text",
  385. f: "Failed to find a KDC for the specified realm - kadmin"
  386. },
  387. {
  388. r: "4 some text",
  389. f: null,
  390. s: true
  391. },
  392. {
  393. r: "4 some text",
  394. f: "4 some text",
  395. s: false
  396. }
  397. ];
  398. tests.forEach(function(t) {
  399. it("kdcErrorMsg for " + t.f + " with strict " + t.s, function() {
  400. expect(App.format.kdcErrorMsg(t.r, t.s)).to.be.equal(t.f);
  401. })
  402. });
  403. });
  404. describe("#role()", function() {
  405. before(function () {
  406. App.format.stackRolesMap = {};
  407. });
  408. beforeEach(function () {
  409. sinon.stub(App.StackService, 'find').returns([Em.Object.create({
  410. id: 'S1',
  411. displayName: 's1'
  412. })]);
  413. sinon.stub(App.StackServiceComponent, 'find').returns([Em.Object.create({
  414. id: 'C1',
  415. displayName: 'c1'
  416. })]);
  417. });
  418. afterEach(function () {
  419. App.StackService.find.restore();
  420. App.StackServiceComponent.find.restore();
  421. });
  422. it("S1 -> s1", function() {
  423. expect(App.format.role('S1')).to.equal('s1');
  424. });
  425. it("C1 -> c1", function() {
  426. expect(App.format.role('C1')).to.equal('c1');
  427. });
  428. it("stackRolesMap is not empty", function() {
  429. expect(App.format.stackRolesMap).to.not.be.empty;
  430. });
  431. });
  432. });
  433. });
  434. describe('#App.permit()', function() {
  435. var obj = {
  436. a1: 'v1',
  437. a2: 'v2',
  438. a3: 'v3'
  439. };
  440. var tests = [
  441. {
  442. keys: 'a1',
  443. e: {
  444. a1: 'v1'
  445. }
  446. },
  447. {
  448. keys: ['a2','a3','a4'],
  449. e: {
  450. a2: 'v2',
  451. a3: 'v3'
  452. }
  453. }
  454. ];
  455. tests.forEach(function(test) {
  456. it('should return object `{0}` permitted keys `{1}`'.format(JSON.stringify(test.e), JSON.stringify(test.keys)), function() {
  457. expect(App.permit(obj, test.keys)).to.deep.eql(test.e);
  458. });
  459. });
  460. });
  461. describe('#App.keysUnderscoreToCamelCase()', function() {
  462. var tests = [
  463. {
  464. object: {
  465. 'key_upper': '2'
  466. },
  467. expected: {
  468. keyUpper: '2'
  469. },
  470. m: 'One level object, key should be camelCased'
  471. },
  472. {
  473. object: {
  474. 'key_upper': '2',
  475. 'key': '1'
  476. },
  477. expected: {
  478. keyUpper: '2',
  479. key: '1'
  480. },
  481. m: 'One level object, one key should be camelCased.'
  482. },
  483. {
  484. object: {
  485. 'key_upper': '2',
  486. 'key': '1'
  487. },
  488. expected: {
  489. keyUpper: '2',
  490. key: '1'
  491. },
  492. m: 'One level object, one key should be camelCased.'
  493. },
  494. {
  495. object: {
  496. 'key_upper': '2',
  497. 'key_upone_uptwo_upthree': '4',
  498. 'key': '1'
  499. },
  500. expected: {
  501. keyUpper: '2',
  502. keyUponeUptwoUpthree: '4',
  503. key: '1'
  504. },
  505. m: 'One level object, two keys should be camelCased, few dots notation.'
  506. }
  507. ];
  508. tests.forEach(function(test) {
  509. it(test.m, function() {
  510. expect(App.keysUnderscoreToCamelCase(test.object)).to.deep.equal(test.expected);
  511. });
  512. });
  513. });
  514. describe('#App.keysDottedToCamelCase()', function() {
  515. var tests = [
  516. {
  517. object: {
  518. 'key.upper': '2'
  519. },
  520. expected: {
  521. keyUpper: '2'
  522. },
  523. m: 'One level object, key should be camelCased'
  524. },
  525. {
  526. object: {
  527. 'key.upper': '2',
  528. 'key': '1'
  529. },
  530. expected: {
  531. keyUpper: '2',
  532. key: '1'
  533. },
  534. m: 'One level object, one key should be camelCased.'
  535. },
  536. {
  537. object: {
  538. 'key.upper': '2',
  539. 'key': '1'
  540. },
  541. expected: {
  542. keyUpper: '2',
  543. key: '1'
  544. },
  545. m: 'One level object, one key should be camelCased.'
  546. },
  547. {
  548. object: {
  549. 'key.upper': '2',
  550. 'key.upone.uptwo.upthree': '4',
  551. 'key': '1'
  552. },
  553. expected: {
  554. keyUpper: '2',
  555. keyUponeUptwoUpthree: '4',
  556. key: '1'
  557. },
  558. m: 'One level object, two keys should be camelCased, few dots notation.'
  559. }
  560. ];
  561. tests.forEach(function(test) {
  562. it(test.m, function() {
  563. expect(App.keysDottedToCamelCase(test.object)).to.deep.equal(test.expected);
  564. });
  565. });
  566. });
  567. describe('#App.formatDateTimeWithTimeZone()', function () {
  568. beforeEach(function () {
  569. sinon.stub(App.router, 'get').withArgs('userSettingsController.userSettings.timezone').returns({
  570. zones: [{
  571. value: 'Europe/Amsterdam'
  572. }]
  573. });
  574. });
  575. afterEach(function () {
  576. App.router.get.restore();
  577. });
  578. it('should format date according to customized timezone', function () {
  579. expect(App.formatDateTimeWithTimeZone(1000000, 'YYYY-MM-DD HH:mm:ss (hh:mm A)')).to.equal('1970-01-01 01:16:40 (01:16 AM)');
  580. });
  581. });
  582. });