moderndash 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ctiignore +3 -0
- package/package.json +41 -0
- package/src/array/chunk.ts +31 -0
- package/src/array/difference.ts +21 -0
- package/src/array/differenceBy.ts +30 -0
- package/src/array/differenceWith.ts +31 -0
- package/src/array/dropRightWhile.ts +28 -0
- package/src/array/dropWhile.ts +24 -0
- package/src/array/index.ts +24 -0
- package/src/array/intersection.ts +20 -0
- package/src/array/intersectionBy.ts +26 -0
- package/src/array/intersectionWith.ts +33 -0
- package/src/array/sample.ts +18 -0
- package/src/array/sampleSize.ts +31 -0
- package/src/array/shuffle.ts +33 -0
- package/src/array/takeRightWhile.ts +33 -0
- package/src/array/takeWhile.ts +33 -0
- package/src/array/union.ts +16 -0
- package/src/array/unionBy.ts +26 -0
- package/src/array/unionWith.ts +31 -0
- package/src/array/uniq.ts +18 -0
- package/src/array/uniqBy.ts +25 -0
- package/src/array/uniqWith.ts +20 -0
- package/src/array/unzip.ts +20 -0
- package/src/array/unzipWith.ts +26 -0
- package/src/array/zip.ts +17 -0
- package/src/array/zipWith.ts +28 -0
- package/src/collection/countBy.ts +38 -0
- package/src/collection/groupBy.ts +33 -0
- package/src/collection/index.ts +3 -0
- package/src/collection/sortBy.ts +15 -0
- package/src/function/after.ts +23 -0
- package/src/function/before.ts +27 -0
- package/src/function/debounce.ts +124 -0
- package/src/function/index.ts +6 -0
- package/src/function/memoize.ts +59 -0
- package/src/function/once.ts +19 -0
- package/src/function/throttle.ts +11 -0
- package/src/helpers/collections.ts +5 -0
- package/src/helpers/shortHands.ts +17 -0
- package/src/helpers/stringModifiers.ts +18 -0
- package/src/helpers/typeofChecks.ts +3 -0
- package/src/index.ts +7 -0
- package/src/lang/index.ts +4 -0
- package/src/lang/isEmpty.ts +23 -0
- package/src/lang/isEqual.ts +54 -0
- package/src/lang/isEqualWith.ts +5 -0
- package/src/lang/isPlainObject.ts +3 -0
- package/src/object/index.ts +1 -0
- package/src/object/pick.ts +22 -0
- package/src/string/camelCase.ts +15 -0
- package/src/string/capitalize.ts +3 -0
- package/src/string/deburr.ts +5 -0
- package/src/string/escape.ts +10 -0
- package/src/string/escapeRegExp.ts +3 -0
- package/src/string/index.ts +11 -0
- package/src/string/kebabCase.ts +10 -0
- package/src/string/pascalCase.ts +10 -0
- package/src/string/snakeCase.ts +13 -0
- package/src/string/startCase.ts +10 -0
- package/src/string/stripSpecialChars.ts +6 -0
- package/src/string/unescape.ts +10 -0
- package/src/types.ts +9 -0
- package/test/.eslintrc.cjs +5 -0
- package/test/array/chunk.test.ts +19 -0
- package/test/array/differenceMethods.test.ts +49 -0
- package/test/array/dropMethods.test.ts +30 -0
- package/test/array/intersectionMethods.test.ts +36 -0
- package/test/array/shuffle.test.ts +17 -0
- package/test/array/takeMethods.test.ts +41 -0
- package/test/array/unionMethods.test.ts +41 -0
- package/test/array/uniqMethods.test.ts +18 -0
- package/test/array/unzipMethods.test.ts +13 -0
- package/test/array/zipMethods.test.ts +48 -0
- package/test/collection/countBy.test.ts +13 -0
- package/test/collection/groupBy.test.ts +35 -0
- package/test/collection/sample.test.ts +17 -0
- package/test/collection/sampleSize.test.ts +33 -0
- package/test/collection/sortBy.test.ts +31 -0
- package/test/function/after.test.ts +19 -0
- package/test/function/before.test.ts +19 -0
- package/test/function/debounce.test.ts +47 -0
- package/test/function/memoize.test.ts +33 -0
- package/test/function/once.test.ts +29 -0
- package/test/function/throttle.test.ts +24 -0
- package/test/lang/isEqualMethods.test.ts +98 -0
- package/test/string/camelCase.test.ts +13 -0
- package/test/string/capitalize.test.ts +17 -0
- package/test/string/deburr.test.ts +16 -0
- package/test/string/escape.test.ts +17 -0
- package/test/string/escapeRegExp.test.ts +18 -0
- package/test/string/kebabCase.test.ts +18 -0
- package/test/string/pascalCase.test.ts +16 -0
- package/test/string/snakeCase.test.ts +23 -0
- package/test/string/startCase.test.ts +14 -0
- package/test/string/stripSpecialChars.test.ts +15 -0
- package/test/string/unescape.test.ts +17 -0
- package/tsconfig.json +112 -0
- package/tsup.config.js +10 -0
- package/vitest.config.ts +27 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './camelCase';
|
|
2
|
+
export * from './capitalize';
|
|
3
|
+
export * from './deburr';
|
|
4
|
+
export * from './escape';
|
|
5
|
+
export * from './escapeRegExp';
|
|
6
|
+
export * from './kebabCase';
|
|
7
|
+
export * from './pascalCase';
|
|
8
|
+
export * from './snakeCase';
|
|
9
|
+
export * from './startCase';
|
|
10
|
+
export * from './stripSpecialChars';
|
|
11
|
+
export * from './unescape';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { splitWords } from '@helpers/stringModifiers';
|
|
2
|
+
|
|
3
|
+
export function kebabCase(str: string): string {
|
|
4
|
+
const words = splitWords(str);
|
|
5
|
+
let kebabCase = '';
|
|
6
|
+
for (const word of words) {
|
|
7
|
+
kebabCase += word.toLowerCase() + '-';
|
|
8
|
+
}
|
|
9
|
+
return kebabCase.slice(0, -1);
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { splitWords } from '@helpers/stringModifiers';
|
|
2
|
+
|
|
3
|
+
export function pascalCase(str: string): string {
|
|
4
|
+
const words = splitWords(str);
|
|
5
|
+
let pascalCase = '';
|
|
6
|
+
for (const word of words) {
|
|
7
|
+
pascalCase += word.charAt(0).toUpperCase() + word.slice(1);
|
|
8
|
+
}
|
|
9
|
+
return pascalCase;
|
|
10
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { splitWords } from '@helpers/stringModifiers';
|
|
2
|
+
|
|
3
|
+
export function snakeCase(str: string): string {
|
|
4
|
+
const words = splitWords(str);
|
|
5
|
+
let snakeCase = '';
|
|
6
|
+
for (const word of words) {
|
|
7
|
+
if (snakeCase.length > 0) {
|
|
8
|
+
snakeCase += '_';
|
|
9
|
+
}
|
|
10
|
+
snakeCase += word.toLowerCase();
|
|
11
|
+
}
|
|
12
|
+
return snakeCase;
|
|
13
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { splitWords } from '@helpers/stringModifiers';
|
|
2
|
+
|
|
3
|
+
export function startCase(str: string): string {
|
|
4
|
+
const words = splitWords(str);
|
|
5
|
+
let startCase = '';
|
|
6
|
+
for (const word of words) {
|
|
7
|
+
startCase += word.charAt(0).toUpperCase() + word.slice(1).toLowerCase() + ' ';
|
|
8
|
+
}
|
|
9
|
+
return startCase.trimEnd();
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function unescapeHTML(html: string): string {
|
|
2
|
+
const entityMap: Record<string, string> = {
|
|
3
|
+
'&': '&',
|
|
4
|
+
'<': '<',
|
|
5
|
+
'>': '>',
|
|
6
|
+
'"': '"',
|
|
7
|
+
''': '\''
|
|
8
|
+
};
|
|
9
|
+
return html.replace(/&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34);/g, (entity: string) => entityMap[entity] || entity);
|
|
10
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type MinimumTwoArrays<T> = [T[], T[], ...T[][]];
|
|
2
|
+
|
|
3
|
+
export type IterateeFunction<T> = (value: T) => unknown;
|
|
4
|
+
export type PropertyShorthand<T> = keyof T;
|
|
5
|
+
|
|
6
|
+
export type RecordKey = string | number | symbol;
|
|
7
|
+
|
|
8
|
+
export type Collection<T> = T[] | Record<RecordKey, T>;
|
|
9
|
+
export type NoUnion<T, U = T> = T extends U ? [U] extends [T] ? T : never : never;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { chunk } from '@array/chunk';
|
|
4
|
+
|
|
5
|
+
describe('Chunk', () => {
|
|
6
|
+
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
7
|
+
|
|
8
|
+
it('should chunk an array', () => {
|
|
9
|
+
expect(chunk(2, array)).toEqual([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('should return the last chunk as remaining elements', () => {
|
|
13
|
+
expect(chunk(3, array)).toEqual([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('should coerce `size` to an integer', () => {
|
|
17
|
+
expect(chunk(array.length / 4, array)).toEqual([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { difference } from '@array/difference';
|
|
4
|
+
import { differenceBy } from '@array/differenceBy';
|
|
5
|
+
import { differenceWith } from '@array/differenceWith';
|
|
6
|
+
|
|
7
|
+
describe('difference', () => {
|
|
8
|
+
it('should return the difference between two arrays', () => {
|
|
9
|
+
const array1 = [1, undefined, null, NaN, 3, 4, 5];
|
|
10
|
+
const array2 = [2, 4, undefined, NaN, null, 8];
|
|
11
|
+
const result = difference(array1, array2);
|
|
12
|
+
expect(result).toEqual([1, NaN, 3, 5]);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
describe('differenceBy', () => {
|
|
17
|
+
it('should return match based on input function', () => {
|
|
18
|
+
expect(differenceBy(Math.floor, [2.1, 1.2], [2.3, 3.4], [99])).toEqual([1.2]);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
describe('differenceWith', () => {
|
|
24
|
+
it('should return an array containing the elements that are present in the first array but not in the other arrays', () => {
|
|
25
|
+
const array1 = [1, 2, 3, 4];
|
|
26
|
+
const array2 = [2, 3, 5, 6];
|
|
27
|
+
const array3 = [3, 4, 5, 6];
|
|
28
|
+
|
|
29
|
+
const difference = differenceWith((a, b) => a === b, array1, array2, array3);
|
|
30
|
+
expect(difference).toEqual([1]);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should return an empty array if no elements are present in the first array but not in the other arrays', () => {
|
|
34
|
+
const array1 = [1, 2, 3, 4];
|
|
35
|
+
const array2 = [1, 2];
|
|
36
|
+
const array3 = [3, 4];
|
|
37
|
+
|
|
38
|
+
const difference = differenceWith((a, b) => a === b, array1, array2, array3);
|
|
39
|
+
expect(difference).toEqual([]);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should return the first array if no elements are present in the other arrays', () => {
|
|
43
|
+
const array1 = [1, 2, 3, 4];
|
|
44
|
+
const array2: number[] = [];
|
|
45
|
+
|
|
46
|
+
const difference = differenceWith((a, b) => a === b, array1, array2);
|
|
47
|
+
expect(difference).toEqual(array1);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { it, expect, describe } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { dropRightWhile } from '@array/dropRightWhile';
|
|
4
|
+
import { dropWhile } from '@array/dropWhile';
|
|
5
|
+
|
|
6
|
+
const array = [2, 4, 5, 6];
|
|
7
|
+
|
|
8
|
+
describe('dropWhile', () => {
|
|
9
|
+
it('removes elements from the start of the array until the predicate returns false', () => {
|
|
10
|
+
expect(dropWhile(x => x % 2 === 0, array)).toEqual([5, 6]);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('returns an empty array if the predicate always returns true', () => {
|
|
14
|
+
expect(dropWhile(() => true, array)).toEqual([]);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('returns the original array if the predicate always returns false', () => {
|
|
18
|
+
expect(dropWhile(() => false, array)).toEqual(array);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('returns an empty array if the input array is empty', () => {
|
|
22
|
+
expect(dropWhile(() => true, [])).toEqual([]);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe('dropRightWhile', () => {
|
|
27
|
+
it('should drop elements while `predicate` returns truthy', () => {
|
|
28
|
+
expect(dropRightWhile(n => n > 4, array)).toEqual([2, 4]);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { expect, it, describe } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { intersection } from '@array/intersection';
|
|
4
|
+
import { intersectionBy } from '@array/intersectionBy';
|
|
5
|
+
import { intersectionWith } from '@array/intersectionWith';
|
|
6
|
+
|
|
7
|
+
describe('intersection', () => {
|
|
8
|
+
it('returns the correct intersections', () => {
|
|
9
|
+
const arr1 = [1, 2, 3, 4, 5];
|
|
10
|
+
const arr2 = [3, 4, 5, 6, 7];
|
|
11
|
+
|
|
12
|
+
const result = intersection(arr1, arr2);
|
|
13
|
+
expect(result).toEqual([3, 4, 5]);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
describe('intersectionBy', () => {
|
|
18
|
+
it('returns the correct intersections', () => {
|
|
19
|
+
const arr1 = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }];
|
|
20
|
+
const arr2 = [{ id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }, { id: 7 }];
|
|
21
|
+
|
|
22
|
+
const result = intersectionBy(value => value.id, arr1, arr2);
|
|
23
|
+
expect(result).toEqual([{ id: 3 }, { id: 4 }, { id: 5 }]);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
describe('intersectionWith', () => {
|
|
29
|
+
it('returns the correct intersections', () => {
|
|
30
|
+
const arr1 = [1, 2, 3, 4, 5];
|
|
31
|
+
const arr2 = [3, 4, 5, 6, 7];
|
|
32
|
+
|
|
33
|
+
const result = intersectionWith((a, b) => a % 2 === 0 && a === b, arr1, arr2);
|
|
34
|
+
expect(result).toEqual([4]);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { test, describe, expect } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { shuffle } from '@array/shuffle';
|
|
4
|
+
|
|
5
|
+
describe('shuffle', () => {
|
|
6
|
+
test('should shuffle the elements of the array', () => {
|
|
7
|
+
const array = [1, 2, 3, 4, 5];
|
|
8
|
+
const shuffledArray = shuffle(array);
|
|
9
|
+
expect(shuffledArray).not.toEqual(array);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test('should not modify the original array', () => {
|
|
13
|
+
const array = [1, 2, 3, 4, 5];
|
|
14
|
+
shuffle(array);
|
|
15
|
+
expect(array).toEqual([1, 2, 3, 4, 5]);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { it, expect, describe } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { takeRightWhile } from '@array/takeRightWhile';
|
|
4
|
+
import { takeWhile } from '@array/takeWhile';
|
|
5
|
+
|
|
6
|
+
describe('takeWhile', () => {
|
|
7
|
+
const numbers = [2, 4, 5, 6, 7, 8, 9, 10];
|
|
8
|
+
it('should return the elements from the input array until the predicate returns false', () => {
|
|
9
|
+
const evenNumbers = takeWhile((n) => n % 2 === 0, numbers);
|
|
10
|
+
expect(evenNumbers).toEqual([2, 4]);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('should return an empty array if the predicate always returns false', () => {
|
|
14
|
+
const evenNumbers = takeWhile((n) => n > 10, numbers);
|
|
15
|
+
expect(evenNumbers).toEqual([]);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should deal with different types', () => {
|
|
19
|
+
const mixed = [1, 2, 3, '4', 5, '6', 7, '8', 9, '10', [], {}, undefined];
|
|
20
|
+
const evenNumbers = takeWhile((n) => typeof n === 'number', mixed);
|
|
21
|
+
expect(evenNumbers).toEqual([1, 2, 3]);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('takeRightWhile', () => {
|
|
26
|
+
const numbers = [2, 3, 5, 7, 11, 14, 17, 19, 23, 29];
|
|
27
|
+
it('should return a new array with the last elements that satisfy the condition specified by the predicate function', () => {
|
|
28
|
+
const result = takeRightWhile(n => n % 2 === 1, numbers);
|
|
29
|
+
expect(result).toEqual([17, 19, 23, 29]);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should return an empty array if no elements satisfy the condition', () => {
|
|
33
|
+
const result = takeRightWhile((n: number) => n % 100 === 1, numbers);
|
|
34
|
+
expect(result).toEqual([]);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should return the original array if all elements satisfy the condition', () => {
|
|
38
|
+
const result = takeRightWhile(() => true, numbers);
|
|
39
|
+
expect(result).toEqual(numbers);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { it, expect, describe } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { union } from '@array/union';
|
|
4
|
+
import { unionBy } from '@array/unionBy';
|
|
5
|
+
import { unionWith } from '@array/unionWith';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
describe('union', () => {
|
|
9
|
+
const array1 = [1, 2, 3];
|
|
10
|
+
const array2 = [2, 3, 4];
|
|
11
|
+
const array3 = [3, 4, [5]];
|
|
12
|
+
|
|
13
|
+
it('should return a new array with the unique elements from all of the provided arrays', () => {
|
|
14
|
+
const result = union(array1, array2, array3);
|
|
15
|
+
expect(result).toEqual([1, 2, 3, 4, [5]]);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
describe('unionWith', () => {
|
|
21
|
+
it('returns a new array containing the unique values from the input arrays', () => {
|
|
22
|
+
const result = unionWith((a, b) => a === b, [1, 2, 3], [2, 3, 4], [3, 4, 5]);
|
|
23
|
+
expect(result).toEqual([1, 2, 3, 4, 5]);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('uses the comparator function to determine uniqueness', () => {
|
|
27
|
+
const result = unionWith((a, b) => a.id === b.id, [{ id: 1 }, { id: 2 }], [{ id: 2 }, { id: 3 }]);
|
|
28
|
+
expect(result).toEqual([{ id: 1 }, { id: 2 }, { id: 3 }]);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe('unionBy', () => {
|
|
33
|
+
it('should return the union of the arrays, using the iteratee to determine uniqueness', () => {
|
|
34
|
+
const objects = [{ x: 1 }, { x: 2 }, { x: 3 }];
|
|
35
|
+
const moreObjects = [{ x: 2 }, { x: 3 }, { x: 4 }];
|
|
36
|
+
expect(unionBy(o => o.x, objects, moreObjects)).toEqual([{ x: 1 }, { x: 2 }, { x: 3 }, { x: 4 }]);
|
|
37
|
+
|
|
38
|
+
// The `property` iteratee shorthand.
|
|
39
|
+
expect(unionBy('x', objects, moreObjects)).toEqual([{ x: 1 }, { x: 2 }, { x: 3 }, { x: 4 }]);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { it, expect, describe } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { uniq } from '@array/uniq';
|
|
4
|
+
|
|
5
|
+
describe('uniq', () => {
|
|
6
|
+
it('should return an array with only unique values', () => {
|
|
7
|
+
const input = [1, 2, 3, 3, 4, 5, 5, 6];
|
|
8
|
+
const expectedOutput = [1, 2, 3, 4, 5, 6];
|
|
9
|
+
expect(uniq(input)).toEqual(expectedOutput);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('should handle objects and arrays correctly', () => {
|
|
13
|
+
const input = [{ a: 1 }, { a: 2 }, { a: 1 }, [1, 2], [1, 2], [1, 2, 3]
|
|
14
|
+
];
|
|
15
|
+
const expectedOutput = [{ a: 1 }, { a: 2 }, [1, 2], [1, 2, 3]];
|
|
16
|
+
expect(uniq(input)).toEqual(expectedOutput);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { describe, test, expect } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { unzipWith } from '@array/unzipWith';
|
|
4
|
+
|
|
5
|
+
describe('unzipWith', () => {
|
|
6
|
+
test('should unzip an arrays with a function', () => {
|
|
7
|
+
const array: [number, string, boolean?][] = [[1, 'a', true], [2, 'b', false], [3, 'c']];
|
|
8
|
+
const iteratee = (x: number, y: string, z?: boolean) => x.toString() + y + (z ? '!' : '');
|
|
9
|
+
|
|
10
|
+
const result = unzipWith(iteratee, array);
|
|
11
|
+
expect(result).toEqual(['1a!', '2b', '3c']);
|
|
12
|
+
});
|
|
13
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { describe, test, expect } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { zipWith } from '@array/zipWith';
|
|
4
|
+
|
|
5
|
+
describe('zipWith function', () => {
|
|
6
|
+
test('returns the expected result for three arrays of the same length', () => {
|
|
7
|
+
const array1 = [1, 2, 3];
|
|
8
|
+
const array2 = [10, 20, 30];
|
|
9
|
+
const array3 = [100, 200, 300];
|
|
10
|
+
|
|
11
|
+
const result = zipWith((a, b, c) => a + b + c, array1, array2, array3);
|
|
12
|
+
|
|
13
|
+
expect(result).toEqual([111, 222, 333]);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('returns the expected result for arrays of different lengths', () => {
|
|
17
|
+
const array1 = [1, 2, 3, 4];
|
|
18
|
+
const array2 = [10, 20, 30];
|
|
19
|
+
const array3 = [100, 200];
|
|
20
|
+
|
|
21
|
+
const result = zipWith((a, b, c) => a + b + c, array1, array2, array3);
|
|
22
|
+
|
|
23
|
+
expect(result).toEqual([111, 222]);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('returns an empty array for empty input arrays', () => {
|
|
27
|
+
const array1: number[] = [];
|
|
28
|
+
const array2: number[] = [];
|
|
29
|
+
const array3: number[] = [];
|
|
30
|
+
|
|
31
|
+
const result = zipWith((a, b, c) => a + b + c, array1, array2, array3);
|
|
32
|
+
|
|
33
|
+
expect(result).toEqual([]);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('works with arrays of different types', () => {
|
|
37
|
+
const array1 = ['a', 'b', 'c'];
|
|
38
|
+
const array2 = [1, 2, 3];
|
|
39
|
+
const array3 = [true, false, true];
|
|
40
|
+
// Todo fix type error
|
|
41
|
+
|
|
42
|
+
const iteratee = (a: string, b: number, c: boolean) => a + b.toString() + c.toString();
|
|
43
|
+
//
|
|
44
|
+
const result = zipWith(iteratee, array1, array2, array3);
|
|
45
|
+
|
|
46
|
+
expect(result).toEqual(['a1true', 'b2false', 'c3true']);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { describe, test, expect } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { countBy } from '@collection/countBy';
|
|
4
|
+
import { sample } from '@array/sample';
|
|
5
|
+
|
|
6
|
+
describe('countBy function', () => {
|
|
7
|
+
test('countBy', () => {
|
|
8
|
+
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
9
|
+
const even = (value: number) => (value % 2 === 0).toString();
|
|
10
|
+
const result = countBy(even, array);
|
|
11
|
+
expect(result).toEqual({ 'true': 5, 'false': 5 });
|
|
12
|
+
});
|
|
13
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { describe, test, expect } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { groupBy } from '@collection/groupBy';
|
|
4
|
+
|
|
5
|
+
describe('groupBy', () => {
|
|
6
|
+
test('groups elements by evenness', () => {
|
|
7
|
+
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
8
|
+
const even = (value: number) => (value % 2 === 0).toString();
|
|
9
|
+
const result = groupBy(even, array);
|
|
10
|
+
expect(result).toEqual({ 'true': [2, 4, 6, 8, 10], 'false': [1, 3, 5, 7, 9] });
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test('should group an array by a property', () => {
|
|
14
|
+
const array = [
|
|
15
|
+
{ name: 'Alice', age: 30 },
|
|
16
|
+
{ name: 'Bob', age: 35 },
|
|
17
|
+
{ name: 'Charlie', age: 30 },
|
|
18
|
+
{ name: 'Dave', age: 40 },
|
|
19
|
+
{ name: 'Eve', age: 35 }
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
const result = groupBy(element => element.age, array);
|
|
23
|
+
|
|
24
|
+
expect(result).toEqual({
|
|
25
|
+
30: [{ name: 'Alice', age: 30 }, { name: 'Charlie', age: 30 }],
|
|
26
|
+
35: [{ name: 'Bob', age: 35 }, { name: 'Eve', age: 35 }],
|
|
27
|
+
40: [{ name: 'Dave', age: 40 }]
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('should work with an object for `collection`', function () {
|
|
32
|
+
const actual = groupBy(Math.floor, { 'a': 6.1, 'b': 4.2, 'c': 6.3 } );
|
|
33
|
+
expect(actual).toEqual({ '4': [4.2], '6': [6.1, 6.3] });
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { test, describe, expect } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { sample } from '@array/sample';
|
|
4
|
+
|
|
5
|
+
describe('sample', () => {
|
|
6
|
+
test('sample function returns a random value from an array', () => {
|
|
7
|
+
const collection = [1, 2, 3, 4, 5];
|
|
8
|
+
const result = sample(collection);
|
|
9
|
+
expect(collection).toContain(result);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test('sample function returns undefined for an empty collection', () => {
|
|
13
|
+
const collection = [] as unknown[];
|
|
14
|
+
const result = sample(collection);
|
|
15
|
+
expect(result).toBeUndefined();
|
|
16
|
+
});
|
|
17
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { sampleSize } from '@array/sampleSize';
|
|
4
|
+
|
|
5
|
+
describe('sampleSize', () => {
|
|
6
|
+
test('should return an array of the specified size', () => {
|
|
7
|
+
const array = [1, 2, 3, 4, 5];
|
|
8
|
+
const size = 3;
|
|
9
|
+
const result = sampleSize(size, array);
|
|
10
|
+
expect(result).toHaveLength(size);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test('should return an empty array if size is 0 or less', () => {
|
|
14
|
+
const array = [1, 2, 3, 4, 5];
|
|
15
|
+
const size = 0;
|
|
16
|
+
const result = sampleSize(size, array);
|
|
17
|
+
expect(result).toHaveLength(0);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('should return an empty array if the input array is empty', () => {
|
|
21
|
+
const array: number[] = [];
|
|
22
|
+
const size = 3;
|
|
23
|
+
const result = sampleSize(size, array);
|
|
24
|
+
expect(result).toHaveLength(0);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('should return a random subset of the input array', () => {
|
|
28
|
+
const array = [1, 2, 3, 4, 5];
|
|
29
|
+
const size = 3;
|
|
30
|
+
const result = sampleSize(size, array);
|
|
31
|
+
expect(expect.arrayContaining(result)).toEqual(array);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { test, describe, expect } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { sortBy } from '@collection/sortBy';
|
|
4
|
+
|
|
5
|
+
describe('sortBy', () => {
|
|
6
|
+
test('should sort the array in ascending order based on the iteratee function', () => {
|
|
7
|
+
const numbers = [3, 1, 2];
|
|
8
|
+
const sortedNumbers = sortBy(number => number, numbers);
|
|
9
|
+
expect(sortedNumbers).toEqual([1, 2, 3]);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test('should return the original array if it is already sorted', () => {
|
|
13
|
+
const numbers = [1, 2, 3];
|
|
14
|
+
const sortedNumbers = sortBy(number => number, numbers);
|
|
15
|
+
expect(sortedNumbers).toEqual(numbers);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('should work with arrays of objects', () => {
|
|
19
|
+
const users = [
|
|
20
|
+
{ name: 'Alice', age: 30 },
|
|
21
|
+
{ name: 'Bob', age: 25 },
|
|
22
|
+
{ name: 'Eve', age: 35 }
|
|
23
|
+
];
|
|
24
|
+
const sortedUsers = sortBy(user => user.age, users);
|
|
25
|
+
expect(sortedUsers).toEqual([
|
|
26
|
+
{ name: 'Bob', age: 25 },
|
|
27
|
+
{ name: 'Alice', age: 30 },
|
|
28
|
+
{ name: 'Eve', age: 35 }
|
|
29
|
+
]);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { describe, test, vi, expect } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { after } from '@function/after';
|
|
4
|
+
|
|
5
|
+
describe('after', () => {
|
|
6
|
+
test('after function works correctly', () => {
|
|
7
|
+
const testFn = vi.fn();
|
|
8
|
+
const afterFn = after(3, testFn);
|
|
9
|
+
|
|
10
|
+
afterFn(1);
|
|
11
|
+
afterFn(1);
|
|
12
|
+
expect(testFn).toHaveBeenCalledTimes(0);
|
|
13
|
+
|
|
14
|
+
afterFn(1);
|
|
15
|
+
afterFn(1);
|
|
16
|
+
|
|
17
|
+
expect(testFn).toHaveBeenCalledTimes(2);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { describe, expect, test, vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { before } from '@function/before';
|
|
4
|
+
|
|
5
|
+
describe('before', () => {
|
|
6
|
+
test('only calls 3 times', () => {
|
|
7
|
+
const testFn = vi.fn();
|
|
8
|
+
const beforeFn = before(3, testFn);
|
|
9
|
+
|
|
10
|
+
beforeFn();
|
|
11
|
+
beforeFn();
|
|
12
|
+
expect(testFn).toHaveBeenCalledTimes(2);
|
|
13
|
+
|
|
14
|
+
beforeFn();
|
|
15
|
+
beforeFn();
|
|
16
|
+
|
|
17
|
+
expect(testFn).toHaveBeenCalledTimes(3);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { afterEach, beforeAll, describe, expect, test, vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { debounce } from '@function/debounce';
|
|
4
|
+
|
|
5
|
+
describe('debounce', () => {
|
|
6
|
+
const testFn = vi.fn((x: number) => x * 2);
|
|
7
|
+
|
|
8
|
+
beforeAll(() => {
|
|
9
|
+
vi.useFakeTimers();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
testFn.mockClear();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('only calls the function once', () => {
|
|
17
|
+
const debounced = debounce(testFn, 100);
|
|
18
|
+
|
|
19
|
+
debounced(1);
|
|
20
|
+
debounced(1);
|
|
21
|
+
debounced(1);
|
|
22
|
+
|
|
23
|
+
expect(testFn).not.toHaveBeenCalled();
|
|
24
|
+
|
|
25
|
+
vi.advanceTimersByTime(99);
|
|
26
|
+
expect(testFn).not.toHaveBeenCalled();
|
|
27
|
+
|
|
28
|
+
vi.advanceTimersByTime(1);
|
|
29
|
+
expect(testFn).toHaveBeenCalledTimes(1);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test('calls the function again after the wait period', () => {
|
|
33
|
+
const debounced = debounce(testFn, 100);
|
|
34
|
+
|
|
35
|
+
debounced(1);
|
|
36
|
+
vi.advanceTimersByTime(50);
|
|
37
|
+
debounced(1);
|
|
38
|
+
vi.advanceTimersByTime(50);
|
|
39
|
+
debounced(1);
|
|
40
|
+
|
|
41
|
+
vi.advanceTimersByTime(50);
|
|
42
|
+
expect(testFn).not.toHaveBeenCalled();
|
|
43
|
+
|
|
44
|
+
vi.advanceTimersByTime(50);
|
|
45
|
+
expect(testFn).toHaveBeenCalledTimes(1);
|
|
46
|
+
});
|
|
47
|
+
});
|