data-structure-typed 2.2.7 → 2.3.0
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/.github/workflows/ci.yml +9 -0
- package/CHANGELOG.md +1 -1
- package/README.md +14 -3
- package/README_CN.md +119 -275
- package/benchmark/report.html +1 -1
- package/benchmark/report.json +20 -324
- package/dist/cjs/index.cjs +689 -182
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +693 -185
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +689 -182
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +693 -185
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/leetcode/avl-tree-counter.mjs +2957 -0
- package/dist/leetcode/avl-tree-multi-map.mjs +2889 -0
- package/dist/leetcode/avl-tree.mjs +2720 -0
- package/dist/leetcode/binary-tree.mjs +1594 -0
- package/dist/leetcode/bst.mjs +2398 -0
- package/dist/leetcode/deque.mjs +683 -0
- package/dist/leetcode/directed-graph.mjs +1733 -0
- package/dist/leetcode/doubly-linked-list.mjs +709 -0
- package/dist/leetcode/hash-map.mjs +493 -0
- package/dist/leetcode/heap.mjs +542 -0
- package/dist/leetcode/max-heap.mjs +375 -0
- package/dist/leetcode/max-priority-queue.mjs +383 -0
- package/dist/leetcode/min-heap.mjs +363 -0
- package/dist/leetcode/min-priority-queue.mjs +371 -0
- package/dist/leetcode/priority-queue.mjs +363 -0
- package/dist/leetcode/queue.mjs +943 -0
- package/dist/leetcode/red-black-tree.mjs +2765 -0
- package/dist/leetcode/singly-linked-list.mjs +754 -0
- package/dist/leetcode/stack.mjs +217 -0
- package/dist/leetcode/tree-counter.mjs +3039 -0
- package/dist/leetcode/tree-multi-map.mjs +2913 -0
- package/dist/leetcode/trie.mjs +413 -0
- package/dist/leetcode/undirected-graph.mjs +1650 -0
- package/dist/types/data-structures/base/linear-base.d.ts +6 -6
- package/dist/types/data-structures/binary-tree/avl-tree-counter.d.ts +1 -1
- package/dist/types/data-structures/binary-tree/avl-tree-multi-map.d.ts +2 -2
- package/dist/types/data-structures/binary-tree/avl-tree.d.ts +10 -10
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +25 -27
- package/dist/types/data-structures/binary-tree/bst.d.ts +13 -12
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +151 -21
- package/dist/types/data-structures/binary-tree/tree-counter.d.ts +4 -4
- package/dist/types/data-structures/binary-tree/tree-multi-map.d.ts +2 -2
- package/dist/types/interfaces/binary-tree.d.ts +1 -1
- package/dist/umd/data-structure-typed.js +689 -181
- package/dist/umd/data-structure-typed.js.map +1 -1
- package/dist/umd/data-structure-typed.min.js +3 -3
- package/dist/umd/data-structure-typed.min.js.map +1 -1
- package/package.json +50 -172
- package/src/data-structures/base/linear-base.ts +2 -12
- package/src/data-structures/binary-tree/avl-tree-counter.ts +6 -6
- package/src/data-structures/binary-tree/avl-tree-multi-map.ts +13 -13
- package/src/data-structures/binary-tree/avl-tree.ts +15 -15
- package/src/data-structures/binary-tree/binary-tree.ts +57 -60
- package/src/data-structures/binary-tree/bst.ts +100 -26
- package/src/data-structures/binary-tree/red-black-tree.ts +586 -76
- package/src/data-structures/binary-tree/tree-counter.ts +25 -13
- package/src/data-structures/binary-tree/tree-multi-map.ts +13 -13
- package/src/data-structures/queue/deque.ts +10 -0
- package/src/interfaces/binary-tree.ts +1 -1
- package/test/performance/data-structures/binary-tree/red-black-tree.test.ts +1 -2
- package/test/unit/data-structures/base/iterable-element-base.coverage.test.ts +106 -0
- package/test/unit/data-structures/base/iterable-element-base.more-branches.coverage.test.ts +61 -0
- package/test/unit/data-structures/base/linear-base.array.coverage.test.ts +168 -0
- package/test/unit/data-structures/base/linear-base.concat-else.coverage.test.ts +82 -0
- package/test/unit/data-structures/base/linear-base.coverage.test.ts +72 -0
- package/test/unit/data-structures/base/linear-base.more-branches.coverage.test.ts +417 -0
- package/test/unit/data-structures/binary-tree/avl-tree-counter.more-branches-3.coverage.test.ts +146 -0
- package/test/unit/data-structures/binary-tree/avl-tree-counter.more-branches.coverage.test.ts +93 -0
- package/test/unit/data-structures/binary-tree/avl-tree-counter.test.ts +30 -30
- package/test/unit/data-structures/binary-tree/avl-tree-multi-map.coverage.test.ts +108 -0
- package/test/unit/data-structures/binary-tree/avl-tree-multi-map.more-branches-2.coverage.test.ts +85 -0
- package/test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts +46 -46
- package/test/unit/data-structures/binary-tree/avl-tree-node.familyPosition-root-left.coverage.test.ts +17 -0
- package/test/unit/data-structures/binary-tree/avl-tree.more-branches-2.coverage.test.ts +99 -0
- package/test/unit/data-structures/binary-tree/avl-tree.test.ts +43 -43
- package/test/unit/data-structures/binary-tree/binary-indexed-tree.more-branches.coverage.test.ts +18 -0
- package/test/unit/data-structures/binary-tree/binary-tree.more-branches.coverage.test.ts +56 -0
- package/test/unit/data-structures/binary-tree/binary-tree.remaining-branches.coverage.test.ts +229 -0
- package/test/unit/data-structures/binary-tree/binary-tree.test.ts +151 -151
- package/test/unit/data-structures/binary-tree/bst.bound-by-predicate.coverage.test.ts +33 -0
- package/test/unit/data-structures/binary-tree/bst.coverage.test.ts +94 -0
- package/test/unit/data-structures/binary-tree/bst.deletebykey.coverage.test.ts +70 -0
- package/test/unit/data-structures/binary-tree/bst.deletewhere.coverage.test.ts +37 -0
- package/test/unit/data-structures/binary-tree/bst.floor-lower-predicate.coverage.test.ts +29 -0
- package/test/unit/data-structures/binary-tree/bst.floor-setmany.coverage.test.ts +72 -0
- package/test/unit/data-structures/binary-tree/bst.getnode.range-ensure.coverage.test.ts +22 -0
- package/test/unit/data-structures/binary-tree/bst.misc-branches.coverage.test.ts +100 -0
- package/test/unit/data-structures/binary-tree/bst.more-branches-2.coverage.test.ts +133 -0
- package/test/unit/data-structures/binary-tree/bst.more-branches-3.coverage.test.ts +45 -0
- package/test/unit/data-structures/binary-tree/bst.more-branches-4.coverage.test.ts +36 -0
- package/test/unit/data-structures/binary-tree/bst.more-branches-5.coverage.test.ts +40 -0
- package/test/unit/data-structures/binary-tree/bst.more.coverage.test.ts +39 -0
- package/test/unit/data-structures/binary-tree/bst.node-family.coverage.test.ts +29 -0
- package/test/unit/data-structures/binary-tree/bst.range-pruning.coverage.test.ts +43 -0
- package/test/unit/data-structures/binary-tree/bst.search-fastpath.coverage.test.ts +30 -0
- package/test/unit/data-structures/binary-tree/bst.test.ts +124 -154
- package/test/unit/data-structures/binary-tree/overall.test.ts +20 -20
- package/test/unit/data-structures/binary-tree/red-black-tree.boundary-corruption-repair.coverage.test.ts +66 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.boundary-max-update.coverage.test.ts +18 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.boundary-null.coverage.test.ts +53 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.boundary-stale-cache.coverage.test.ts +25 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.boundary-update.coverage.test.ts +23 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.cache-delete.coverage.test.ts +49 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.cache-edge.coverage.test.ts +37 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.cache-stale-insert.coverage.test.ts +39 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.coverage.test.ts +334 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.delete-fixup.coverage.test.ts +68 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.delete-successor.coverage.test.ts +75 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.factories.coverage.test.ts +26 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint-cache-compare-update.coverage.test.ts +74 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint-cache-no-update.coverage.test.ts +44 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint-cache-nullish.coverage.test.ts +61 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint-mapmode-defined.coverage.test.ts +35 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint-mapmode-undefined.coverage.test.ts +43 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint-more.coverage.test.ts +99 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.hint.coverage.test.ts +60 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.insert-cache-nullish.coverage.test.ts +29 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.insert-header-parent-nullish.coverage.test.ts +17 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.internal-walk.coverage.test.ts +57 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.minmax-cache.test.ts +65 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.misc-inputs.coverage.test.ts +17 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.more-branches-2.coverage.test.ts +121 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.more-branches-3.coverage.test.ts +55 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.more-branches-4.coverage.test.ts +44 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.predsucc.coverage.test.ts +40 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.remaining-branches.coverage.test.ts +123 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.set-inputs.coverage.test.ts +64 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.setkvnode-parent-cache.coverage.test.ts +79 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.setkvnode-remaining.coverage.test.ts +44 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.setkvnode-uncovered.coverage.test.ts +74 -0
- package/test/unit/data-structures/binary-tree/red-black-tree.test.ts +141 -141
- package/test/unit/data-structures/binary-tree/red-black-tree.update-branches.coverage.test.ts +30 -0
- package/test/unit/data-structures/binary-tree/segment-tree.more-branches.coverage.test.ts +31 -0
- package/test/unit/data-structures/binary-tree/tree-counter.coverage.test.ts +115 -0
- package/test/unit/data-structures/binary-tree/tree-counter.more-branches.coverage.test.ts +244 -0
- package/test/unit/data-structures/binary-tree/tree-counter.test.ts +41 -39
- package/test/unit/data-structures/binary-tree/tree-multi-map.coverage.test.ts +104 -0
- package/test/unit/data-structures/binary-tree/tree-multi-map.more-branches-2.coverage.test.ts +59 -0
- package/test/unit/data-structures/binary-tree/tree-multi-map.test.ts +145 -145
- package/test/unit/data-structures/graph/abstract-graph.more-branches-2.coverage.test.ts +40 -0
- package/test/unit/data-structures/graph/abstract-graph.more-branches-3.coverage.test.ts +65 -0
- package/test/unit/data-structures/graph/abstract-graph.more-branches-4.coverage.test.ts +98 -0
- package/test/unit/data-structures/graph/abstract-graph.more-branches-5.coverage.test.ts +51 -0
- package/test/unit/data-structures/graph/abstract-graph.more-branches.coverage.test.ts +62 -0
- package/test/unit/data-structures/graph/directed-graph.more-branches-2.coverage.test.ts +38 -0
- package/test/unit/data-structures/graph/directed-graph.more-branches-3.coverage.test.ts +25 -0
- package/test/unit/data-structures/graph/directed-graph.more-branches.coverage.test.ts +82 -0
- package/test/unit/data-structures/graph/map-graph.more-branches.coverage.test.ts +22 -0
- package/test/unit/data-structures/graph/undirected-graph.more-branches-2.coverage.test.ts +35 -0
- package/test/unit/data-structures/graph/undirected-graph.more-branches.coverage.test.ts +87 -0
- package/test/unit/data-structures/hash/hash-map.more-branches.coverage.test.ts +64 -0
- package/test/unit/data-structures/hash/hash-map.toEntryFn-branch.coverage.test.ts +9 -0
- package/test/unit/data-structures/heap/heap.misc-branches.coverage.test.ts +110 -0
- package/test/unit/data-structures/heap/heap.remaining-branches.coverage.test.ts +22 -0
- package/test/unit/data-structures/heap/max-heap.coverage.test.ts +29 -0
- package/test/unit/data-structures/linked-list/doubly-linked-list.more-branches.coverage.test.ts +72 -0
- package/test/unit/data-structures/linked-list/linked-list.unshiftMany-else.coverage.test.ts +15 -0
- package/test/unit/data-structures/linked-list/singly-linked-list.coverage.test.ts +221 -0
- package/test/unit/data-structures/linked-list/singly-linked-list.more-branches.coverage.test.ts +86 -0
- package/test/unit/data-structures/linked-list/skip-linked-list.more-branches.coverage.test.ts +31 -0
- package/test/unit/data-structures/matrix/matrix.more-branches.coverage.test.ts +81 -0
- package/test/unit/data-structures/matrix/matrix.pivotElement-nullish.coverage.test.ts +28 -0
- package/test/unit/data-structures/priority-queue/max-priority-queue.more-branches.coverage.test.ts +10 -0
- package/test/unit/data-structures/priority-queue/priority-queue.coverage.test.ts +21 -0
- package/test/unit/data-structures/queue/deque.coverage.test.ts +173 -0
- package/test/unit/data-structures/queue/deque.more-branches-2.coverage.test.ts +39 -0
- package/test/unit/data-structures/queue/deque.more-branches-3.coverage.test.ts +9 -0
- package/test/unit/data-structures/queue/deque.more-branches.coverage.test.ts +95 -0
- package/test/unit/data-structures/queue/queue.coverage.test.ts +138 -0
- package/test/unit/data-structures/queue/queue.more-branches-2.coverage.test.ts +27 -0
- package/test/unit/data-structures/stack/stack.coverage.test.ts +112 -0
- package/test/unit/data-structures/tree/tree.more-branches.coverage.test.ts +9 -0
- package/test/unit/data-structures/trie/trie.more-branches-2.coverage.test.ts +51 -0
- package/test/utils/patch.ts +33 -0
- package/tsup.config.js +50 -21
- package/tsup.umd.config.js +29 -0
- package/tsup.node.config.js +0 -83
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Matrix } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('Matrix inverse pivotElement ?? 1 remaining branch coverage', () => {
|
|
4
|
+
it('inverse() uses pivotElement fallback 1 when get(i,i) is nullish', () => {
|
|
5
|
+
const origGet = Matrix.prototype.get;
|
|
6
|
+
try {
|
|
7
|
+
Matrix.prototype.get = function (row: number, col: number): any {
|
|
8
|
+
if (row === 0 && col === 0) return undefined;
|
|
9
|
+
return origGet.call(this, row, col);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const m = new Matrix([
|
|
13
|
+
[1, 0],
|
|
14
|
+
[0, 1]
|
|
15
|
+
]);
|
|
16
|
+
|
|
17
|
+
const inv = m.inverse();
|
|
18
|
+
|
|
19
|
+
// Restore before asserting so inv.get is not affected.
|
|
20
|
+
Matrix.prototype.get = origGet;
|
|
21
|
+
|
|
22
|
+
expect(inv?.get(0, 0)).toBe(1);
|
|
23
|
+
expect(inv?.get(1, 1)).toBe(1);
|
|
24
|
+
} finally {
|
|
25
|
+
Matrix.prototype.get = origGet;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
});
|
package/test/unit/data-structures/priority-queue/max-priority-queue.more-branches.coverage.test.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { MaxPriorityQueue } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('MaxPriorityQueue remaining branch coverage', () => {
|
|
4
|
+
it('default comparator throws when comparing object elements', () => {
|
|
5
|
+
const pq = new MaxPriorityQueue<any>();
|
|
6
|
+
// call comparator directly to deterministically hit the throw branch
|
|
7
|
+
const cmp = (pq as any).comparator as (a: any, b: any) => number;
|
|
8
|
+
expect(() => cmp({ a: 1 }, { b: 2 })).toThrow(TypeError);
|
|
9
|
+
});
|
|
10
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { PriorityQueue } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Coverage-focused test for PriorityQueue thin wrapper.
|
|
5
|
+
* Keep existing @example tests intact.
|
|
6
|
+
*/
|
|
7
|
+
describe('PriorityQueue coverage', () => {
|
|
8
|
+
it('constructs and supports basic add/poll via Heap API', () => {
|
|
9
|
+
const pq = new PriorityQueue<number>();
|
|
10
|
+
pq.add(3);
|
|
11
|
+
pq.add(1);
|
|
12
|
+
pq.add(2);
|
|
13
|
+
|
|
14
|
+
// Default PriorityQueue here behaves as a min-heap.
|
|
15
|
+
expect(pq.peek()).toBe(1);
|
|
16
|
+
expect(pq.poll()).toBe(1);
|
|
17
|
+
expect(pq.poll()).toBe(2);
|
|
18
|
+
expect(pq.poll()).toBe(3);
|
|
19
|
+
expect(pq.poll()).toBe(undefined);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { Deque } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('Deque coverage', () => {
|
|
4
|
+
it('constructor handles iterable-like length()/size() branches and bucketSize option', () => {
|
|
5
|
+
const arr = [1, 2, 3, 4, 5];
|
|
6
|
+
|
|
7
|
+
const withLengthFn = {
|
|
8
|
+
length: () => arr.length,
|
|
9
|
+
[Symbol.iterator]: function* () {
|
|
10
|
+
yield* arr;
|
|
11
|
+
}
|
|
12
|
+
} as any;
|
|
13
|
+
|
|
14
|
+
const d1 = new Deque<number>(withLengthFn, { bucketSize: 4 });
|
|
15
|
+
expect(d1.bucketSize).toBe(4);
|
|
16
|
+
expect([...d1]).toEqual(arr);
|
|
17
|
+
|
|
18
|
+
const withSizeFn = {
|
|
19
|
+
size: () => arr.length,
|
|
20
|
+
[Symbol.iterator]: function* () {
|
|
21
|
+
yield* arr;
|
|
22
|
+
}
|
|
23
|
+
} as any;
|
|
24
|
+
|
|
25
|
+
const d2 = new Deque<number>(withSizeFn, { bucketSize: 4 });
|
|
26
|
+
expect([...d2]).toEqual(arr);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('push/unshift respect maxLen (trigger shift/pop) and cover wrap-around + reallocate', () => {
|
|
30
|
+
// small bucket to make wrap/reallocate reachable with few ops
|
|
31
|
+
const d = new Deque<number>([], { bucketSize: 4, maxLen: 5 });
|
|
32
|
+
|
|
33
|
+
// Fill and force internal pointers to wrap a couple times
|
|
34
|
+
for (let i = 0; i < 20; i++) d.push(i);
|
|
35
|
+
expect(d.length).toBe(5);
|
|
36
|
+
expect([...d]).toEqual([15, 16, 17, 18, 19]);
|
|
37
|
+
|
|
38
|
+
for (let i = 100; i < 110; i++) d.unshift(i);
|
|
39
|
+
expect(d.length).toBe(5);
|
|
40
|
+
// unshift beyond maxLen pops from end
|
|
41
|
+
expect([...d]).toEqual([109, 108, 107, 106, 105]);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('pop/shift on empty and singleton cases', () => {
|
|
45
|
+
const empty = new Deque<number>([], { bucketSize: 4 });
|
|
46
|
+
expect(empty.pop()).toBeUndefined();
|
|
47
|
+
expect(empty.shift()).toBeUndefined();
|
|
48
|
+
expect(empty.first).toBeUndefined();
|
|
49
|
+
expect(empty.last).toBeUndefined();
|
|
50
|
+
|
|
51
|
+
const one = new Deque<number>([1], { bucketSize: 4 });
|
|
52
|
+
expect(one.first).toBe(1);
|
|
53
|
+
expect(one.last).toBe(1);
|
|
54
|
+
expect(one.pop()).toBe(1);
|
|
55
|
+
expect(one.length).toBe(0);
|
|
56
|
+
|
|
57
|
+
one.push(2);
|
|
58
|
+
expect(one.shift()).toBe(2);
|
|
59
|
+
expect(one.length).toBe(0);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('at/setAt/addAt/deleteAt/splice rangeCheck throwing + success paths', () => {
|
|
63
|
+
const d = new Deque<number>([1, 2, 3], { bucketSize: 4 });
|
|
64
|
+
|
|
65
|
+
expect(d.at(-1)).toBeUndefined();
|
|
66
|
+
expect(d.at(999)).toBeUndefined();
|
|
67
|
+
|
|
68
|
+
expect(() => d.setAt(-1 as any, 0)).toThrow();
|
|
69
|
+
expect(() => d.setAt(999 as any, 0)).toThrow();
|
|
70
|
+
expect(d.setAt(1, 20)).toBe(true);
|
|
71
|
+
expect([...d]).toEqual([1, 20, 3]);
|
|
72
|
+
|
|
73
|
+
expect(() => d.addAt(-1 as any, 0)).toThrow();
|
|
74
|
+
expect(() => d.deleteAt(-1 as any)).toThrow();
|
|
75
|
+
expect(() => d.splice(999 as any, 0)).toThrow();
|
|
76
|
+
|
|
77
|
+
// addAt: pos=0 and pos=length branches
|
|
78
|
+
d.addAt(0, 9, 2);
|
|
79
|
+
d.addAt(d.length, 7, 1);
|
|
80
|
+
expect(d.first).toBe(9);
|
|
81
|
+
expect(d.last).toBe(7);
|
|
82
|
+
|
|
83
|
+
// deleteAt: middle shift loop branch
|
|
84
|
+
const mid = d.deleteAt(2);
|
|
85
|
+
expect(mid).toBeDefined();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('cut/cutRest cover in-place and copy branches', () => {
|
|
89
|
+
const d = new Deque<number>([1, 2, 3, 4, 5], { bucketSize: 4 });
|
|
90
|
+
|
|
91
|
+
const prefix = d.cut(2, false);
|
|
92
|
+
expect([...prefix]).toEqual([1, 2, 3]);
|
|
93
|
+
|
|
94
|
+
const suffix = d.cutRest(3, false);
|
|
95
|
+
expect([...suffix]).toEqual([4, 5]);
|
|
96
|
+
|
|
97
|
+
// in-place cut with pos<0 clears
|
|
98
|
+
d.cut(-1, true);
|
|
99
|
+
expect(d.length).toBe(0);
|
|
100
|
+
|
|
101
|
+
const d2 = new Deque<number>([1, 2, 3, 4, 5], { bucketSize: 4 });
|
|
102
|
+
d2.cutRest(-1, true);
|
|
103
|
+
expect([...d2]).toEqual([1, 2, 3, 4, 5]);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('delete/deleteWhere/setEquality/unique/reverse/shrinkToFit cover branches', () => {
|
|
107
|
+
type Obj = { id: number };
|
|
108
|
+
const a: Obj = { id: 1 };
|
|
109
|
+
const b: Obj = { id: 1 };
|
|
110
|
+
const c: Obj = { id: 2 };
|
|
111
|
+
|
|
112
|
+
const d = new Deque<Obj>([a, c], { bucketSize: 4 });
|
|
113
|
+
|
|
114
|
+
// default Object.is: b not found
|
|
115
|
+
expect(d.delete(b)).toBe(true); // returns true even when not found? it compacts all != element
|
|
116
|
+
expect(d.length).toBe(2);
|
|
117
|
+
|
|
118
|
+
d.setEquality((x, y) => x.id === y.id);
|
|
119
|
+
expect(d.delete(b)).toBe(true);
|
|
120
|
+
expect([...d].map(x => x.id)).toEqual([2]);
|
|
121
|
+
|
|
122
|
+
d.push({ id: 2 });
|
|
123
|
+
d.push({ id: 3 });
|
|
124
|
+
|
|
125
|
+
expect(d.deleteWhere(v => v.id === 2)).toBe(true);
|
|
126
|
+
expect(d.deleteWhere(v => v.id === 999)).toBe(false);
|
|
127
|
+
|
|
128
|
+
// unique
|
|
129
|
+
const nums = new Deque<number>([1, 1, 2, 2, 2, 3], { bucketSize: 4 });
|
|
130
|
+
nums.unique();
|
|
131
|
+
expect([...nums]).toEqual([1, 2, 3]);
|
|
132
|
+
|
|
133
|
+
// unique early return
|
|
134
|
+
expect(new Deque<number>([1], { bucketSize: 4 }).unique().length).toBe(1);
|
|
135
|
+
|
|
136
|
+
// reverse
|
|
137
|
+
nums.reverse();
|
|
138
|
+
expect([...nums]).toEqual([3, 2, 1]);
|
|
139
|
+
|
|
140
|
+
// shrinkToFit branches
|
|
141
|
+
const s0 = new Deque<number>([], { bucketSize: 4 });
|
|
142
|
+
s0.shrinkToFit();
|
|
143
|
+
|
|
144
|
+
const s1 = new Deque<number>([1, 2, 3, 4, 5, 6, 7, 8], { bucketSize: 2 });
|
|
145
|
+
s1.shift();
|
|
146
|
+
s1.shift();
|
|
147
|
+
s1.pop();
|
|
148
|
+
s1.pop();
|
|
149
|
+
// now likely spans multiple buckets; just ensure no throw
|
|
150
|
+
s1.shrinkToFit();
|
|
151
|
+
expect(s1.length).toBeGreaterThan(0);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('filter/mapSame/map cover thisArg and toElementFn branches', () => {
|
|
155
|
+
const d = new Deque<number, { v: number }>([{ v: 1 }, { v: 2 }, { v: 3 }] as any, {
|
|
156
|
+
bucketSize: 4,
|
|
157
|
+
toElementFn: r => r.v
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const filtered = d.filter(v => v % 2 === 1);
|
|
161
|
+
expect([...filtered]).toEqual([1, 3]);
|
|
162
|
+
|
|
163
|
+
const ctx = { mul: 3 };
|
|
164
|
+
const mappedSame = d.mapSame(function (v) {
|
|
165
|
+
// @ts-ignore
|
|
166
|
+
return v * this.mul;
|
|
167
|
+
}, ctx);
|
|
168
|
+
expect([...mappedSame]).toEqual([3, 6, 9]);
|
|
169
|
+
|
|
170
|
+
const mapped = d.map(v => String(v));
|
|
171
|
+
expect([...mapped]).toEqual(['1', '2', '3']);
|
|
172
|
+
});
|
|
173
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Deque } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('Deque remaining branch coverage (batch 2)', () => {
|
|
4
|
+
it('unshiftMany covers toElementFn branch (and is executed at all)', () => {
|
|
5
|
+
const d = new Deque<number, { v: number }>([], {
|
|
6
|
+
toElementFn: (r: { v: number }) => r.v
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
expect(d.unshiftMany([{ v: 1 }, { v: 2 }])).toEqual([true, true]);
|
|
10
|
+
expect(d.toArray()).toEqual([2, 1]);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('splice(start) uses default deleteCount = length - start', () => {
|
|
14
|
+
const d = new Deque<number>();
|
|
15
|
+
d.pushMany([1, 2, 3, 4]);
|
|
16
|
+
|
|
17
|
+
// omit deleteCount to hit the default-arg branch
|
|
18
|
+
const removed = d.splice(1);
|
|
19
|
+
|
|
20
|
+
expect(removed.toArray()).toEqual([2, 3, 4]);
|
|
21
|
+
expect(d.toArray()).toEqual([1]);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('shrinkToFit covers wrap-around bucketFirst > bucketLast branch', () => {
|
|
25
|
+
const d = new Deque<number>();
|
|
26
|
+
|
|
27
|
+
// Force an internal wrap-around layout (reachable-only: test-side corruption).
|
|
28
|
+
(d as any)._length = 1;
|
|
29
|
+
(d as any)._bucketFirst = 2;
|
|
30
|
+
(d as any)._bucketLast = 1;
|
|
31
|
+
(d as any)._bucketCount = 4;
|
|
32
|
+
(d as any)._buckets = [[0], [1], [2], [3]];
|
|
33
|
+
|
|
34
|
+
expect(() => d.shrinkToFit()).not.toThrow();
|
|
35
|
+
expect((d as any)._bucketFirst).toBe(0);
|
|
36
|
+
expect((d as any)._bucketLast).toBe(3);
|
|
37
|
+
expect((d as any)._buckets.length).toBe(4);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Deque } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('Deque remaining branch coverage (batch 3)', () => {
|
|
4
|
+
it('unshiftMany covers else-branch when toElementFn is not provided', () => {
|
|
5
|
+
const d = new Deque<number>();
|
|
6
|
+
expect(d.unshiftMany([1, 2])).toEqual([true, true]);
|
|
7
|
+
expect(d.toArray()).toEqual([2, 1]);
|
|
8
|
+
});
|
|
9
|
+
});
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Deque } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('Deque additional branch coverage', () => {
|
|
4
|
+
it('unshiftMany() default-arg empty iterable returns []', () => {
|
|
5
|
+
const d = new Deque<number>();
|
|
6
|
+
expect(d.unshiftMany()).toEqual([]);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('splice clamps deleteCount when negative / too large (covers both clamp branches)', () => {
|
|
10
|
+
const d = new Deque<number>();
|
|
11
|
+
d.pushMany([1, 2, 3, 4]);
|
|
12
|
+
|
|
13
|
+
// deleteCount < 0 => clamp to 0
|
|
14
|
+
const r0 = d.splice(1, -1, 99);
|
|
15
|
+
expect(r0.toArray()).toEqual([]);
|
|
16
|
+
|
|
17
|
+
// deleteCount too large => clamp to length-start
|
|
18
|
+
const r1 = d.splice(1, 999);
|
|
19
|
+
expect(r1.toArray()).toEqual([99, 2, 3, 4]);
|
|
20
|
+
expect(d.toArray()).toEqual([1]);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('shrinkToFit returns early when bucketFirst===bucketLast (covers that return branch)', () => {
|
|
24
|
+
const d = new Deque<number>();
|
|
25
|
+
d.push(1);
|
|
26
|
+
// Force bucketFirst===bucketLast and length>0
|
|
27
|
+
(d as any)._bucketFirst = 0;
|
|
28
|
+
(d as any)._bucketLast = 0;
|
|
29
|
+
d.shrinkToFit();
|
|
30
|
+
expect(d.length).toBe(1);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('mapSame uses the thisArg===undefined branch', () => {
|
|
34
|
+
const d = new Deque<number>();
|
|
35
|
+
d.pushMany([1, 2, 3]);
|
|
36
|
+
const out = d.mapSame(v => v * 2);
|
|
37
|
+
expect(out.toArray()).toEqual([2, 4, 6]);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('map() uses thisArg branch and also covers options??{} merge path', () => {
|
|
41
|
+
const d = new Deque<number>();
|
|
42
|
+
d.pushMany([1, 2]);
|
|
43
|
+
const ctx = { add: 10 };
|
|
44
|
+
|
|
45
|
+
const out = d.map(
|
|
46
|
+
function (this: any, v: number) {
|
|
47
|
+
return v + this.add;
|
|
48
|
+
},
|
|
49
|
+
undefined,
|
|
50
|
+
ctx
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
expect(out.toArray()).toEqual([11, 12]);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('_setBucketSize does not reinit buckets when length>0 (covers length===0 false branch)', () => {
|
|
57
|
+
const d = new Deque<number>();
|
|
58
|
+
d.pushMany([1, 2, 3]);
|
|
59
|
+
const before = (d as any)._buckets;
|
|
60
|
+
(d as any)._setBucketSize((d as any)._bucketSize);
|
|
61
|
+
expect((d as any)._buckets).toBe(before);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('_getIterator yields only defined values (covers v!==undefined true branch)', () => {
|
|
65
|
+
const d = new Deque<number>();
|
|
66
|
+
d.pushMany([1, 2, 3]);
|
|
67
|
+
// Corrupt one slot to undefined; _getIterator should skip it.
|
|
68
|
+
const loc = (d as any)._getBucketAndPosition(1);
|
|
69
|
+
(d as any)._buckets[loc.bucketIndex][loc.indexInBucket] = undefined;
|
|
70
|
+
|
|
71
|
+
const got: number[] = [];
|
|
72
|
+
for (const v of d) got.push(v);
|
|
73
|
+
expect(got).toEqual([1, 3]);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('_createLike default-arg path can be called with no args', () => {
|
|
77
|
+
const d = new Deque<number>();
|
|
78
|
+
const like = (d as any)._createLike();
|
|
79
|
+
expect(like.length).toBe(0);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('_getReverseIterator handles v===undefined by not yielding it', () => {
|
|
83
|
+
const d = new Deque<number>();
|
|
84
|
+
d.pushMany([1, 2, 3]);
|
|
85
|
+
|
|
86
|
+
// Make last element undefined
|
|
87
|
+
const loc = (d as any)._getBucketAndPosition(2);
|
|
88
|
+
(d as any)._buckets[loc.bucketIndex][loc.indexInBucket] = undefined;
|
|
89
|
+
|
|
90
|
+
const it = (d as any)._getReverseIterator();
|
|
91
|
+
const got: number[] = [];
|
|
92
|
+
for (const v of it) got.push(v);
|
|
93
|
+
expect(got).toEqual([2, 1]);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { Queue } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('Queue coverage', () => {
|
|
4
|
+
it('constructor options set autoCompactRatio and push respects maxLen via shift', () => {
|
|
5
|
+
const q = new Queue<number>([], { maxLen: 2, autoCompactRatio: 1 });
|
|
6
|
+
expect(q.autoCompactRatio).toBe(1);
|
|
7
|
+
|
|
8
|
+
q.push(1);
|
|
9
|
+
q.push(2);
|
|
10
|
+
q.push(3); // maxLen overflow triggers shift()
|
|
11
|
+
|
|
12
|
+
expect([...q]).toEqual([2, 3]);
|
|
13
|
+
expect(q.length).toBe(2);
|
|
14
|
+
expect(q.first).toBe(2);
|
|
15
|
+
expect(q.last).toBe(3);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('pushMany uses toElementFn branch', () => {
|
|
19
|
+
const q = new Queue<number, { v: number }>([], { toElementFn: r => r.v });
|
|
20
|
+
expect(q.pushMany([{ v: 1 }, { v: 2 }])).toEqual([true, true]);
|
|
21
|
+
expect([...q]).toEqual([1, 2]);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('shift covers empty branch and compaction trigger', () => {
|
|
25
|
+
const q = new Queue<number>();
|
|
26
|
+
expect(q.shift()).toBeUndefined();
|
|
27
|
+
|
|
28
|
+
// Force compaction quickly.
|
|
29
|
+
q.autoCompactRatio = 0.25;
|
|
30
|
+
q.pushMany([1, 2, 3, 4]);
|
|
31
|
+
|
|
32
|
+
expect(q.shift()).toBe(1);
|
|
33
|
+
// offset=1, elements.length=4 => 0.25, not strictly greater
|
|
34
|
+
expect(q.offset).toBe(1);
|
|
35
|
+
|
|
36
|
+
expect(q.shift()).toBe(2);
|
|
37
|
+
// offset=2, elements.length=4 => 0.5 > 0.25 => compact()
|
|
38
|
+
expect(q.offset).toBe(0);
|
|
39
|
+
expect(q.elements).toEqual([3, 4]);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('delete/deleteAt/addAt/setAt cover bounds and success', () => {
|
|
43
|
+
const q = new Queue<number>([1, 2, 3, 4]);
|
|
44
|
+
// consume one to introduce offset
|
|
45
|
+
expect(q.shift()).toBe(1);
|
|
46
|
+
|
|
47
|
+
expect(q.delete(999)).toBe(false);
|
|
48
|
+
expect(q.delete(3)).toBe(true);
|
|
49
|
+
expect([...q]).toEqual([2, 4]);
|
|
50
|
+
|
|
51
|
+
expect(q.at(-1)).toBeUndefined();
|
|
52
|
+
expect(q.at(999)).toBeUndefined();
|
|
53
|
+
expect(q.at(0)).toBe(2);
|
|
54
|
+
|
|
55
|
+
expect(q.deleteAt(-1)).toBeUndefined();
|
|
56
|
+
expect(q.deleteAt(999)).toBeUndefined();
|
|
57
|
+
expect(q.deleteAt(0)).toBe(2);
|
|
58
|
+
expect([...q]).toEqual([4]);
|
|
59
|
+
|
|
60
|
+
expect(q.addAt(-1, 0)).toBe(false);
|
|
61
|
+
expect(q.addAt(999, 0)).toBe(false);
|
|
62
|
+
expect(q.addAt(0, 3)).toBe(true);
|
|
63
|
+
expect([...q]).toEqual([3, 4]);
|
|
64
|
+
|
|
65
|
+
expect(q.setAt(-1, 0)).toBe(false);
|
|
66
|
+
expect(q.setAt(999, 0)).toBe(false);
|
|
67
|
+
expect(q.setAt(1, 40)).toBe(true);
|
|
68
|
+
expect([...q]).toEqual([3, 40]);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('reverse/clear/compact basic behaviors', () => {
|
|
72
|
+
const q = new Queue<number>([1, 2, 3]);
|
|
73
|
+
q.shift();
|
|
74
|
+
expect(q.offset).toBe(1);
|
|
75
|
+
|
|
76
|
+
q.reverse();
|
|
77
|
+
expect(q.offset).toBe(0);
|
|
78
|
+
expect([...q]).toEqual([3, 2]);
|
|
79
|
+
|
|
80
|
+
q.clear();
|
|
81
|
+
expect(q.length).toBe(0);
|
|
82
|
+
expect(q.offset).toBe(0);
|
|
83
|
+
|
|
84
|
+
q.pushMany([1, 2]);
|
|
85
|
+
q.shift();
|
|
86
|
+
expect(q.compact()).toBe(true);
|
|
87
|
+
expect(q.offset).toBe(0);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('splice triggers optional compaction and returns removed queue with copied ratio', () => {
|
|
91
|
+
const q = new Queue<number>([1, 2, 3, 4, 5], { autoCompactRatio: 0.2 });
|
|
92
|
+
q.shift();
|
|
93
|
+
q.shift(); // offset=2, len=5 => 0.4 > 0.2 would compact on next splice
|
|
94
|
+
|
|
95
|
+
const removed = q.splice(1, 2, 9, 8);
|
|
96
|
+
expect([...removed]).toEqual([4, 5]);
|
|
97
|
+
expect(removed.autoCompactRatio).toBe(q.autoCompactRatio);
|
|
98
|
+
|
|
99
|
+
expect([...q]).toEqual([3, 9, 8]);
|
|
100
|
+
expect(q.offset).toBe(0);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('map/mapSame cover thisArg and default branches, and _createLike default elements branch', () => {
|
|
104
|
+
const q = new Queue<number>([1, 2, 3], { autoCompactRatio: 0.9 });
|
|
105
|
+
|
|
106
|
+
const mapped1 = q.map(v => v + 1);
|
|
107
|
+
expect([...mapped1]).toEqual([2, 3, 4]);
|
|
108
|
+
|
|
109
|
+
const ctx = { mul: 2 };
|
|
110
|
+
const mapped2 = q.map(function (v) {
|
|
111
|
+
// @ts-ignore
|
|
112
|
+
return v * this.mul;
|
|
113
|
+
}, undefined, ctx);
|
|
114
|
+
expect([...mapped2]).toEqual([2, 4, 6]);
|
|
115
|
+
|
|
116
|
+
const same1 = q.mapSame(v => v * 10);
|
|
117
|
+
expect([...same1]).toEqual([10, 20, 30]);
|
|
118
|
+
|
|
119
|
+
const same2 = q.mapSame(function (v) {
|
|
120
|
+
// @ts-ignore
|
|
121
|
+
return v + this.inc;
|
|
122
|
+
}, { inc: 5 });
|
|
123
|
+
expect([...same2]).toEqual([6, 7, 8]);
|
|
124
|
+
|
|
125
|
+
const like = (q as any)._createLike();
|
|
126
|
+
expect(like.length).toBe(0);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('_getReverseIterator skips undefined items', () => {
|
|
130
|
+
const q = new Queue<number | undefined>([1, undefined, 2]);
|
|
131
|
+
expect([...q.toReversedArray()]).toEqual([2, undefined, 1]);
|
|
132
|
+
|
|
133
|
+
const rev: (number | undefined)[] = [];
|
|
134
|
+
for (const v of (q as any)._getReverseIterator()) rev.push(v);
|
|
135
|
+
// undefined is skipped by implementation
|
|
136
|
+
expect(rev).toEqual([2, 1]);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Queue } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('Queue remaining branch coverage (batch 2)', () => {
|
|
4
|
+
it('splice(start) hits default deleteCount=0 and can trigger auto-compaction branch', () => {
|
|
5
|
+
const q = new Queue<number>();
|
|
6
|
+
q.pushMany([1, 2, 3]);
|
|
7
|
+
|
|
8
|
+
// Prevent auto-compaction during the shifts; we want a non-zero offset.
|
|
9
|
+
q.autoCompactRatio = 1;
|
|
10
|
+
|
|
11
|
+
// Create offset > 0 while keeping underlying elements array non-empty.
|
|
12
|
+
expect(q.shift()).toBe(1);
|
|
13
|
+
expect(q.shift()).toBe(2);
|
|
14
|
+
expect(q.offset).toBe(2);
|
|
15
|
+
|
|
16
|
+
// Now ensure the condition `offset/elements.length > autoCompactRatio` is true at splice-time.
|
|
17
|
+
q.autoCompactRatio = 0;
|
|
18
|
+
|
|
19
|
+
// Omit deleteCount to hit the default-arg branch.
|
|
20
|
+
const removed = q.splice(0, undefined as any, 9);
|
|
21
|
+
|
|
22
|
+
// Should have compacted (offset reset) and inserted item.
|
|
23
|
+
expect(q.offset).toBe(0);
|
|
24
|
+
expect(q.toArray()).toEqual([9, 3]);
|
|
25
|
+
expect(removed.toArray()).toEqual([]);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { Stack } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('Stack coverage', () => {
|
|
4
|
+
it('fromArray + basic ops cover isEmpty/peek/pop on empty', () => {
|
|
5
|
+
// constructor default params branch
|
|
6
|
+
const empty = new Stack<number>();
|
|
7
|
+
expect(empty.size).toBe(0);
|
|
8
|
+
|
|
9
|
+
const s = Stack.fromArray([1, 2, 3]);
|
|
10
|
+
expect([...s]).toEqual([1, 2, 3]);
|
|
11
|
+
|
|
12
|
+
expect(s.peek()).toBe(3);
|
|
13
|
+
expect(s.pop()).toBe(3);
|
|
14
|
+
expect(s.pop()).toBe(2);
|
|
15
|
+
expect(s.pop()).toBe(1);
|
|
16
|
+
|
|
17
|
+
expect(s.isEmpty()).toBe(true);
|
|
18
|
+
expect(s.peek()).toBeUndefined();
|
|
19
|
+
expect(s.pop()).toBeUndefined();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('pushMany uses toElementFn conversion branch', () => {
|
|
23
|
+
const s = new Stack<number, { v: number }>([], { toElementFn: r => r.v });
|
|
24
|
+
const res = s.pushMany([{ v: 1 }, { v: 2 }]);
|
|
25
|
+
expect(res).toEqual([true, true]);
|
|
26
|
+
expect([...s]).toEqual([1, 2]);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('delete/deleteAt cover not-found and bounds', () => {
|
|
30
|
+
const s = new Stack<number>([1, 2, 3, 2]);
|
|
31
|
+
|
|
32
|
+
// not found => _indexOfByEquals returns -1 => deleteAt(-1) false
|
|
33
|
+
expect(s.delete(999)).toBe(false);
|
|
34
|
+
|
|
35
|
+
// bounds
|
|
36
|
+
expect(s.deleteAt(-1)).toBe(false);
|
|
37
|
+
expect(s.deleteAt(999)).toBe(false);
|
|
38
|
+
|
|
39
|
+
// delete first matching occurrence (bottom-up)
|
|
40
|
+
expect(s.delete(2)).toBe(true);
|
|
41
|
+
expect([...s]).toEqual([1, 3, 2]);
|
|
42
|
+
|
|
43
|
+
// deleteAt valid
|
|
44
|
+
expect(s.deleteAt(1)).toBe(true);
|
|
45
|
+
expect([...s]).toEqual([1, 2]);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('deleteWhere covers both match and no-match branches', () => {
|
|
49
|
+
const s = new Stack<number>([1, 2, 3]);
|
|
50
|
+
expect(s.deleteWhere(v => v === 2)).toBe(true);
|
|
51
|
+
expect([...s]).toEqual([1, 3]);
|
|
52
|
+
|
|
53
|
+
expect(s.deleteWhere(v => v === 999)).toBe(false);
|
|
54
|
+
expect([...s]).toEqual([1, 3]);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('clear/clone/filter/mapSame/map cover instance factories and thisArg call path', () => {
|
|
58
|
+
const raw = [{ v: 1 }, { v: 2 }, { v: 3 }];
|
|
59
|
+
const s = new Stack<number, { v: number }>(raw, { toElementFn: r => r.v });
|
|
60
|
+
|
|
61
|
+
const cloned = s.clone();
|
|
62
|
+
expect([...cloned]).toEqual([1, 2, 3]);
|
|
63
|
+
|
|
64
|
+
const filtered = s.filter(v => v % 2 === 1);
|
|
65
|
+
expect([...filtered]).toEqual([1, 3]);
|
|
66
|
+
|
|
67
|
+
const mappedSame = s.mapSame(v => v * 2);
|
|
68
|
+
expect([...mappedSame]).toEqual([2, 4, 6]);
|
|
69
|
+
|
|
70
|
+
// mapSame with thisArg branch
|
|
71
|
+
const ctx2 = { mul: 3 };
|
|
72
|
+
const mappedSame2 = s.mapSame(function (v) {
|
|
73
|
+
// @ts-ignore
|
|
74
|
+
return v * this.mul;
|
|
75
|
+
}, ctx2);
|
|
76
|
+
expect([...mappedSame2]).toEqual([3, 6, 9]);
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
// map with thisArg branch
|
|
80
|
+
const ctx = { inc: 10 };
|
|
81
|
+
const mapped = s.map(function (v) {
|
|
82
|
+
// @ts-ignore
|
|
83
|
+
return v + this.inc;
|
|
84
|
+
}, undefined, ctx);
|
|
85
|
+
expect([...mapped]).toEqual([11, 12, 13]);
|
|
86
|
+
|
|
87
|
+
// map with undefined thisArg branch
|
|
88
|
+
const mapped2 = s.map(v => v + 1);
|
|
89
|
+
expect([...mapped2]).toEqual([2, 3, 4]);
|
|
90
|
+
|
|
91
|
+
// _createLike default elements branch (protected)
|
|
92
|
+
const like = (s as any)._createLike();
|
|
93
|
+
expect(like.size).toBe(0);
|
|
94
|
+
|
|
95
|
+
s.clear();
|
|
96
|
+
expect(s.size).toBe(0);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('setEquality affects delete/search semantics', () => {
|
|
100
|
+
type Obj = { id: number };
|
|
101
|
+
const a = { id: 1 };
|
|
102
|
+
const b = { id: 2 };
|
|
103
|
+
const s = new Stack<Obj>([a, b]);
|
|
104
|
+
|
|
105
|
+
// default Object.is: new object not found
|
|
106
|
+
expect(s.delete({ id: 1 } as any)).toBe(false);
|
|
107
|
+
|
|
108
|
+
s.setEquality((x, y) => x.id === y.id);
|
|
109
|
+
expect(s.delete({ id: 1 } as any)).toBe(true);
|
|
110
|
+
expect([...s].map(x => x.id)).toEqual([2]);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { TreeNode } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('TreeNode remaining branch coverage', () => {
|
|
4
|
+
it('constructor assigns children when provided (covers if(children) branch)', () => {
|
|
5
|
+
const child = new TreeNode('c');
|
|
6
|
+
const root = new TreeNode('r', undefined, [child]);
|
|
7
|
+
expect(root.children).toEqual([child]);
|
|
8
|
+
});
|
|
9
|
+
});
|