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.

830 lines
20 KiB

4 years ago
  1. 'use strict';
  2. const assert = require('assert');
  3. const _ = require('lodash');
  4. describe('code snippet example', () => {
  5. it('compact', () => {
  6. assert.deepEqual(
  7. _.compact([0, 1, false, 2, '', 3]),
  8. [0, 1, false, 2, '', 3].filter(v => v)
  9. )
  10. })
  11. it('concat', () => {
  12. const lodashArray = [1]
  13. const lodashResult = _.concat(lodashArray, 2, [3], [[4]])
  14. const nativehArray = [1]
  15. const nativeResult = nativehArray.concat(2, [3], [[4]])
  16. assert.deepEqual(lodashResult, nativeResult)
  17. })
  18. it('pick', () => {
  19. var object = { 'a': 1, 'b': '2', 'c': 3 };
  20. function pick(object, paths) {
  21. const obj = {};
  22. for (const path of paths) {
  23. if (object[path]) {
  24. obj[path] = object[path]
  25. }
  26. }
  27. return obj;
  28. }
  29. assert.deepEqual(
  30. _.pick(object, ['a', 'c']),
  31. pick(object, ['a', 'c'])
  32. )
  33. })
  34. it('pickBy', () => {
  35. var object = { 'a': 1, 'b': null, 'c': 3, 'd': false, 'e': undefined, 'f': '', 'g': 0 };
  36. function pickBy(object) {
  37. const obj = {};
  38. for (const key in object) {
  39. if (object[key]) {
  40. obj[key] = object[key];
  41. }
  42. }
  43. return obj;
  44. }
  45. assert.deepEqual(
  46. _.pickBy(object),
  47. pickBy(object)
  48. )
  49. })
  50. describe('fill', () => {
  51. it("_.fill(array, 'a')", () => {
  52. var array = [1, 2, 3]
  53. assert.deepEqual(
  54. _.fill(array, 'a'),
  55. array.fill('a')
  56. )
  57. })
  58. it("_.fill(Array(3), 2)", () => {
  59. assert.deepEqual(
  60. _.fill(Array(3), 2),
  61. Array(3).fill(2)
  62. )
  63. })
  64. it("_.fill([4, 6, 8, 10], '*', 1, 3)", () => {
  65. assert.deepEqual(
  66. _.fill([4, 6, 8, 10], '*', 1, 3),
  67. [4, 6, 8, 10].fill('*', 1, 3)
  68. )
  69. })
  70. })
  71. describe('chunk', () => {
  72. const chunk = (input, size) => {
  73. return input.reduce((arr, item, idx) => {
  74. return idx % size === 0
  75. ? [...arr, [item]]
  76. : [...arr.slice(0, -1), [...arr.slice(-1)[0], item]];
  77. }, []);
  78. };
  79. it("_.chunk(['a', 'b', 'c', 'd'], 2);", () => {
  80. assert.deepEqual(
  81. _.chunk(['a', 'b', 'c', 'd'], 2),
  82. chunk(['a', 'b', 'c', 'd'], 2)
  83. )
  84. })
  85. it("_.chunk(['a', 'b', 'c', 'd'], 3);", () => {
  86. assert.deepEqual(
  87. _.chunk(['a', 'b', 'c', 'd'], 3),
  88. chunk(['a', 'b', 'c', 'd'], 3)
  89. )
  90. })
  91. })
  92. describe('times', () => {
  93. const times = (n, fn = (_, x) => x) => {
  94. return Array.from(Array(n), fn)
  95. };
  96. it("_.times(10);", () => {
  97. assert.deepEqual(
  98. _.times(10),
  99. times(10)
  100. )
  101. })
  102. it("_.times(10, x => x + 1);", () => {
  103. assert.deepEqual(
  104. _.times(10, x => x + 1),
  105. times(10, (_, x) => x + 1)
  106. )
  107. })
  108. })
  109. describe('assign', () => {
  110. function Foo() {
  111. this.c = 3;
  112. }
  113. function Bar() {
  114. this.e = 5;
  115. }
  116. Foo.prototype.d = 4;
  117. Bar.prototype.f = 6;
  118. const assign = (target, ...sources) => Object.assign(target, ...sources);
  119. it("_.assign({}, new Foo, new Bar);", () => {
  120. assert.deepEqual(
  121. _.assign({}, new Foo, new Bar),
  122. assign({}, new Foo, new Bar)
  123. )
  124. })
  125. it("_.assign(new Foo, new Bar);", () => {
  126. assert.deepEqual(
  127. _.assign(new Foo, new Bar),
  128. assign(new Foo, new Bar)
  129. )
  130. })
  131. })
  132. describe('extend', () => {
  133. function Foo() {
  134. this.c = 3;
  135. }
  136. function Bar() {
  137. this.e = 5;
  138. }
  139. Foo.prototype.d = 4;
  140. Bar.prototype.f = 6;
  141. const extend = (target, ...sources) => {
  142. const length = sources.length;
  143. if (length < 1 || target == null) return target;
  144. for (let i = 0; i < length; i++) {
  145. const source = sources[i];
  146. for (const key in source) {
  147. target[key] = source[key];
  148. }
  149. }
  150. return target;
  151. };
  152. it("_.extend({}, new Foo, new Bar);", () => {
  153. assert.deepEqual(
  154. _.extend({}, new Foo, new Bar),
  155. extend({}, new Foo, new Bar)
  156. )
  157. })
  158. it("_.extend(new Foo, new Bar);", () => {
  159. assert.deepEqual(
  160. _.extend(new Foo, new Bar),
  161. extend(new Foo, new Bar)
  162. )
  163. })
  164. })
  165. describe('isEmpty', () => {
  166. const isEmpty = (obj) => {
  167. return (obj ? [Object, Array].includes(obj.constructor) && !Object.entries(obj).length : true);
  168. };
  169. it ('_.isEmpty(null)', () => {
  170. assert.equal(
  171. _.isEmpty(null),
  172. isEmpty(null)
  173. )
  174. })
  175. it ("_.isEmpty('')", () => {
  176. assert.equal(
  177. _.isEmpty(''),
  178. isEmpty('')
  179. )
  180. })
  181. it ("_.isEmpty({})", () => {
  182. assert.equal(
  183. _.isEmpty({}),
  184. isEmpty({})
  185. )
  186. })
  187. it ("_.isEmpty([])", () => {
  188. assert.equal(
  189. _.isEmpty([]),
  190. isEmpty([])
  191. )
  192. })
  193. it ("_.isEmpty({a: '1'})", () => {
  194. assert.equal(
  195. _.isEmpty({a: '1'}),
  196. isEmpty({a: '1'})
  197. )
  198. })
  199. })
  200. describe('isInteger', () => {
  201. it('_.isInteger(3)', () => {
  202. assert.equal(
  203. _.isInteger(3),
  204. Number.isInteger(3)
  205. )
  206. })
  207. it('_.isInteger("3")', () => {
  208. assert.equal(
  209. _.isInteger("3"),
  210. Number.isInteger("3")
  211. )
  212. })
  213. it('_.isInteger(2.9)', () => {
  214. assert.equal(
  215. _.isInteger(2.9),
  216. Number.isInteger(2.9)
  217. )
  218. })
  219. it('_.isInteger(NaN)', () => {
  220. assert.equal(
  221. _.isInteger(NaN),
  222. Number.isInteger(NaN)
  223. )
  224. })
  225. })
  226. describe('get', () => {
  227. const get = (obj, path, defaultValue) => {
  228. const travel = regexp =>
  229. String.prototype.split
  230. .call(path, regexp)
  231. .filter(Boolean)
  232. .reduce((res, key) => (res !== null && res !== undefined ? res[key] : res), obj);
  233. const result = travel(/[,[\]]+?/) || travel(/[,[\].]+?/);
  234. return result === undefined || result === obj ? defaultValue : result;
  235. };
  236. var obj = {
  237. aa: [{ b: { c: 0 }, 1: 0 }],
  238. dd: { ee: { ff: 2 } },
  239. gg: { h: 2 },
  240. "gg.h": 1,
  241. "kk.ll": { "mm.n": [3, 4, { "oo.p": 5 }] }
  242. };
  243. it ("should handle falsey values", () => {
  244. var val = _.get(obj, 'aa[0].b.c', 1)
  245. assert.strictEqual(val, get(obj, 'aa[0].b.c', 1))
  246. assert.notEqual(val, 1)
  247. })
  248. it ("should handle just bracket notation", () => {
  249. var val = _.get(obj, 'aa[0][1]', 1)
  250. assert.strictEqual(val, get(obj, 'aa[0][1]', 1))
  251. assert.notEqual(val, 1)
  252. })
  253. it ("should handle just period notation", () => {
  254. var val = _.get(obj, 'dd.ee.ff', 1)
  255. assert.strictEqual(val, get(obj, 'dd.ee.ff', 1))
  256. assert.notEqual(val, 1)
  257. })
  258. it ("should handle neither notation", () => {
  259. var val = _.get(obj, 'aa', 1)
  260. assert.deepEqual(val, get(obj, 'aa', 1))
  261. assert.notEqual(val, 1)
  262. })
  263. it ("should handle both notation", () => {
  264. var val = _.get(obj, 'aa[0].b.c', 1)
  265. assert.strictEqual(val, get(obj, 'aa[0].b.c', 1))
  266. assert.notEqual(val, 1)
  267. })
  268. it ("should handle array path", () => {
  269. var val = _.get(obj, ['aa', [0], 'b', 'c'], 1)
  270. assert.strictEqual(val, get(obj, ['aa', [0], 'b', 'c'], 1))
  271. assert.notEqual(val, 1)
  272. })
  273. it ("should handle undefined without default", () => {
  274. var val = _.get(obj, 'dd.b')
  275. assert.strictEqual(val, get(obj, 'dd.b'))
  276. })
  277. it ("should handle undefined with default", () => {
  278. var val = _.get(obj, 'dd.b', 1)
  279. assert.strictEqual(val, get(obj, 'dd.b', 1))
  280. })
  281. it ("should handle deep undefined without default", () => {
  282. var val = _.get(obj, 'dd.b.c')
  283. assert.strictEqual(val, get(obj, 'dd.b.c'))
  284. })
  285. it ("should handle deep undefined with default", () => {
  286. var val = _.get(obj, 'dd.b.c', 1)
  287. assert.strictEqual(val, get(obj, 'dd.b.c', 1))
  288. assert.strictEqual(val, 1);
  289. })
  290. it ("should handle null default", () => {
  291. var val = _.get(obj, 'dd.b', null)
  292. assert.strictEqual(val, get(obj, 'dd.b', null))
  293. assert.strictEqual(val, null);
  294. })
  295. it ("should handle empty path", () => {
  296. var val = _.get(obj, '', 1)
  297. assert.strictEqual(val, get(obj, '', 1))
  298. assert.notEqual(val, obj);
  299. })
  300. it ("should handle undefined obj", () => {
  301. var val = _.get(undefined, 'aa')
  302. assert.strictEqual(val, get(undefined, 'aa'))
  303. })
  304. it ("should handle path contains a key with dots", () => {
  305. var val = _.get(obj, 'gg.h')
  306. assert.strictEqual(val, get(obj, 'gg.h'))
  307. assert.strictEqual(val, 1)
  308. })
  309. it ("should handle array path of keys with dots", () => {
  310. var val = _.get(obj, ["kk.ll", "mm.n", 0, "oo.p"])
  311. assert.strictEqual(
  312. val,
  313. get(obj, ["kk.ll", "mm.n", 0, "oo.p"])
  314. );
  315. })
  316. })
  317. describe('split', () => {
  318. const source = 'a-b-c';
  319. const separator = '-';
  320. const limit = 2;
  321. it(`_.split("${source}", "${separator}")`, () => {
  322. assert.deepEqual(
  323. _.split(source, separator),
  324. source.split(separator)
  325. );
  326. })
  327. it(`_.split("${source}", "${separator}", ${limit})`, () => {
  328. assert.deepEqual(
  329. _.split(source, separator, limit),
  330. source.split(separator, limit)
  331. );
  332. })
  333. })
  334. describe('inRange', () => {
  335. const inRange = (num, init, final) => {
  336. if(final === undefined){
  337. final = init;
  338. init = 0;
  339. }
  340. return (num >= Math.min(init, final) && num < Math.max(init, final));
  341. }
  342. it('_.inRange(3, 2, 4)', () => {
  343. assert.equal(
  344. _.inRange(3, 2, 4),
  345. inRange(3, 2, 4)
  346. )
  347. });
  348. it('_.inRange(4, 8)', () => {
  349. assert.equal(
  350. _.inRange(4, 8),
  351. inRange(4, 8)
  352. )
  353. });
  354. it('_.inRange(4, 2)', () => {
  355. assert.equal(
  356. _.inRange(4, 2),
  357. inRange(4, 2)
  358. )
  359. });
  360. it('_.inRange(2, 2)', () => {
  361. assert.equal(
  362. _.inRange(2, 2),
  363. inRange(2, 2)
  364. )
  365. });
  366. it('_.inRange(1.2, 2)', () => {
  367. assert.equal(
  368. _.inRange(1.2, 2),
  369. inRange(1.2, 2)
  370. )
  371. });
  372. it('_.inRange(5.2, 4)', () => {
  373. assert.equal(
  374. _.inRange(5.2, 4),
  375. inRange(5.2, 4)
  376. )
  377. });
  378. it('_.inRange(-3, -2, -6)', () => {
  379. assert.equal(
  380. _.inRange(-3, -2, -6),
  381. inRange(-3, -2, -6)
  382. )
  383. });
  384. it('_.inRange(1, 1, 5)', () => {
  385. assert.equal(
  386. _.inRange(1, 1, 5),
  387. inRange(1, 1, 5)
  388. )
  389. });
  390. })
  391. describe('random', () => {
  392. const random = (a = 1, b = 0) => {
  393. const lower = Math.min(a, b);
  394. const upper = Math.max(a, b);
  395. return lower + Math.random() * (upper - lower);
  396. };
  397. const array = Array(1000).fill(0);
  398. it('random() in range [0, 1]', () => {
  399. assert.ok(array.every(() => {
  400. const randomValue = random();
  401. return randomValue >= 0 && randomValue <= 1;
  402. }));
  403. });
  404. it('random() is float', () => {
  405. assert.ok(array.some(() => {
  406. const randomValue = random();
  407. return !Number.isInteger(randomValue);
  408. }));
  409. });
  410. it('random(5) in range [0, 5]', () => {
  411. assert.ok(array.every(() => {
  412. const randomValue = random(5);
  413. return randomValue >= 0 && randomValue <= 5;
  414. }));
  415. });
  416. it('random(5) is float', () => {
  417. assert.ok(array.some(() => {
  418. const randomValue = random(5);
  419. return !Number.isInteger(randomValue);
  420. }));
  421. });
  422. it('random(-10) supports negative', () => {
  423. assert.ok(array.every(() => {
  424. const randomValue = random(-10);
  425. return randomValue <= 0;
  426. }));
  427. });
  428. it('random(10, 5) swap the bounds', () => {
  429. assert.ok(array.every(() => {
  430. const randomValue = random(10, 5);
  431. return randomValue >= 5 && randomValue <= 10;
  432. }));
  433. });
  434. it('random(-10, 10) supports negative', () => {
  435. assert.ok(array.some(() => {
  436. const randomValue = random(-10, 10);
  437. return randomValue > 0;
  438. }));
  439. assert.ok(array.some(() => {
  440. const randomValue = random(-10, 10);
  441. return randomValue < 0;
  442. }));
  443. });
  444. it('random(-10, 10) in range [-10, 10]', () => {
  445. assert.ok(array.every(() => {
  446. const randomValue = random(-10, 10);
  447. return randomValue >= -10 && randomValue <= 10;
  448. }));
  449. });
  450. it('random(1.2, 5.2) supports floats', () => {
  451. assert.ok(array.every(() => {
  452. const randomValue = random(1.2, 5.2);
  453. return randomValue >= 1.2 && randomValue <= 5.2;
  454. }));
  455. });
  456. it('random(100000, 100001) in range [100000, 100001]', () => {
  457. assert.ok(array.every(() => {
  458. const randomValue = random(100000, 100001);
  459. return randomValue >= 100000 && randomValue <= 100001;
  460. }));
  461. });
  462. });
  463. describe('randomInt', () => {
  464. const randomInt = (a = 1, b = 0) => {
  465. const lower = Math.ceil(Math.min(a, b));
  466. const upper = Math.floor(Math.max(a, b));
  467. return Math.floor(lower + Math.random() * (upper - lower + 1))
  468. };
  469. const array = Array(1000).fill(0);
  470. const uniq = (arr) => [...new Set(arr)];
  471. it('randomInt() return `0` or `1`', () => {
  472. const randoms = uniq(array.map(() => {
  473. return randomInt();
  474. })).sort();
  475. assert.deepStrictEqual(randoms, [0, 1]);
  476. });
  477. it('randomInt(5) in range [0, 5]', () => {
  478. assert.ok(array.every(() => {
  479. const randomValue = randomInt(5);
  480. return randomValue >= 0 && randomValue <= 5;
  481. }));
  482. });
  483. it('randomInt(5) is integer', () => {
  484. assert.ok(array.some(() => {
  485. const randomValue = randomInt(5);
  486. return Number.isInteger(randomValue);
  487. }));
  488. });
  489. it('randomInt(-10) supports negative', () => {
  490. assert.ok(array.every(() => {
  491. const randomValue = randomInt(-10);
  492. return randomValue <= 0;
  493. }));
  494. });
  495. it('randomInt(10, 5) swap the bounds', () => {
  496. assert.ok(array.every(() => {
  497. const randomValue = randomInt(10, 5);
  498. return randomValue >= 5 && randomValue <= 10;
  499. }));
  500. });
  501. it('randomInt(-10, 10) supports negative', () => {
  502. assert.ok(array.some(() => {
  503. const randomValue = randomInt(-10, 10);
  504. return randomValue > 0;
  505. }));
  506. assert.ok(array.some(() => {
  507. const randomValue = randomInt(-10, 10);
  508. return randomValue < 0;
  509. }));
  510. });
  511. it('randomInt(-10, 10) in range [-10, 10]', () => {
  512. assert.ok(array.every(() => {
  513. const randomValue = randomInt(-10, 10);
  514. return randomValue >= -10 && randomValue <= 10;
  515. }));
  516. });
  517. it('randomInt(1.2, 5.2) supports floats', () => {
  518. assert.ok(array.every(() => {
  519. const randomValue = randomInt(1.2, 5.2);
  520. return randomValue >= 2 && randomValue <= 5;
  521. }));
  522. });
  523. it('randomInt(100000, 100001) return `100000` or `100001`', () => {
  524. const randoms = uniq(array.map(() => {
  525. return randomInt(100000, 100001);
  526. })).sort();
  527. assert.deepStrictEqual(randoms, [100000, 100001]);
  528. });
  529. });
  530. describe('clamp', () => {
  531. const clamp = (number, boundOne, boundTwo) => {
  532. if (!boundTwo) {
  533. return Math.max(number, boundOne) === boundOne ? number : boundOne;
  534. } else if (Math.min(number, boundOne) === number) {
  535. return boundOne;
  536. } else if (Math.max(number, boundTwo) === number) {
  537. return boundTwo;
  538. }
  539. return number;
  540. };
  541. it('clamp(-10, -5, 5) returns lower bound if number is less than it', () => {
  542. assert.deepStrictEqual(clamp(-10, -5, 5), -5);
  543. });
  544. it('clamp(10, -5, 5) returns upper bound if number is greater than it', () => {
  545. assert.deepStrictEqual(clamp(10, -5, 5), 10);
  546. });
  547. it('clamp(10, -5) treats second parameter as upper bound', () => {
  548. assert.deepStrictEqual(clamp(10, -5), -5);
  549. });
  550. });
  551. describe('padStart', () => {
  552. it('_.padStart("123", 5, "0")', () => {
  553. assert.equal(
  554. _.padStart("123", 5, '0'),
  555. "123".padStart(5, '0')
  556. );
  557. })
  558. it('_.padStart("123", 6, "_-")', () => {
  559. assert.equal(
  560. _.padStart("123", 6, '_-'),
  561. "123".padStart(6, '_-')
  562. );
  563. })
  564. })
  565. describe('padEnd', () => {
  566. it('_.padEnd("123", 5, "0")', () => {
  567. assert.equal(
  568. _.padEnd("123", 5, '0'),
  569. "123".padEnd(5, '0')
  570. );
  571. })
  572. it('_.padEnd("123", 6, "_-")', () => {
  573. assert.equal(
  574. _.padEnd("123", 6, '_-'),
  575. "123".padEnd(6, '_-')
  576. );
  577. })
  578. })
  579. describe('upperFirst', () => {
  580. const upperFirst = (string) => {
  581. return string ? string.charAt(0).toUpperCase() + string.slice(1) : ''
  582. }
  583. it('_.upperFirst("george")', () => {
  584. assert.equal(
  585. _.upperFirst('george'),
  586. upperFirst('george')
  587. )
  588. })
  589. it('_.upperFirst(null)', () => {
  590. assert.equal(
  591. _.upperFirst(null),
  592. upperFirst(null)
  593. )
  594. })
  595. it('_.upperFirst("")', () => {
  596. assert.equal(
  597. _.upperFirst(''),
  598. upperFirst('')
  599. )
  600. })
  601. })
  602. describe('isString', () => {
  603. function isString(str) {
  604. if (str && typeof str.valueOf() === "string") {
  605. return true
  606. }
  607. return false
  608. }
  609. it('_.isString(abc)', () => {
  610. assert.deepEqual(_.isString("abc"),
  611. isString("abc"))
  612. });
  613. it('_.isString(1)', () => {
  614. assert.deepEqual(_.isString(1),
  615. isString(1))
  616. });
  617. });
  618. describe('isUndefined', () => {
  619. const definedVariable = 1; //defined variable (will return false)
  620. let undefinedVariable; //undefined variable (will return true)
  621. it('_.isUndefined(definedVariable)', () => {
  622. assert.equal(_.isUndefined(definedVariable),
  623. (definedVariable === undefined))
  624. });
  625. it('_(definedVariable).isUndefined()', () => {
  626. assert.equal(_(definedVariable).isUndefined(),
  627. (definedVariable === undefined))
  628. });
  629. it('_.isUndefined(undefinedVariable)', () => {
  630. assert.equal(_.isUndefined(undefinedVariable),
  631. (undefinedVariable === undefined))
  632. });
  633. it('_(undefinedVariable).isUndefined()', () => {
  634. assert.equal(_(undefinedVariable).isUndefined(),
  635. (undefinedVariable === undefined))
  636. });
  637. });
  638. describe('flatten', () => {
  639. it('_.flatten(twoLayerArray)', () => {
  640. const testArray = [1,2[3,4]];
  641. assert.deepEqual(_.flatten(testArray),
  642. testArray.reduce((a,b) => a.concat(b), []))
  643. });
  644. it('_.flatten(multiLayerArray)', () => {
  645. const testArray = [1,2[3,4,[5,6,[7,8]]]];
  646. assert.deepEqual(_.flatten(testArray),
  647. testArray.reduce((a,b) => a.concat(b), []))
  648. });
  649. });
  650. describe('forEach', () => {
  651. it('_.forEach(array)', () => {
  652. const testArray = [1,2,3,4];
  653. let lodashOutput = []
  654. let nativeOutput = []
  655. _.forEach(testArray, element => {
  656. lodashOutput.push(element);
  657. });
  658. testArray.forEach(element => {
  659. nativeOutput.push(element);
  660. });
  661. assert.deepEqual(lodashOutput,nativeOutput);
  662. });
  663. it('_.forEach(object)', () => {
  664. const testObject = {
  665. 'one':1,
  666. 'two':2,
  667. 'three':3,
  668. 'four':4,
  669. }
  670. let lodashOutput = []
  671. let nativeOutput = []
  672. _.forEach(testObject, value => {
  673. lodashOutput.push(value);
  674. });
  675. Object.entries(testObject).forEach(([key,value]) => {
  676. nativeOutput.push(value);
  677. });
  678. assert.deepEqual(lodashOutput,nativeOutput);
  679. });
  680. });
  681. describe('startsWith', () => {
  682. it(`_.startsWith('abc', 'a')`, () => {
  683. assert.deepEqual(
  684. _.startsWith('abc', 'a'),
  685. 'abc'.startsWith('a')
  686. );
  687. });
  688. it(`_.startsWith('abc', 'b')`, () => {
  689. assert.deepEqual(
  690. _.startsWith('abc', 'b'),
  691. 'abc'.startsWith('b')
  692. );
  693. });
  694. it(`_.startsWith('abc', 'b', 1)`, () => {
  695. assert.deepEqual(
  696. _.startsWith('abc', 'b', 1),
  697. 'abc'.startsWith('b', 1)
  698. );
  699. });
  700. });
  701. describe('endsWith', () => {
  702. it(`_.endsWith('abc', 'c')`, () => {
  703. assert.deepEqual(
  704. _.endsWith('abc', 'c'),
  705. 'abc'.endsWith('c')
  706. );
  707. });
  708. it(`_.endsWith('abc', 'b')`, () => {
  709. assert.deepEqual(
  710. _.endsWith('abc', 'b'),
  711. 'abc'.endsWith('b')
  712. );
  713. });
  714. it(`_.endsWith('abc', 'b', 2)`, () => {
  715. assert.deepEqual(
  716. _.endsWith('abc', 'b', 2),
  717. 'abc'.endsWith('b', 2)
  718. );
  719. });
  720. });
  721. describe('throttle', () => {
  722. function throttle(func, timeFrame) {
  723. var lastTime = 0;
  724. return function () {
  725. var now = new Date();
  726. if (now - lastTime >= timeFrame) {
  727. func();
  728. lastTime = now;
  729. }
  730. };
  731. }
  732. it('throttle is not called more than once within timeframe', () => {
  733. let callCount = 0;
  734. const fn = throttle(() => callCount++, 100);
  735. fn();
  736. fn();
  737. fn();
  738. assert.equal(callCount, 1);
  739. });
  740. })
  741. });