vis.js is a dynamic, browser-based visualization library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

901 lines
27 KiB

  1. var jsdom_global = require('jsdom-global');
  2. var assert = require('assert');
  3. var util = require('../lib/util');
  4. var moment = require('../lib//module/moment');
  5. var ASPDateRegex = /^\/?Date\((\-?\d+)/i;
  6. describe('util', function () {
  7. /**
  8. * Tests for copy and extend methods.
  9. *
  10. * Goal: to cover all possible paths within the tested method(s)
  11. *
  12. *
  13. * **NOTES**
  14. *
  15. * - All these methods have the inherent flaw that it's possible to define properties
  16. * on an object with value 'undefined'. e.g. in `node`:
  17. *
  18. * > a = { b:undefined }
  19. * > a.hasOwnProperty('b')
  20. * true
  21. *
  22. * The logic for handling this in the code is minimal and accidental. For the time being,
  23. * this flaw is ignored.
  24. */
  25. describe('extend routines', function () {
  26. /**
  27. * Check if values have been copied over from b to a as intended
  28. */
  29. function checkExtended(a, b, checkCopyTarget = false) {
  30. var result = {
  31. color: 'green',
  32. sub: {
  33. enabled: false,
  34. sub2: {
  35. font: 'awesome'
  36. }
  37. }
  38. };
  39. assert(a.color !== undefined && a.color === result.color);
  40. assert(a.notInSource === true);
  41. if (checkCopyTarget) {
  42. assert(a.notInTarget === true);
  43. } else {
  44. assert(a.notInTarget === undefined);
  45. }
  46. var sub = a.sub;
  47. assert(sub !== undefined);
  48. assert(sub.enabled !== undefined && sub.enabled === result.sub.enabled);
  49. assert(sub.notInSource === true);
  50. if (checkCopyTarget) {
  51. assert(sub.notInTarget === true);
  52. } else {
  53. assert(sub.notInTarget === undefined);
  54. }
  55. sub = a.sub.sub2;
  56. assert(sub !== undefined);
  57. assert(sub !== undefined && sub.font !== undefined && sub.font === result.sub.sub2.font);
  58. assert(sub.notInSource === true);
  59. assert(a.subNotInSource !== undefined);
  60. if (checkCopyTarget) {
  61. assert(a.subNotInTarget.enabled === true);
  62. assert(sub.notInTarget === true);
  63. } else {
  64. assert(a.subNotInTarget === undefined);
  65. assert(sub.notInTarget === undefined);
  66. }
  67. }
  68. /**
  69. * Spot check on values of a unchanged as intended
  70. */
  71. function testAUnchanged(a) {
  72. var sub = a.sub;
  73. assert(sub !== undefined);
  74. assert(sub.enabled !== undefined && sub.enabled === true);
  75. assert(sub.notInSource === true);
  76. assert(sub.notInTarget === undefined);
  77. assert(sub.deleteThis === true);
  78. sub = a.sub.sub2;
  79. assert(sub !== undefined);
  80. assert(sub !== undefined && sub.font !== undefined && sub.font === 'arial');
  81. assert(sub.notInSource === true);
  82. assert(sub.notInTarget === undefined);
  83. assert(a.subNotInSource !== undefined);
  84. assert(a.subNotInTarget === undefined);
  85. }
  86. function initA() {
  87. return {
  88. color: 'red',
  89. notInSource: true,
  90. sub: {
  91. enabled: true,
  92. notInSource: true,
  93. sub2: {
  94. font: 'arial',
  95. notInSource: true,
  96. },
  97. deleteThis: true,
  98. },
  99. subNotInSource: {
  100. enabled: true,
  101. },
  102. deleteThis: true,
  103. subDeleteThis: {
  104. enabled: true,
  105. },
  106. };
  107. }
  108. beforeEach(function() {
  109. this.a = initA();
  110. this.b = {
  111. color: 'green',
  112. notInTarget: true,
  113. sub: {
  114. enabled: false,
  115. notInTarget: true,
  116. sub2: {
  117. font: 'awesome',
  118. notInTarget: true,
  119. },
  120. deleteThis: null,
  121. },
  122. subNotInTarget: {
  123. enabled: true,
  124. },
  125. deleteThis: null,
  126. subDeleteThis: null
  127. };
  128. });
  129. it('performs fillIfDefined() as advertized', function () {
  130. var a = this.a;
  131. var b = this.b;
  132. util.fillIfDefined(a, b);
  133. checkExtended(a, b);
  134. // NOTE: if allowDeletion === false, null values are copied over!
  135. // This is due to existing logic; it might not be the intention and hence a bug
  136. assert(a.sub.deleteThis === null);
  137. assert(a.deleteThis === null);
  138. assert(a.subDeleteThis === null);
  139. });
  140. it('performs fillIfDefined() as advertized with deletion', function () {
  141. var a = this.a;
  142. var b = this.b;
  143. util.fillIfDefined(a, b, true); // thrid param: allowDeletion
  144. checkExtended(a, b);
  145. // Following should be removed now
  146. assert(a.sub.deleteThis === undefined);
  147. assert(a.deleteThis === undefined);
  148. assert(a.subDeleteThis === undefined);
  149. });
  150. it('performs selectiveDeepExtend() as advertized', function () {
  151. var a = this.a;
  152. var b = this.b;
  153. // pedantic: copy nothing
  154. util.selectiveDeepExtend([], a, b);
  155. assert(a.color !== undefined && a.color === 'red');
  156. assert(a.notInSource === true);
  157. assert(a.notInTarget === undefined);
  158. // pedantic: copy nonexistent property (nothing happens)
  159. assert(b.iDontExist === undefined);
  160. util.selectiveDeepExtend(['iDontExist'], a, b, true);
  161. assert(a.iDontExist === undefined);
  162. // At this point nothing should have changed yet.
  163. testAUnchanged(a);
  164. // Copy one property
  165. util.selectiveDeepExtend(['color'], a, b);
  166. assert(a.color !== undefined && a.color === 'green');
  167. // Copy property Object
  168. var sub = a.sub;
  169. assert(sub.deleteThis === true); // pre
  170. util.selectiveDeepExtend(['sub'], a, b);
  171. assert(sub !== undefined);
  172. assert(sub.enabled !== undefined && sub.enabled === false);
  173. assert(sub.notInSource === true);
  174. assert(sub.notInTarget === true);
  175. assert(sub.deleteThis === null);
  176. // Copy new Objects
  177. assert(a.notInTarget === undefined); // pre
  178. assert(a.subNotInTarget === undefined); // pre
  179. util.selectiveDeepExtend(['notInTarget', 'subNotInTarget'], a, b);
  180. assert(a.notInTarget === true);
  181. assert(a.subNotInTarget.enabled === true);
  182. // Copy null objects
  183. assert(a.deleteThis !== null); // pre
  184. assert(a.subDeleteThis !== null); // pre
  185. util.selectiveDeepExtend(['deleteThis', 'subDeleteThis'], a, b);
  186. // NOTE: if allowDeletion === false, null values are copied over!
  187. // This is due to existing logic; it might not be the intention and hence a bug
  188. assert(a.deleteThis === null);
  189. assert(a.subDeleteThis === null);
  190. });
  191. it('performs selectiveDeepExtend() as advertized with deletion', function () {
  192. var a = this.a;
  193. var b = this.b;
  194. // Only test expected differences here with test allowDeletion === false
  195. // Copy object property with properties to be deleted
  196. var sub = a.sub;
  197. assert(sub.deleteThis === true); // pre
  198. util.selectiveDeepExtend(['sub'], a, b, true);
  199. assert(sub.deleteThis === undefined); // should be deleted
  200. // Spot check on rest of properties in `a.sub` - there should have been copied
  201. sub = a.sub;
  202. assert(sub !== undefined);
  203. assert(sub.enabled !== undefined && sub.enabled === false);
  204. assert(sub.notInSource === true);
  205. assert(sub.notInTarget === true);
  206. // Copy null objects
  207. assert(a.deleteThis === true); // pre
  208. assert(a.subDeleteThis !== undefined); // pre
  209. assert(a.subDeleteThis.enabled === true); // pre
  210. util.selectiveDeepExtend(['deleteThis', 'subDeleteThis'], a, b, true);
  211. assert(a.deleteThis === undefined); // should be deleted
  212. assert(a.subDeleteThis === undefined); // should be deleted
  213. });
  214. it('performs selectiveNotDeepExtend() as advertized', function () {
  215. var a = this.a;
  216. var b = this.b;
  217. // Exclude all properties, nothing copied
  218. util.selectiveNotDeepExtend(Object.keys(b), a, b);
  219. testAUnchanged(a);
  220. // Exclude nothing, everything copied
  221. util.selectiveNotDeepExtend([], a, b);
  222. checkExtended(a, b, true);
  223. // Exclude some
  224. a = initA();
  225. assert(a.notInTarget === undefined); // pre
  226. assert(a.subNotInTarget === undefined); // pre
  227. util.selectiveNotDeepExtend(['notInTarget', 'subNotInTarget'], a, b);
  228. assert(a.notInTarget === undefined); // not copied
  229. assert(a.subNotInTarget === undefined); // not copied
  230. assert(a.sub.notInTarget === true); // copied!
  231. });
  232. it('performs selectiveNotDeepExtend() as advertized with deletion', function () {
  233. var a = this.a;
  234. var b = this.b;
  235. // Exclude all properties, nothing copied
  236. util.selectiveNotDeepExtend(Object.keys(b), a, b, true);
  237. testAUnchanged(a);
  238. // Exclude nothing, everything copied and some deleted
  239. util.selectiveNotDeepExtend([], a, b, true);
  240. checkExtended(a, b, true);
  241. // Exclude some
  242. a = initA();
  243. assert(a.notInTarget === undefined); // pre
  244. assert(a.subNotInTarget === undefined); // pre
  245. assert(a.deleteThis === true); // pre
  246. assert(a.subDeleteThis !== undefined); // pre
  247. assert(a.sub.deleteThis === true); // pre
  248. assert(a.subDeleteThis.enabled === true); // pre
  249. util.selectiveNotDeepExtend(['notInTarget', 'subNotInTarget'], a, b, true);
  250. assert(a.deleteThis === undefined); // should be deleted
  251. assert(a.sub.deleteThis !== undefined); // not deleted! Original logic, could be a bug
  252. assert(a.subDeleteThis === undefined); // should be deleted
  253. // Spot check: following should be same as allowDeletion === false
  254. assert(a.notInTarget === undefined); // not copied
  255. assert(a.subNotInTarget === undefined); // not copied
  256. assert(a.sub.notInTarget === true); // copied!
  257. });
  258. /**
  259. * NOTE: parameter `protoExtend` not tested here!
  260. */
  261. it('performs deepExtend() as advertized', function () {
  262. var a = this.a;
  263. var b = this.b;
  264. util.deepExtend(a, b);
  265. checkExtended(a, b, true);
  266. });
  267. /**
  268. * NOTE: parameter `protoExtend` not tested here!
  269. */
  270. it('performs deepExtend() as advertized with delete', function () {
  271. var a = this.a;
  272. var b = this.b;
  273. // Copy null objects
  274. assert(a.deleteThis === true); // pre
  275. assert(a.subDeleteThis !== undefined); // pre
  276. assert(a.subDeleteThis.enabled === true); // pre
  277. util.deepExtend(a, b, false, true);
  278. checkExtended(a, b, true); // Normal copy should be good
  279. assert(a.deleteThis === undefined); // should be deleted
  280. assert(a.subDeleteThis === undefined); // should be deleted
  281. assert(a.sub.deleteThis !== undefined); // not deleted!!! Original logic, could be a bug
  282. });
  283. }); // extend routines
  284. //
  285. // The important thing with mergeOptions() is that 'enabled' is always set in target option.
  286. //
  287. describe('mergeOptions', function () {
  288. it('handles good input without global options', function () {
  289. var options = {
  290. someValue: "silly value",
  291. aBoolOption: false,
  292. anObject: {
  293. answer:42
  294. },
  295. anotherObject: {
  296. enabled: false,
  297. },
  298. merge: null
  299. };
  300. // Case with empty target
  301. var mergeTarget = {};
  302. util.mergeOptions(mergeTarget, options, 'someValue');
  303. assert(mergeTarget.someValue === undefined, 'Non-object option should not be copied');
  304. assert(mergeTarget.anObject === undefined);
  305. util.mergeOptions(mergeTarget, options, 'aBoolOption');
  306. assert(mergeTarget.aBoolOption !== undefined, 'option aBoolOption should now be an object');
  307. assert(mergeTarget.aBoolOption.enabled === false, 'enabled value option aBoolOption should have been copied into object');
  308. util.mergeOptions(mergeTarget, options, 'anObject');
  309. assert(mergeTarget.anObject !== undefined, 'Option object is not copied');
  310. assert(mergeTarget.anObject.answer === 42);
  311. assert(mergeTarget.anObject.enabled === true);
  312. util.mergeOptions(mergeTarget, options, 'anotherObject');
  313. assert(mergeTarget.anotherObject.enabled === false, 'enabled value from options must have priority');
  314. util.mergeOptions(mergeTarget, options, 'merge');
  315. assert(mergeTarget.merge === undefined, 'Explicit null option should not be copied, there is no global option for it');
  316. // Case with non-empty target
  317. mergeTarget = {
  318. someValue: false,
  319. aBoolOption: true,
  320. anObject: {
  321. answer: 49
  322. },
  323. anotherObject: {
  324. enabled: true,
  325. },
  326. merge: 'hello'
  327. };
  328. util.mergeOptions(mergeTarget, options, 'someValue');
  329. assert(mergeTarget.someValue === false, 'Non-object option should not be copied');
  330. assert(mergeTarget.anObject.answer === 49, 'Sibling option should not be changed');
  331. util.mergeOptions(mergeTarget, options, 'aBoolOption');
  332. assert(mergeTarget.aBoolOption !== true, 'option enabled should have been overwritten');
  333. assert(mergeTarget.aBoolOption.enabled === false, 'enabled value option aBoolOption should have been copied into object');
  334. util.mergeOptions(mergeTarget, options, 'anObject');
  335. assert(mergeTarget.anObject.answer === 42);
  336. assert(mergeTarget.anObject.enabled === true);
  337. util.mergeOptions(mergeTarget, options, 'anotherObject');
  338. assert(mergeTarget.anotherObject !== undefined, 'Option object is not copied');
  339. assert(mergeTarget.anotherObject.enabled === false, 'enabled value from options must have priority');
  340. util.mergeOptions(mergeTarget, options, 'merge');
  341. assert(mergeTarget.merge === 'hello', 'Explicit null-option should not be copied, already present in target');
  342. });
  343. it('gracefully handles bad input', function () {
  344. var mergeTarget = {};
  345. var options = {
  346. merge: null
  347. };
  348. var errMsg = 'Non-object parameters should not be accepted';
  349. assert.throws(() => util.mergeOptions(null, options, 'anything'), Error, errMsg);
  350. assert.throws(() => util.mergeOptions(undefined, options, 'anything'), Error, errMsg);
  351. assert.throws(() => util.mergeOptions(42, options, 'anything'), Error, errMsg);
  352. assert.throws(() => util.mergeOptions(mergeTarget, null, 'anything'), Error, errMsg);
  353. assert.throws(() => util.mergeOptions(mergeTarget, undefined, 'anything'), Error, errMsg);
  354. assert.throws(() => util.mergeOptions(mergeTarget, 42, 'anything'), Error, errMsg);
  355. assert.throws(() => util.mergeOptions(mergeTarget, options, null), Error, errMsg);
  356. assert.throws(() => util.mergeOptions(mergeTarget, options, undefined), Error, errMsg);
  357. assert.throws(() => util.mergeOptions(mergeTarget, options, 'anything', null), Error, errMsg);
  358. assert.throws(() => util.mergeOptions(mergeTarget, options, 'anything', 'not an object'), Error, errMsg);
  359. util.mergeOptions(mergeTarget, options, 'iDontExist');
  360. assert(mergeTarget.iDontExist === undefined);
  361. });
  362. it('handles good input with global options', function () {
  363. var mergeTarget = {
  364. };
  365. var options = {
  366. merge: null,
  367. missingEnabled: {
  368. answer: 42
  369. },
  370. alsoMissingEnabled: { // has no enabled in globals
  371. answer: 42
  372. }
  373. };
  374. var globalOptions = {
  375. merge: {
  376. enabled: false
  377. },
  378. missingEnabled: {
  379. enabled: false
  380. }
  381. };
  382. util.mergeOptions(mergeTarget, options, 'merge', globalOptions);
  383. assert(mergeTarget.merge.enabled === false, "null-option should create an empty target object");
  384. util.mergeOptions(mergeTarget, options, 'missingEnabled', globalOptions);
  385. assert(mergeTarget.missingEnabled.enabled === false);
  386. util.mergeOptions(mergeTarget, options, 'alsoMissingEnabled', globalOptions);
  387. assert(mergeTarget.alsoMissingEnabled.enabled === true);
  388. });
  389. }); // mergeOptions
  390. describe('recursiveDOMDelete', function () {
  391. beforeEach(function() {
  392. this.jsdom_global = jsdom_global();
  393. });
  394. afterEach(function() {
  395. this.jsdom_global();
  396. });
  397. it('removes children', function () {
  398. var root = document.createElement("div");
  399. // Create children for root
  400. var parent = document.createElement("div");
  401. var parentSibiling = document.createElement("div");
  402. // Attach parents to root
  403. root.appendChild(parent);
  404. root.appendChild(parentSibiling);
  405. // Create children for the respective parents
  406. var child = document.createElement("div");
  407. var childSibling = document.createElement("div");
  408. // Attach children to parents
  409. parent.appendChild(child);
  410. parentSibiling.appendChild(childSibling);
  411. util.recursiveDOMDelete(root);
  412. assert.equal(root.children.length, 0);
  413. assert.equal(parent.children.length, 0);
  414. assert.equal(parentSibiling.children.length, 0);
  415. assert.equal(child.children.length, 0);
  416. assert.equal(childSibling.children.length, 0);
  417. });
  418. });
  419. describe('isDate', function () {
  420. it('identifies a Date', function () {
  421. assert(util.isDate(new Date()));
  422. });
  423. it('identifies an ASPDate as String', function () {
  424. assert(util.isDate('Date(1198908717056)'));
  425. });
  426. it('identifies a date string', function () {
  427. assert(util.isDate('1995-01-01'));
  428. });
  429. it('identifies a date string', function () {
  430. assert.equal(util.isDate(''), false);
  431. });
  432. it('identifies non-dates', function () {
  433. assert.equal(util.isDate(null), false);
  434. assert.equal(util.isDate(undefined), false);
  435. assert.equal(util.isDate([1, 2, 3]), false);
  436. assert.equal(util.isDate({a: 42}), false);
  437. assert.equal(util.isDate(42), false);
  438. assert.equal(util.isDate('meow'), false);
  439. });
  440. });
  441. describe('convert', function () {
  442. it('handles null', function () {
  443. assert.equal(util.convert(null), null);
  444. });
  445. it('handles undefined', function () {
  446. assert.equal(util.convert(undefined), undefined);
  447. });
  448. it('undefined type returns original object', function () {
  449. assert.deepEqual(util.convert({}), {});
  450. });
  451. it('non-string type throws', function () {
  452. assert.throws(function () {util.convert({}, {});}, Error, null);
  453. });
  454. it('converts to boolean', function () {
  455. assert(util.convert({}, 'boolean'));
  456. });
  457. it('converts to number', function () {
  458. assert.equal(typeof util.convert('1198908717056', 'number'), "number");
  459. });
  460. it('converts to String', function () {
  461. assert.equal(typeof util.convert({}, 'string'), "string");
  462. });
  463. it('converts to Date from Number', function () {
  464. assert(util.convert(1198908717056, 'Date') instanceof Date);
  465. });
  466. it('converts to Date from String', function () {
  467. assert(util.convert('1198908717056', 'Date') instanceof Date);
  468. });
  469. it('converts to Date from Moment', function () {
  470. assert(util.convert(new moment(), 'Date') instanceof Date);
  471. });
  472. it('throws when converting unknown object to Date', function () {
  473. assert.throws(function () {util.convert({}, 'Date');}, Error, null);
  474. });
  475. xit('converts to Moment from Numbern - Throws a deprecation warning', function () {
  476. assert(util.convert(1198908717056, 'Moment') instanceof moment);
  477. });
  478. it('converts to Moment from String', function () {
  479. assert(util.convert('1198908717056', 'Moment') instanceof moment);
  480. });
  481. it('converts to Moment from Date', function () {
  482. assert(util.convert(new Date(), 'Moment') instanceof moment);
  483. });
  484. it('converts to Moment from Moment', function () {
  485. assert(util.convert(new moment(), 'Moment') instanceof moment);
  486. });
  487. it('throws when converting unknown object to Moment', function () {
  488. assert.throws(function () {util.convert({}, 'Moment');}, Error, null);
  489. });
  490. it('converts to ISODate from Number', function () {
  491. assert(util.convert(1198908717056, 'ISODate') instanceof Date);
  492. });
  493. it('converts to ISODate from String', function () {
  494. assert.equal(typeof util.convert('1995-01-01', 'ISODate'), 'string');
  495. });
  496. it('converts to ISODate from Date - Throws a deprecation warning', function () {
  497. assert.equal(typeof util.convert(new Date(), 'ISODate'), 'string');
  498. });
  499. it('converts to ISODate from Moment', function () {
  500. assert.equal(typeof util.convert(new moment(), 'ISODate'), 'string');
  501. });
  502. it('throws when converting unknown object to ISODate', function () {
  503. assert.throws(function () {util.convert({}, 'ISODate');}, Error, null);
  504. });
  505. it('converts to ASPDate from Number', function () {
  506. assert(ASPDateRegex.test(util.convert(1198908717056, 'ASPDate')));
  507. });
  508. it('converts to ASPDate from String', function () {
  509. assert(ASPDateRegex.test(util.convert('1995-01-01', 'ASPDate')));
  510. });
  511. it('converts to ASPDate from Date', function () {
  512. assert(ASPDateRegex.test(util.convert(new Date(), 'ASPDate')));
  513. });
  514. it('converts to ASPDate from ASPDate', function () {
  515. assert(ASPDateRegex.test(util.convert('/Date(12344444)/', 'ASPDate')));
  516. });
  517. xit('converts to ASPDate from Moment - skipped, because it fails', function () {
  518. assert(ASPDateRegex.test(util.convert(new moment(), 'ASPDate')));
  519. });
  520. it('throws when converting unknown object to ASPDate', function () {
  521. assert.throws(function () {util.convert({}, 'ASPDate');}, Error, null);
  522. });
  523. it('throws when converting unknown type', function () {
  524. assert.throws(function () {util.convert({}, 'UnknownType');}, Error, null);
  525. });
  526. });
  527. describe('getType', function () {
  528. it('of object null is null', function () {
  529. assert.equal(util.getType(null), 'null');
  530. });
  531. it('of object Boolean is Boolean', function () {
  532. function Tester () {}
  533. Tester.prototype = Object.create(Boolean.prototype);
  534. assert.equal(util.getType(new Tester('true')), 'Boolean');
  535. });
  536. it('of object Number is Number', function () {
  537. function Tester () {}
  538. Tester.prototype = Object.create(Number.prototype);
  539. assert.equal(util.getType(new Tester(1)), 'Number');
  540. });
  541. it('of object String is String', function () {
  542. function Tester () {}
  543. Tester.prototype = Object.create(String.prototype);
  544. assert.equal(util.getType(new Tester('stringy!')), 'String');
  545. });
  546. it('of object Array is Array', function () {
  547. assert.equal(util.getType(new Array([])), 'Array');
  548. });
  549. it('of object Date is Date', function () {
  550. assert.equal(util.getType(new Date()), 'Date');
  551. });
  552. it('of object any other type is Object', function () {
  553. assert.equal(util.getType({}), 'Object');
  554. });
  555. it('of number is Number', function () {
  556. assert.equal(util.getType(1), 'Number');
  557. });
  558. it('of boolean is Boolean', function () {
  559. assert.equal(util.getType(true), 'Boolean');
  560. });
  561. it('of string is String', function () {
  562. assert.equal(util.getType('string'), 'String');
  563. });
  564. it('of undefined is undefined', function () {
  565. assert.equal(util.getType(), 'undefined');
  566. });
  567. });
  568. describe('easingFunctions', function () {
  569. it('take a number and output a number', function () {
  570. for (var key in util.easingFunctions) {
  571. if (util.easingFunctions.hasOwnProperty(key)) {
  572. assert.equal(typeof util.easingFunctions[key](1), 'number');
  573. assert.equal(typeof util.easingFunctions[key](0.2), 'number');
  574. }
  575. }
  576. });
  577. });
  578. describe('getScrollBarWidth', function () {
  579. beforeEach(function() {
  580. this.jsdom_global = jsdom_global();
  581. });
  582. afterEach(function() {
  583. this.jsdom_global();
  584. });
  585. it('returns 0 when there is no content', function () {
  586. assert.equal(util.getScrollBarWidth(), 0);
  587. });
  588. });
  589. describe('equalArray', function () {
  590. it('arrays of different lengths are not equal', function () {
  591. assert.equal(util.equalArray([1, 2, 3], [1, 2]), false)
  592. });
  593. it('arrays with different content are not equal', function () {
  594. assert.equal(util.equalArray([1, 2, 3], [3, 2, 1]), false)
  595. });
  596. it('same content arrays are equal', function () {
  597. assert(util.equalArray([1, 2, 3], [1, 2, 3]))
  598. });
  599. it('empty arrays are equal', function () {
  600. assert(util.equalArray([], []))
  601. });
  602. it('the same array is equal', function () {
  603. var arr = [1, 2, 3];
  604. assert(util.equalArray(arr, arr))
  605. });
  606. });
  607. describe('asBoolean', function () {
  608. it('resolves value from a function', function () {
  609. assert(util.option.asBoolean(function () {return true}, false));
  610. });
  611. it('returns default value for null', function () {
  612. assert(util.option.asBoolean(null, true));
  613. });
  614. it('returns true for other types', function () {
  615. assert(util.option.asBoolean('should be true', false));
  616. });
  617. it('returns null for undefined', function () {
  618. assert.equal(util.option.asBoolean(), null);
  619. });
  620. });
  621. describe('asNumber', function () {
  622. it('resolves value from a function', function () {
  623. assert.equal(util.option.asNumber(function () {return 777}, 13), 777);
  624. });
  625. it('returns default value for null', function () {
  626. assert.equal(util.option.asNumber(null, 13), 13);
  627. });
  628. it('returns number for other types', function () {
  629. assert.equal(util.option.asNumber('777', 13), 777);
  630. });
  631. it('returns default for NaN', function () {
  632. assert.equal(util.option.asNumber(NaN, 13), 13);
  633. });
  634. it('returns null for undefined', function () {
  635. assert.equal(util.option.asNumber(), null);
  636. });
  637. });
  638. describe('asString', function () {
  639. it('resolves value from a function', function () {
  640. assert.equal(util.option.asString(function () {return 'entered'}, 'default'), 'entered');
  641. });
  642. it('returns default value for null', function () {
  643. assert.equal(util.option.asString(null, 'default'), 'default');
  644. });
  645. it('returns string for other types', function () {
  646. assert.equal(util.option.asString(777, 'default'), '777');
  647. });
  648. it('returns default for undefined', function () {
  649. assert.equal(util.option.asString(undefined, 'default'), 'default');
  650. });
  651. it('returns null for undefined', function () {
  652. assert.equal(util.option.asString(), null);
  653. });
  654. });
  655. describe('asSize', function () {
  656. it('resolves value from a function', function () {
  657. assert.equal(util.option.asSize(function () {return '100px'}, '50px'), '100px');
  658. });
  659. it('returns default value for null', function () {
  660. assert.equal(util.option.asSize(null, '50px'), '50px');
  661. });
  662. it('returns string with px for other number', function () {
  663. assert.equal(util.option.asSize(100, '50px'), '100px');
  664. });
  665. it('returns default for undefined', function () {
  666. assert.equal(util.option.asSize(undefined, '50px'), '50px');
  667. });
  668. it('returns null for undefined', function () {
  669. assert.equal(util.option.asSize(), null);
  670. });
  671. });
  672. describe('asElement', function () {
  673. before(function() {
  674. this.jsdom_global = jsdom_global();
  675. this.value = document.createElement("div");
  676. this.defaultValue = document.createElement("div");
  677. });
  678. it('resolves value from a function', function () {
  679. var me = this;
  680. assert.equal(util.option.asElement(function () {return me.value}, this.defaultValue), this.value);
  681. });
  682. it('returns Element', function () {
  683. assert.equal(util.option.asElement(this.value, this.defaultValue), this.value);
  684. });
  685. it('returns default value for null', function () {
  686. assert.equal(util.option.asElement(null, this.defaultValue), this.defaultValue);
  687. });
  688. it('returns null for undefined', function () {
  689. assert.equal(util.option.asElement(), null);
  690. });
  691. });
  692. describe('binarySearchValue', function () {
  693. it('Finds center target on odd sized array', function () {
  694. assert.equal(
  695. util.binarySearchValue(
  696. [{id: 'a', val: 0}, {id: 'b', val: 1}, {id: 'c', val: 2}],
  697. 1,
  698. 'val'
  699. ),
  700. 1
  701. );
  702. });
  703. it('Finds target on odd sized array', function () {
  704. assert.equal(
  705. util.binarySearchValue(
  706. [{id: 'a', val: 0}, {id: 'b', val: 1}, {id: 'c', val: 2}],
  707. 2,
  708. 'val'
  709. ),
  710. 2
  711. );
  712. });
  713. it('Cannot find target', function () {
  714. assert.equal(
  715. util.binarySearchValue(
  716. [{id: 'a', val: 0}, {id: 'b', val: 1}, {id: 'c', val: 2}],
  717. 7,
  718. 'val'
  719. ),
  720. -1
  721. );
  722. });
  723. });
  724. });