helpers.core.tests.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. 'use strict';
  2. describe('Chart.helpers.core', function() {
  3. var helpers = Chart.helpers;
  4. describe('noop', function() {
  5. it('should be callable', function() {
  6. expect(helpers.noop).toBeDefined();
  7. expect(typeof helpers.noop).toBe('function');
  8. expect(typeof helpers.noop.call).toBe('function');
  9. });
  10. it('should returns "undefined"', function() {
  11. expect(helpers.noop(42)).not.toBeDefined();
  12. expect(helpers.noop.call(this, 42)).not.toBeDefined();
  13. });
  14. });
  15. describe('isArray', function() {
  16. it('should return true if value is an array', function() {
  17. expect(helpers.isArray([])).toBeTruthy();
  18. expect(helpers.isArray([42])).toBeTruthy();
  19. expect(helpers.isArray(new Array())).toBeTruthy();
  20. expect(helpers.isArray(Array.prototype)).toBeTruthy();
  21. expect(helpers.isArray(new Int8Array(2))).toBeTruthy();
  22. expect(helpers.isArray(new Uint8Array())).toBeTruthy();
  23. expect(helpers.isArray(new Uint8ClampedArray([128, 244]))).toBeTruthy();
  24. expect(helpers.isArray(new Int16Array())).toBeTruthy();
  25. expect(helpers.isArray(new Uint16Array())).toBeTruthy();
  26. expect(helpers.isArray(new Int32Array())).toBeTruthy();
  27. expect(helpers.isArray(new Uint32Array())).toBeTruthy();
  28. expect(helpers.isArray(new Float32Array([1.2]))).toBeTruthy();
  29. expect(helpers.isArray(new Float64Array([]))).toBeTruthy();
  30. });
  31. it('should return false if value is not an array', function() {
  32. expect(helpers.isArray()).toBeFalsy();
  33. expect(helpers.isArray({})).toBeFalsy();
  34. expect(helpers.isArray(undefined)).toBeFalsy();
  35. expect(helpers.isArray(null)).toBeFalsy();
  36. expect(helpers.isArray(true)).toBeFalsy();
  37. expect(helpers.isArray(false)).toBeFalsy();
  38. expect(helpers.isArray(42)).toBeFalsy();
  39. expect(helpers.isArray('Array')).toBeFalsy();
  40. expect(helpers.isArray({__proto__: Array.prototype})).toBeFalsy();
  41. });
  42. });
  43. describe('isObject', function() {
  44. it('should return true if value is an object', function() {
  45. expect(helpers.isObject({})).toBeTruthy();
  46. expect(helpers.isObject({a: 42})).toBeTruthy();
  47. expect(helpers.isObject(new Object())).toBeTruthy();
  48. });
  49. it('should return false if value is not an object', function() {
  50. expect(helpers.isObject()).toBeFalsy();
  51. expect(helpers.isObject(undefined)).toBeFalsy();
  52. expect(helpers.isObject(null)).toBeFalsy();
  53. expect(helpers.isObject(true)).toBeFalsy();
  54. expect(helpers.isObject(false)).toBeFalsy();
  55. expect(helpers.isObject(42)).toBeFalsy();
  56. expect(helpers.isObject('Object')).toBeFalsy();
  57. expect(helpers.isObject([])).toBeFalsy();
  58. expect(helpers.isObject([42])).toBeFalsy();
  59. expect(helpers.isObject(new Array())).toBeFalsy();
  60. expect(helpers.isObject(new Date())).toBeFalsy();
  61. });
  62. });
  63. describe('isFinite', function() {
  64. it('should return true if value is a finite number', function() {
  65. expect(helpers.isFinite(0)).toBeTruthy();
  66. // eslint-disable-next-line no-new-wrappers
  67. expect(helpers.isFinite(new Number(10))).toBeTruthy();
  68. });
  69. it('should return false if the value is infinite', function() {
  70. expect(helpers.isFinite(Number.POSITIVE_INFINITY)).toBeFalsy();
  71. expect(helpers.isFinite(Number.NEGATIVE_INFINITY)).toBeFalsy();
  72. });
  73. it('should return false if the value is not a number', function() {
  74. expect(helpers.isFinite('a')).toBeFalsy();
  75. expect(helpers.isFinite({})).toBeFalsy();
  76. });
  77. });
  78. describe('isNullOrUndef', function() {
  79. it('should return true if value is null/undefined', function() {
  80. expect(helpers.isNullOrUndef(null)).toBeTruthy();
  81. expect(helpers.isNullOrUndef(undefined)).toBeTruthy();
  82. });
  83. it('should return false if value is not null/undefined', function() {
  84. expect(helpers.isNullOrUndef(true)).toBeFalsy();
  85. expect(helpers.isNullOrUndef(false)).toBeFalsy();
  86. expect(helpers.isNullOrUndef('')).toBeFalsy();
  87. expect(helpers.isNullOrUndef('String')).toBeFalsy();
  88. expect(helpers.isNullOrUndef(0)).toBeFalsy();
  89. expect(helpers.isNullOrUndef([])).toBeFalsy();
  90. expect(helpers.isNullOrUndef({})).toBeFalsy();
  91. expect(helpers.isNullOrUndef([42])).toBeFalsy();
  92. expect(helpers.isNullOrUndef(new Date())).toBeFalsy();
  93. });
  94. });
  95. describe('valueOrDefault', function() {
  96. it('should return value if defined', function() {
  97. var object = {};
  98. var array = [];
  99. expect(helpers.valueOrDefault(null, 42)).toBe(null);
  100. expect(helpers.valueOrDefault(false, 42)).toBe(false);
  101. expect(helpers.valueOrDefault(object, 42)).toBe(object);
  102. expect(helpers.valueOrDefault(array, 42)).toBe(array);
  103. expect(helpers.valueOrDefault('', 42)).toBe('');
  104. expect(helpers.valueOrDefault(0, 42)).toBe(0);
  105. });
  106. it('should return default if undefined', function() {
  107. expect(helpers.valueOrDefault(undefined, 42)).toBe(42);
  108. expect(helpers.valueOrDefault({}.foo, 42)).toBe(42);
  109. });
  110. });
  111. describe('valueAtIndexOrDefault', function() {
  112. it('should return the passed value if not an array', function() {
  113. expect(helpers.valueAtIndexOrDefault(0, 0, 42)).toBe(0);
  114. expect(helpers.valueAtIndexOrDefault('', 0, 42)).toBe('');
  115. expect(helpers.valueAtIndexOrDefault(null, 0, 42)).toBe(null);
  116. expect(helpers.valueAtIndexOrDefault(false, 0, 42)).toBe(false);
  117. expect(helpers.valueAtIndexOrDefault(98, 0, 42)).toBe(98);
  118. });
  119. it('should return the value at index if defined', function() {
  120. expect(helpers.valueAtIndexOrDefault([1, false, 'foo'], 1, 42)).toBe(false);
  121. expect(helpers.valueAtIndexOrDefault([1, false, 'foo'], 2, 42)).toBe('foo');
  122. });
  123. it('should return the default value if the passed value is undefined', function() {
  124. expect(helpers.valueAtIndexOrDefault(undefined, 0, 42)).toBe(42);
  125. });
  126. it('should return the default value if value at index is undefined', function() {
  127. expect(helpers.valueAtIndexOrDefault([1, false, 'foo'], 3, 42)).toBe(42);
  128. expect(helpers.valueAtIndexOrDefault([1, undefined, 'foo'], 1, 42)).toBe(42);
  129. });
  130. });
  131. describe('callback', function() {
  132. it('should return undefined if fn is not a function', function() {
  133. expect(helpers.callback()).not.toBeDefined();
  134. expect(helpers.callback(null)).not.toBeDefined();
  135. expect(helpers.callback(42)).not.toBeDefined();
  136. expect(helpers.callback([])).not.toBeDefined();
  137. expect(helpers.callback({})).not.toBeDefined();
  138. });
  139. it('should call fn with the given args', function() {
  140. var spy = jasmine.createSpy('spy');
  141. helpers.callback(spy);
  142. helpers.callback(spy, []);
  143. helpers.callback(spy, ['foo']);
  144. helpers.callback(spy, [42, 'bar']);
  145. expect(spy.calls.argsFor(0)).toEqual([]);
  146. expect(spy.calls.argsFor(1)).toEqual([]);
  147. expect(spy.calls.argsFor(2)).toEqual(['foo']);
  148. expect(spy.calls.argsFor(3)).toEqual([42, 'bar']);
  149. });
  150. it('should call fn with the given scope', function() {
  151. var spy = jasmine.createSpy('spy');
  152. var scope = {};
  153. helpers.callback(spy);
  154. helpers.callback(spy, [], null);
  155. helpers.callback(spy, [], undefined);
  156. helpers.callback(spy, [], scope);
  157. expect(spy.calls.all()[0].object).toBe(window);
  158. expect(spy.calls.all()[1].object).toBe(window);
  159. expect(spy.calls.all()[2].object).toBe(window);
  160. expect(spy.calls.all()[3].object).toBe(scope);
  161. });
  162. it('should return the value returned by fn', function() {
  163. expect(helpers.callback(helpers.noop, [41])).toBe(undefined);
  164. expect(helpers.callback(function(i) {
  165. return i + 1;
  166. }, [41])).toBe(42);
  167. });
  168. });
  169. describe('each', function() {
  170. it('should iterate over an array forward if reverse === false', function() {
  171. var scope = {};
  172. var scopes = [];
  173. var items = [];
  174. var keys = [];
  175. helpers.each(['foo', 'bar', 42], function(item, key) {
  176. scopes.push(this);
  177. items.push(item);
  178. keys.push(key);
  179. }, scope);
  180. expect(scopes).toEqual([scope, scope, scope]);
  181. expect(items).toEqual(['foo', 'bar', 42]);
  182. expect(keys).toEqual([0, 1, 2]);
  183. });
  184. it('should iterate over an array backward if reverse === true', function() {
  185. var scope = {};
  186. var scopes = [];
  187. var items = [];
  188. var keys = [];
  189. helpers.each(['foo', 'bar', 42], function(item, key) {
  190. scopes.push(this);
  191. items.push(item);
  192. keys.push(key);
  193. }, scope, true);
  194. expect(scopes).toEqual([scope, scope, scope]);
  195. expect(items).toEqual([42, 'bar', 'foo']);
  196. expect(keys).toEqual([2, 1, 0]);
  197. });
  198. it('should iterate over object properties', function() {
  199. var scope = {};
  200. var scopes = [];
  201. var items = [];
  202. helpers.each({a: 'foo', b: 'bar', c: 42}, function(item, key) {
  203. scopes.push(this);
  204. items[key] = item;
  205. }, scope);
  206. expect(scopes).toEqual([scope, scope, scope]);
  207. expect(items).toEqual(jasmine.objectContaining({a: 'foo', b: 'bar', c: 42}));
  208. });
  209. it('should not throw when called with a non iterable object', function() {
  210. expect(function() {
  211. helpers.each(undefined);
  212. }).not.toThrow();
  213. expect(function() {
  214. helpers.each(null);
  215. }).not.toThrow();
  216. expect(function() {
  217. helpers.each(42);
  218. }).not.toThrow();
  219. });
  220. });
  221. describe('arrayEquals', function() {
  222. it('should return false if arrays are not the same', function() {
  223. expect(helpers.arrayEquals([], [42])).toBeFalsy();
  224. expect(helpers.arrayEquals([42], ['42'])).toBeFalsy();
  225. expect(helpers.arrayEquals([1, 2, 3], [1, 2, 3, 4])).toBeFalsy();
  226. expect(helpers.arrayEquals(['foo', 'bar'], ['bar', 'foo'])).toBeFalsy();
  227. expect(helpers.arrayEquals([1, 2, 3], [1, 2, 'foo'])).toBeFalsy();
  228. expect(helpers.arrayEquals([1, 2, [3, 4]], [1, 2, [3, 'foo']])).toBeFalsy();
  229. expect(helpers.arrayEquals([{a: 42}], [{a: 42}])).toBeFalsy();
  230. });
  231. it('should return false if arrays are not the same', function() {
  232. var o0 = {};
  233. var o1 = {};
  234. var o2 = {};
  235. expect(helpers.arrayEquals([], [])).toBeTruthy();
  236. expect(helpers.arrayEquals([1, 2, 3], [1, 2, 3])).toBeTruthy();
  237. expect(helpers.arrayEquals(['foo', 'bar'], ['foo', 'bar'])).toBeTruthy();
  238. expect(helpers.arrayEquals([true, false, true], [true, false, true])).toBeTruthy();
  239. expect(helpers.arrayEquals([o0, o1, o2], [o0, o1, o2])).toBeTruthy();
  240. });
  241. });
  242. describe('clone', function() {
  243. it('should clone primitive values', function() {
  244. expect(helpers.clone()).toBe(undefined);
  245. expect(helpers.clone(null)).toBe(null);
  246. expect(helpers.clone(true)).toBe(true);
  247. expect(helpers.clone(42)).toBe(42);
  248. expect(helpers.clone('foo')).toBe('foo');
  249. });
  250. it('should perform a deep copy of arrays', function() {
  251. var o0 = {a: 42};
  252. var o1 = {s: 's'};
  253. var a0 = ['bar'];
  254. var a1 = [a0, o0, 2];
  255. var f0 = function() {};
  256. var input = [a1, o1, f0, 42, 'foo'];
  257. var output = helpers.clone(input);
  258. expect(output).toEqual(input);
  259. expect(output).not.toBe(input);
  260. expect(output[0]).not.toBe(a1);
  261. expect(output[0][0]).not.toBe(a0);
  262. expect(output[1]).not.toBe(o1);
  263. });
  264. it('should perform a deep copy of objects', function() {
  265. var a0 = ['bar'];
  266. var a1 = [1, 2, 3];
  267. var o0 = {a: a1, i: 42};
  268. var f0 = function() {};
  269. var input = {o: o0, a: a0, f: f0, s: 'foo', i: 42};
  270. var output = helpers.clone(input);
  271. expect(output).toEqual(input);
  272. expect(output).not.toBe(input);
  273. expect(output.o).not.toBe(o0);
  274. expect(output.o.a).not.toBe(a1);
  275. expect(output.a).not.toBe(a0);
  276. });
  277. });
  278. describe('merge', function() {
  279. it('should update target and return it', function() {
  280. var target = {a: 1};
  281. var result = helpers.merge(target, {a: 2, b: 'foo'});
  282. expect(target).toEqual({a: 2, b: 'foo'});
  283. expect(target).toBe(result);
  284. });
  285. it('should return target if not an object', function() {
  286. expect(helpers.merge(undefined, {a: 42})).toEqual(undefined);
  287. expect(helpers.merge(null, {a: 42})).toEqual(null);
  288. expect(helpers.merge('foo', {a: 42})).toEqual('foo');
  289. expect(helpers.merge(['foo', 'bar'], {a: 42})).toEqual(['foo', 'bar']);
  290. });
  291. it('should ignore sources which are not objects', function() {
  292. expect(helpers.merge({a: 42})).toEqual({a: 42});
  293. expect(helpers.merge({a: 42}, null)).toEqual({a: 42});
  294. expect(helpers.merge({a: 42}, 42)).toEqual({a: 42});
  295. });
  296. it('should recursively overwrite target with source properties', function() {
  297. expect(helpers.merge({a: {b: 1}}, {a: {c: 2}})).toEqual({a: {b: 1, c: 2}});
  298. expect(helpers.merge({a: {b: 1}}, {a: {b: 2}})).toEqual({a: {b: 2}});
  299. expect(helpers.merge({a: [1, 2]}, {a: [3, 4]})).toEqual({a: [3, 4]});
  300. expect(helpers.merge({a: 42}, {a: {b: 0}})).toEqual({a: {b: 0}});
  301. expect(helpers.merge({a: 42}, {a: null})).toEqual({a: null});
  302. expect(helpers.merge({a: 42}, {a: undefined})).toEqual({a: undefined});
  303. });
  304. it('should merge multiple sources in the correct order', function() {
  305. var t0 = {a: {b: 1, c: [1, 2]}};
  306. var s0 = {a: {d: 3}, e: {f: 4}};
  307. var s1 = {a: {b: 5}};
  308. var s2 = {a: {c: [6, 7]}, e: 'foo'};
  309. expect(helpers.merge(t0, [s0, s1, s2])).toEqual({a: {b: 5, c: [6, 7], d: 3}, e: 'foo'});
  310. });
  311. it('should deep copy merged values from sources', function() {
  312. var a0 = ['foo'];
  313. var a1 = [1, 2, 3];
  314. var o0 = {a: a1, i: 42};
  315. var output = helpers.merge({}, {a: a0, o: o0});
  316. expect(output).toEqual({a: a0, o: o0});
  317. expect(output.a).not.toBe(a0);
  318. expect(output.o).not.toBe(o0);
  319. expect(output.o.a).not.toBe(a1);
  320. });
  321. });
  322. describe('mergeIf', function() {
  323. it('should update target and return it', function() {
  324. var target = {a: 1};
  325. var result = helpers.mergeIf(target, {a: 2, b: 'foo'});
  326. expect(target).toEqual({a: 1, b: 'foo'});
  327. expect(target).toBe(result);
  328. });
  329. it('should return target if not an object', function() {
  330. expect(helpers.mergeIf(undefined, {a: 42})).toEqual(undefined);
  331. expect(helpers.mergeIf(null, {a: 42})).toEqual(null);
  332. expect(helpers.mergeIf('foo', {a: 42})).toEqual('foo');
  333. expect(helpers.mergeIf(['foo', 'bar'], {a: 42})).toEqual(['foo', 'bar']);
  334. });
  335. it('should ignore sources which are not objects', function() {
  336. expect(helpers.mergeIf({a: 42})).toEqual({a: 42});
  337. expect(helpers.mergeIf({a: 42}, null)).toEqual({a: 42});
  338. expect(helpers.mergeIf({a: 42}, 42)).toEqual({a: 42});
  339. });
  340. it('should recursively copy source properties in target only if they do not exist in target', function() {
  341. expect(helpers.mergeIf({a: {b: 1}}, {a: {c: 2}})).toEqual({a: {b: 1, c: 2}});
  342. expect(helpers.mergeIf({a: {b: 1}}, {a: {b: 2}})).toEqual({a: {b: 1}});
  343. expect(helpers.mergeIf({a: [1, 2]}, {a: [3, 4]})).toEqual({a: [1, 2]});
  344. expect(helpers.mergeIf({a: 0}, {a: {b: 2}})).toEqual({a: 0});
  345. expect(helpers.mergeIf({a: null}, {a: 42})).toEqual({a: null});
  346. expect(helpers.mergeIf({a: undefined}, {a: 42})).toEqual({a: undefined});
  347. });
  348. it('should merge multiple sources in the correct order', function() {
  349. var t0 = {a: {b: 1, c: [1, 2]}};
  350. var s0 = {a: {d: 3}, e: {f: 4}};
  351. var s1 = {a: {b: 5}};
  352. var s2 = {a: {c: [6, 7]}, e: 'foo'};
  353. expect(helpers.mergeIf(t0, [s0, s1, s2])).toEqual({a: {b: 1, c: [1, 2], d: 3}, e: {f: 4}});
  354. });
  355. it('should deep copy merged values from sources', function() {
  356. var a0 = ['foo'];
  357. var a1 = [1, 2, 3];
  358. var o0 = {a: a1, i: 42};
  359. var output = helpers.mergeIf({}, {a: a0, o: o0});
  360. expect(output).toEqual({a: a0, o: o0});
  361. expect(output.a).not.toBe(a0);
  362. expect(output.o).not.toBe(o0);
  363. expect(output.o.a).not.toBe(a1);
  364. });
  365. });
  366. describe('extend', function() {
  367. it('should merge object properties in target and return target', function() {
  368. var target = {a: 'abc', b: 56};
  369. var object = {b: 0, c: [2, 5, 6]};
  370. var result = helpers.extend(target, object);
  371. expect(result).toBe(target);
  372. expect(target).toEqual({a: 'abc', b: 0, c: [2, 5, 6]});
  373. });
  374. it('should merge multiple objects properties in target', function() {
  375. var target = {a: 0, b: 1};
  376. var o0 = {a: 2, c: 3, d: 4};
  377. var o1 = {a: 5, c: 6};
  378. var o2 = {a: 7, e: 8};
  379. helpers.extend(target, o0, o1, o2);
  380. expect(target).toEqual({a: 7, b: 1, c: 6, d: 4, e: 8});
  381. });
  382. it('should not deeply merge object properties in target', function() {
  383. var target = {a: {b: 0, c: 1}};
  384. var object = {a: {b: 2, d: 3}};
  385. helpers.extend(target, object);
  386. expect(target).toEqual({a: {b: 2, d: 3}});
  387. expect(target.a).toBe(object.a);
  388. });
  389. });
  390. describe('inherits', function() {
  391. it('should return a derived class', function() {
  392. var A = function() {};
  393. A.prototype.p0 = 41;
  394. A.prototype.p1 = function() {
  395. return '42';
  396. };
  397. A.inherits = helpers.inherits;
  398. var B = A.inherits({p0: 43, p2: [44]});
  399. var C = A.inherits({p3: 45, p4: [46]});
  400. var b = new B();
  401. expect(b instanceof A).toBeTruthy();
  402. expect(b instanceof B).toBeTruthy();
  403. expect(b instanceof C).toBeFalsy();
  404. expect(b.p0).toBe(43);
  405. expect(b.p1()).toBe('42');
  406. expect(b.p2).toEqual([44]);
  407. });
  408. });
  409. });