data-structure-typed 2.2.8 → 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 +1 -1
- package/README_CN.md +1 -1
- package/dist/cjs/index.cjs +584 -76
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs-legacy/index.cjs +588 -79
- package/dist/cjs-legacy/index.cjs.map +1 -1
- package/dist/esm/index.mjs +584 -76
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm-legacy/index.mjs +588 -79
- package/dist/esm-legacy/index.mjs.map +1 -1
- package/dist/types/data-structures/base/linear-base.d.ts +6 -6
- package/dist/types/data-structures/binary-tree/binary-tree.d.ts +3 -4
- package/dist/types/data-structures/binary-tree/bst.d.ts +2 -1
- package/dist/types/data-structures/binary-tree/red-black-tree.d.ts +150 -20
- package/dist/types/data-structures/binary-tree/tree-counter.d.ts +3 -3
- package/dist/types/interfaces/binary-tree.d.ts +1 -1
- package/dist/umd/data-structure-typed.js +588 -79
- 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 +4 -3
- package/src/data-structures/base/linear-base.ts +2 -12
- package/src/data-structures/binary-tree/binary-tree.ts +5 -6
- package/src/data-structures/binary-tree/bst.ts +79 -4
- package/src/data-structures/binary-tree/red-black-tree.ts +583 -73
- package/src/data-structures/binary-tree/tree-counter.ts +21 -9
- package/src/data-structures/queue/deque.ts +10 -0
- package/src/interfaces/binary-tree.ts +1 -1
- 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-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-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/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/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 +25 -55
- 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.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 +4 -2
- 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/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
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { DoublyLinkedList, SinglyLinkedList } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('LinkedList unshiftMany else-branch coverage', () => {
|
|
4
|
+
it('DoublyLinkedList.unshiftMany uses else-branch when toElementFn is not provided', () => {
|
|
5
|
+
const l = new DoublyLinkedList<number>();
|
|
6
|
+
expect(l.unshiftMany([1, 2])).toEqual([true, true]);
|
|
7
|
+
expect(l.toArray()).toEqual([2, 1]);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('SinglyLinkedList.unshiftMany uses else-branch when toElementFn is not provided', () => {
|
|
11
|
+
const l = new SinglyLinkedList<number>();
|
|
12
|
+
expect(l.unshiftMany([1, 2])).toEqual([true, true]);
|
|
13
|
+
expect(l.toArray()).toEqual([2, 1]);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { SinglyLinkedList, SinglyLinkedListNode } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('SinglyLinkedList coverage', () => {
|
|
4
|
+
it('push respects maxLen by shifting when over capacity', () => {
|
|
5
|
+
const list = new SinglyLinkedList<number>([], { maxLen: 2 });
|
|
6
|
+
list.push(1);
|
|
7
|
+
list.push(2);
|
|
8
|
+
list.push(3); // should shift 1
|
|
9
|
+
expect([...list]).toEqual([2, 3]);
|
|
10
|
+
expect(list.length).toBe(2);
|
|
11
|
+
expect(list.first).toBe(2);
|
|
12
|
+
expect(list.last).toBe(3);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('pop covers empty, single-node, and multi-node cases', () => {
|
|
16
|
+
const empty = new SinglyLinkedList<number>();
|
|
17
|
+
expect(empty.pop()).toBeUndefined();
|
|
18
|
+
|
|
19
|
+
const single = new SinglyLinkedList<number>([1]);
|
|
20
|
+
expect(single.pop()).toBe(1);
|
|
21
|
+
expect(single.length).toBe(0);
|
|
22
|
+
expect(single.head).toBeUndefined();
|
|
23
|
+
expect(single.tail).toBeUndefined();
|
|
24
|
+
|
|
25
|
+
const multi = new SinglyLinkedList<number>([1, 2, 3]);
|
|
26
|
+
expect(multi.pop()).toBe(3);
|
|
27
|
+
expect([...multi]).toEqual([1, 2]);
|
|
28
|
+
expect(multi.tail?.value).toBe(2);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('shift/unshift handle empty and update tail when last removed', () => {
|
|
32
|
+
const list = new SinglyLinkedList<number>();
|
|
33
|
+
expect(list.shift()).toBeUndefined();
|
|
34
|
+
|
|
35
|
+
list.unshift(1);
|
|
36
|
+
expect(list.shift()).toBe(1);
|
|
37
|
+
expect(list.head).toBeUndefined();
|
|
38
|
+
expect(list.tail).toBeUndefined();
|
|
39
|
+
expect(list.length).toBe(0);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('pushMany/unshiftMany exercise toElementFn conversion branch', () => {
|
|
43
|
+
const list = new SinglyLinkedList<number, { v: number }>([], { toElementFn: r => r.v });
|
|
44
|
+
|
|
45
|
+
expect(list.pushMany([{ v: 1 }, { v: 2 }])).toEqual([true, true]);
|
|
46
|
+
expect([...list]).toEqual([1, 2]);
|
|
47
|
+
|
|
48
|
+
expect(list.unshiftMany([{ v: 3 }, { v: 4 }])).toEqual([true, true]);
|
|
49
|
+
expect([...list]).toEqual([4, 3, 1, 2]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('at/getNodeAt/setAt cover bounds and success cases', () => {
|
|
53
|
+
const list = new SinglyLinkedList<number>([1, 2, 3]);
|
|
54
|
+
|
|
55
|
+
expect(list.at(-1)).toBeUndefined();
|
|
56
|
+
expect(list.at(999)).toBeUndefined();
|
|
57
|
+
expect(list.at(1)).toBe(2);
|
|
58
|
+
|
|
59
|
+
expect(list.getNodeAt(-1)).toBeUndefined();
|
|
60
|
+
expect(list.getNodeAt(999)).toBeUndefined();
|
|
61
|
+
|
|
62
|
+
expect(list.setAt(999, 0)).toBe(false);
|
|
63
|
+
expect(list.setAt(1, 20)).toBe(true);
|
|
64
|
+
expect([...list]).toEqual([1, 20, 3]);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('deleteAt covers head delete, tail delete, and middle delete', () => {
|
|
68
|
+
const list = new SinglyLinkedList<number>([1, 2, 3]);
|
|
69
|
+
|
|
70
|
+
expect(list.deleteAt(-1)).toBeUndefined();
|
|
71
|
+
expect(list.deleteAt(999)).toBeUndefined();
|
|
72
|
+
|
|
73
|
+
// head
|
|
74
|
+
expect(list.deleteAt(0)).toBe(1);
|
|
75
|
+
expect([...list]).toEqual([2, 3]);
|
|
76
|
+
|
|
77
|
+
// tail
|
|
78
|
+
expect(list.deleteAt(1)).toBe(3);
|
|
79
|
+
expect([...list]).toEqual([2]);
|
|
80
|
+
expect(list.tail?.value).toBe(2);
|
|
81
|
+
|
|
82
|
+
// middle (rebuild)
|
|
83
|
+
list.pushMany([3, 4]); // [2,3,4]
|
|
84
|
+
expect(list.deleteAt(1)).toBe(3);
|
|
85
|
+
expect([...list]).toEqual([2, 4]);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('delete covers undefined input, missing node, and deleting head/tail', () => {
|
|
89
|
+
const list = new SinglyLinkedList<number>([1, 2, 3]);
|
|
90
|
+
|
|
91
|
+
expect(list.delete(undefined)).toBe(false);
|
|
92
|
+
expect(list.delete(999)).toBe(false);
|
|
93
|
+
|
|
94
|
+
// delete head
|
|
95
|
+
expect(list.delete(1)).toBe(true);
|
|
96
|
+
expect([...list]).toEqual([2, 3]);
|
|
97
|
+
|
|
98
|
+
// delete tail
|
|
99
|
+
expect(list.delete(3)).toBe(true);
|
|
100
|
+
expect([...list]).toEqual([2]);
|
|
101
|
+
expect(list.tail?.value).toBe(2);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('reverse early-return and full reverse path', () => {
|
|
105
|
+
const empty = new SinglyLinkedList<number>();
|
|
106
|
+
expect(empty.reverse()).toBe(empty);
|
|
107
|
+
|
|
108
|
+
const single = new SinglyLinkedList<number>([1]);
|
|
109
|
+
expect([...single.reverse()]).toEqual([1]);
|
|
110
|
+
|
|
111
|
+
const list = new SinglyLinkedList<number>([1, 2, 3]);
|
|
112
|
+
list.reverse();
|
|
113
|
+
expect([...list]).toEqual([3, 2, 1]);
|
|
114
|
+
expect(list.first).toBe(3);
|
|
115
|
+
expect(list.last).toBe(1);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('getNode/search handle undefined, node pass-through, and predicate branches', () => {
|
|
119
|
+
const list = new SinglyLinkedList<number>([1, 2, 3]);
|
|
120
|
+
expect(list.getNode(undefined)).toBeUndefined();
|
|
121
|
+
|
|
122
|
+
const n2 = list.getNodeAt(1)!;
|
|
123
|
+
expect(list.getNode(n2)).toBe(n2);
|
|
124
|
+
|
|
125
|
+
expect(list.getNode(node => node.value === 3)?.value).toBe(3);
|
|
126
|
+
expect(list.search(node => node.value === 2)).toBe(2);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('addAt/addBefore/addAfter cover boundary and missing-node cases', () => {
|
|
130
|
+
const list = new SinglyLinkedList<number>([2, 4]);
|
|
131
|
+
|
|
132
|
+
expect(list.addAt(-1, 0)).toBe(false);
|
|
133
|
+
expect(list.addAt(999, 0)).toBe(false);
|
|
134
|
+
|
|
135
|
+
// addAt head/tail/middle
|
|
136
|
+
expect(list.addAt(0, 1)).toBe(true);
|
|
137
|
+
expect(list.addAt(list.length, 5)).toBe(true);
|
|
138
|
+
expect(list.addAt(2, 3)).toBe(true);
|
|
139
|
+
expect([...list]).toEqual([1, 2, 3, 4, 5]);
|
|
140
|
+
|
|
141
|
+
// addBefore/After missing
|
|
142
|
+
expect(list.addBefore(999, 0)).toBe(false);
|
|
143
|
+
expect(list.addAfter(999, 0)).toBe(false);
|
|
144
|
+
|
|
145
|
+
// addBefore head
|
|
146
|
+
expect(list.addBefore(1, 0)).toBe(true);
|
|
147
|
+
// addAfter tail
|
|
148
|
+
expect(list.addAfter(5, 6)).toBe(true);
|
|
149
|
+
expect([...list]).toEqual([0, 1, 2, 3, 4, 5, 6]);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('splice covers remove-only, insert-only, remove+insert, and empty-result reset', () => {
|
|
153
|
+
const list = new SinglyLinkedList<number>([1, 2, 3, 4]);
|
|
154
|
+
|
|
155
|
+
// remove middle
|
|
156
|
+
const removed = list.splice(1, 2);
|
|
157
|
+
expect([...removed]).toEqual([2, 3]);
|
|
158
|
+
expect([...list]).toEqual([1, 4]);
|
|
159
|
+
|
|
160
|
+
// insert at head without deletion
|
|
161
|
+
const removed2 = list.splice(0, 0, 9, 8);
|
|
162
|
+
expect([...removed2]).toEqual([]);
|
|
163
|
+
expect([...list]).toEqual([9, 8, 1, 4]);
|
|
164
|
+
|
|
165
|
+
// remove tail and insert
|
|
166
|
+
const removed3 = list.splice(3, 10, 7);
|
|
167
|
+
expect([...removed3]).toEqual([4]);
|
|
168
|
+
expect([...list]).toEqual([9, 8, 1, 7]);
|
|
169
|
+
|
|
170
|
+
// remove everything, expect head/tail reset
|
|
171
|
+
const removedAll = list.splice(0, 999);
|
|
172
|
+
expect([...removedAll]).toEqual([9, 8, 1, 7]);
|
|
173
|
+
expect(list.length).toBe(0);
|
|
174
|
+
expect(list.head).toBeUndefined();
|
|
175
|
+
expect(list.tail).toBeUndefined();
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('countOccurrences covers element/node/predicate branches and setEquality', () => {
|
|
179
|
+
type Obj = { id: number };
|
|
180
|
+
const a: Obj = { id: 1 };
|
|
181
|
+
const b: Obj = { id: 1 };
|
|
182
|
+
const c: Obj = { id: 2 };
|
|
183
|
+
|
|
184
|
+
const list = new SinglyLinkedList<Obj>([a, c]);
|
|
185
|
+
|
|
186
|
+
// default Object.is: b is not the same ref as a
|
|
187
|
+
expect(list.countOccurrences(b)).toBe(0);
|
|
188
|
+
|
|
189
|
+
list.setEquality((x, y) => x.id === y.id);
|
|
190
|
+
expect(list.countOccurrences(b)).toBe(1);
|
|
191
|
+
|
|
192
|
+
const nodeA = list.getNodeAt(0)!;
|
|
193
|
+
expect(list.countOccurrences(nodeA)).toBe(1);
|
|
194
|
+
|
|
195
|
+
expect(list.countOccurrences(node => node.value.id === 2)).toBe(1);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('deleteWhere covers deleting head and tail branches + no-match', () => {
|
|
199
|
+
const list = new SinglyLinkedList<number>([1, 2, 3]);
|
|
200
|
+
|
|
201
|
+
// delete head branch
|
|
202
|
+
expect(list.deleteWhere(v => v === 1)).toBe(true);
|
|
203
|
+
expect([...list]).toEqual([2, 3]);
|
|
204
|
+
|
|
205
|
+
// delete tail branch
|
|
206
|
+
expect(list.deleteWhere(v => v === 3)).toBe(true);
|
|
207
|
+
expect([...list]).toEqual([2]);
|
|
208
|
+
expect(list.tail?.value).toBe(2);
|
|
209
|
+
|
|
210
|
+
// no match
|
|
211
|
+
expect(list.deleteWhere(v => v === 999)).toBe(false);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('_getPrevNode not-found branch via foreign node', () => {
|
|
215
|
+
const list = new SinglyLinkedList<number>([1, 2, 3]);
|
|
216
|
+
const foreign = new SinglyLinkedListNode(2);
|
|
217
|
+
|
|
218
|
+
// Access protected for branch coverage.
|
|
219
|
+
expect((list as any)._getPrevNode(foreign)).toBeUndefined();
|
|
220
|
+
});
|
|
221
|
+
});
|
package/test/unit/data-structures/linked-list/singly-linked-list.more-branches.coverage.test.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { SinglyLinkedList, SinglyLinkedListNode } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('SinglyLinkedList additional branch coverage', () => {
|
|
4
|
+
it('unshiftMany uses toElementFn branch when provided', () => {
|
|
5
|
+
const l = new SinglyLinkedList<number, { v: number }>([], {
|
|
6
|
+
toElementFn: r => r.v
|
|
7
|
+
});
|
|
8
|
+
expect(l.unshiftMany([{ v: 1 }, { v: 2 }])).toEqual([true, true]);
|
|
9
|
+
expect(l.toArray()).toEqual([2, 1]);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('addBefore sets tail when prevNode is undefined and internal tail is missing (covers if(!this._tail))', () => {
|
|
13
|
+
const l = new SinglyLinkedList<number>();
|
|
14
|
+
l.push(1);
|
|
15
|
+
|
|
16
|
+
// Corrupt internal tail so the recovery branch runs.
|
|
17
|
+
(l as any)._tail = undefined;
|
|
18
|
+
|
|
19
|
+
expect(l.addBefore(1, 0)).toBe(true);
|
|
20
|
+
expect(l.toArray()).toEqual([0, 1]);
|
|
21
|
+
// and tail should be restored (best-effort invariant)
|
|
22
|
+
expect((l as any)._tail).toBeDefined();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('splice uses default deleteCount=0 when omitted', () => {
|
|
26
|
+
const l = new SinglyLinkedList<number>();
|
|
27
|
+
l.pushMany([1, 2, 3]);
|
|
28
|
+
|
|
29
|
+
const removed = l.splice(1); // deleteCount omitted
|
|
30
|
+
expect(removed.toArray()).toEqual([]);
|
|
31
|
+
expect(l.toArray()).toEqual([1, 2, 3]);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('deleteWhere sets tail to undefined when removing the only element (covers current===_tail branch)', () => {
|
|
35
|
+
const l = new SinglyLinkedList<number>();
|
|
36
|
+
l.push(1);
|
|
37
|
+
|
|
38
|
+
expect(l.deleteWhere(v => v === 1)).toBe(true);
|
|
39
|
+
expect(l.length).toBe(0);
|
|
40
|
+
expect((l as any)._tail).toBeUndefined();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('mapSame covers both ternary arms (thisArg undefined vs defined)', () => {
|
|
44
|
+
const l = new SinglyLinkedList<number>();
|
|
45
|
+
l.pushMany([1, 2]);
|
|
46
|
+
|
|
47
|
+
// thisArg === undefined branch
|
|
48
|
+
expect(l.mapSame(v => v + 1).toArray()).toEqual([2, 3]);
|
|
49
|
+
|
|
50
|
+
// thisArg provided branch
|
|
51
|
+
const ctx = { add: 10 };
|
|
52
|
+
expect(
|
|
53
|
+
l
|
|
54
|
+
.mapSame(function (this: any, v: number) {
|
|
55
|
+
return v + this.add;
|
|
56
|
+
}, ctx)
|
|
57
|
+
.toArray()
|
|
58
|
+
).toEqual([11, 12]);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('_ensureNode returns the same node when input is a node (covers isNode true branch)', () => {
|
|
62
|
+
const l = new SinglyLinkedList<number>();
|
|
63
|
+
l.pushMany([1, 3]);
|
|
64
|
+
|
|
65
|
+
const existing = l.getNodeAt(0)!;
|
|
66
|
+
const newNode = new SinglyLinkedListNode(2);
|
|
67
|
+
|
|
68
|
+
// addAfter calls _ensureNode(newElementOrNode)
|
|
69
|
+
expect(l.addAfter(existing, newNode)).toBe(true);
|
|
70
|
+
expect(l.toArray()).toEqual([1, 2, 3]);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('_ensurePredicate covers isNode(target) branch via search(node)', () => {
|
|
74
|
+
const l = new SinglyLinkedList<number>();
|
|
75
|
+
l.pushMany([1, 2, 3]);
|
|
76
|
+
|
|
77
|
+
const target = l.getNodeAt(1)!;
|
|
78
|
+
expect(l.search(target)).toBe(2);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('_createLike default-arg path can be called with no args', () => {
|
|
82
|
+
const l = new SinglyLinkedList<number>();
|
|
83
|
+
const like = (l as any)._createLike();
|
|
84
|
+
expect(like.length).toBe(0);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { SkipList } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('SkipList additional branch coverage', () => {
|
|
4
|
+
it('constructor applies options branches (maxLevel/probability) and first() returns undefined when empty', () => {
|
|
5
|
+
const s = new SkipList<number, number>([], { maxLevel: 8, probability: 0.25 });
|
|
6
|
+
expect(s.maxLevel).toBe(8);
|
|
7
|
+
expect(s.probability).toBe(0.25);
|
|
8
|
+
|
|
9
|
+
// covers `firstNode ? ... : undefined` false arm
|
|
10
|
+
expect(s.first).toBeUndefined();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('delete() covers the break branch when deleted node has smaller level than list level', () => {
|
|
14
|
+
const s = new SkipList<number, string>();
|
|
15
|
+
|
|
16
|
+
// Force deterministic node levels: first node makes list level high, second is low-level.
|
|
17
|
+
const origRandomLevel = (s as any)._randomLevel;
|
|
18
|
+
const levels = [4, 1];
|
|
19
|
+
(s as any)._randomLevel = () => levels.shift() ?? 1;
|
|
20
|
+
try {
|
|
21
|
+
s.add(1, 'hi'); // level 4, end -> raises list level
|
|
22
|
+
s.add(2, 'lo'); // level 1, end, list level stays 4
|
|
23
|
+
|
|
24
|
+
expect(s.level).toBeGreaterThan(1);
|
|
25
|
+
expect(s.delete(2)).toBe(true);
|
|
26
|
+
expect(s.get(2)).toBeUndefined();
|
|
27
|
+
} finally {
|
|
28
|
+
(s as any)._randomLevel = origRandomLevel;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Matrix } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('Matrix additional branch coverage', () => {
|
|
4
|
+
it('inverse throws when matrix is singular (pivotRow reaches rows)', () => {
|
|
5
|
+
const m = new Matrix([[0]], { rows: 1, cols: 1 });
|
|
6
|
+
expect(() => m.inverse()).toThrow(/singular/i);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('inverse hits division-by-zero guard (pivotElement===0) via get() monkeypatch', () => {
|
|
10
|
+
const m = new Matrix(
|
|
11
|
+
[
|
|
12
|
+
[1, 0],
|
|
13
|
+
[0, 1]
|
|
14
|
+
],
|
|
15
|
+
{ rows: 2, cols: 2 }
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
const origGet = (Matrix as any).prototype.get;
|
|
19
|
+
try {
|
|
20
|
+
(Matrix as any).prototype.get = function (row: number, col: number) {
|
|
21
|
+
// Make pivot search succeed (non-zero) but pivot element read as 0.
|
|
22
|
+
if (row === col) return 0;
|
|
23
|
+
return 1;
|
|
24
|
+
};
|
|
25
|
+
expect(() => m.inverse()).toThrow(/division by zero/i);
|
|
26
|
+
} finally {
|
|
27
|
+
(Matrix as any).prototype.get = origGet;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('inverse treats undefined elimination factor as 0 (factor===undefined branch)', () => {
|
|
32
|
+
const m = new Matrix(
|
|
33
|
+
[
|
|
34
|
+
[1, 0],
|
|
35
|
+
[0, 1]
|
|
36
|
+
],
|
|
37
|
+
{ rows: 2, cols: 2 }
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const origGet = (Matrix as any).prototype.get;
|
|
41
|
+
try {
|
|
42
|
+
(Matrix as any).prototype.get = function (row: number, col: number) {
|
|
43
|
+
// Provide real diagonal for pivoting
|
|
44
|
+
if (row === col) return 1;
|
|
45
|
+
// For elimination factor reads (j,i) when j!=i, return undefined
|
|
46
|
+
return undefined;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// Should still return something (we only care about branch execution)
|
|
50
|
+
const inv = m.inverse();
|
|
51
|
+
expect(inv?.rows).toBe(2);
|
|
52
|
+
expect(inv?.cols).toBe(2);
|
|
53
|
+
} finally {
|
|
54
|
+
(Matrix as any).prototype.get = origGet;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('_scaleRow and _addScaledRow coerce undefined multiply/add results to 0', () => {
|
|
59
|
+
const m = new Matrix(
|
|
60
|
+
[
|
|
61
|
+
[1, 2],
|
|
62
|
+
[3, 4]
|
|
63
|
+
],
|
|
64
|
+
{
|
|
65
|
+
rows: 2,
|
|
66
|
+
cols: 2,
|
|
67
|
+
multiplyFn: () => undefined as any,
|
|
68
|
+
addFn: () => undefined as any
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
// call protected helpers via any
|
|
73
|
+
(m as any)._scaleRow(0, 2);
|
|
74
|
+
expect(m.data[0][0]).toBe(0);
|
|
75
|
+
expect(m.data[0][1]).toBe(0);
|
|
76
|
+
|
|
77
|
+
(m as any)._addScaledRow(1, 0, 3);
|
|
78
|
+
expect(m.data[1][0]).toBe(0);
|
|
79
|
+
expect(m.data[1][1]).toBe(0);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -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
|
+
});
|