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,62 @@
|
|
|
1
|
+
import { DirectedGraph, DirectedVertex, AbstractVertex } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('AbstractGraph extra branch coverage via DirectedGraph', () => {
|
|
4
|
+
it('getVertex(missingKey) returns undefined (covers `|| undefined` branch)', () => {
|
|
5
|
+
const g = new DirectedGraph();
|
|
6
|
+
expect(g.getVertex('MISSING' as any)).toBeUndefined();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('addEdge(srcKey,destKey) returns false when either vertex is missing', () => {
|
|
10
|
+
const g = new DirectedGraph();
|
|
11
|
+
g.addVertex('A');
|
|
12
|
+
expect(g.addEdge('A', 'B' as any)).toBe(false);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('addEdge(srcVertex,destVertex) converts AbstractVertex endpoints to keys', () => {
|
|
16
|
+
const g = new DirectedGraph();
|
|
17
|
+
const a = new DirectedVertex('A');
|
|
18
|
+
const b = new DirectedVertex('B');
|
|
19
|
+
g.addVertex(a);
|
|
20
|
+
g.addVertex(b);
|
|
21
|
+
|
|
22
|
+
// goes through addEdge(srcOrEdge, dest) branch where dest is AbstractVertex
|
|
23
|
+
expect(g.addEdge(a as unknown as AbstractVertex<any>, b as unknown as AbstractVertex<any>, 2)).toBe(true);
|
|
24
|
+
expect(g.hasEdge('A', 'B')).toBe(true);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('addEdge throws when dest is not a Vertex or vertex key', () => {
|
|
28
|
+
const g = new DirectedGraph();
|
|
29
|
+
g.addVertex('A');
|
|
30
|
+
expect(() => g.addEdge('A' as any, { bad: true } as any)).toThrow(/dest must be a Vertex or vertex key/i);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('setEdgeWeight returns false when edge does not exist', () => {
|
|
34
|
+
const g = new DirectedGraph();
|
|
35
|
+
g.addVertex('A');
|
|
36
|
+
g.addVertex('B');
|
|
37
|
+
expect(g.setEdgeWeight('A', 'B', 123)).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('dijkstraWithoutHeap uses default args and also covers early-stop (dest + getMinDist + genPaths)', () => {
|
|
41
|
+
const g = new DirectedGraph();
|
|
42
|
+
g.addVertex('A');
|
|
43
|
+
g.addVertex('B');
|
|
44
|
+
g.addVertex('C');
|
|
45
|
+
|
|
46
|
+
g.addEdge('A', 'B', 1);
|
|
47
|
+
g.addEdge('B', 'C', 2);
|
|
48
|
+
|
|
49
|
+
// default args: dest undefined, getMinDist/genPaths false
|
|
50
|
+
const base = g.dijkstraWithoutHeap('A');
|
|
51
|
+
expect(base).toBeDefined();
|
|
52
|
+
|
|
53
|
+
const res = g.dijkstraWithoutHeap('A', 'C', true, true);
|
|
54
|
+
// Implementation detail: DirectedGraph may normalize weights; here we only assert it computed a finite minDist.
|
|
55
|
+
expect(typeof res?.minDist).toBe('number');
|
|
56
|
+
expect(Number.isFinite(res!.minDist)).toBe(true);
|
|
57
|
+
// genPaths=true should generate a path for each vertex
|
|
58
|
+
expect(res?.paths.length).toBe(3);
|
|
59
|
+
// minPath should be some path ending at the destination when implementation chooses to store it.
|
|
60
|
+
expect(Array.isArray(res?.minPath)).toBe(true);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { DirectedGraph } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('DirectedGraph remaining branch coverage (batch 2)', () => {
|
|
4
|
+
it('createEdge falls back to weight=1 when weight and defaultEdgeWeight are both undefined', () => {
|
|
5
|
+
const g = new DirectedGraph<string, any>();
|
|
6
|
+
const e = g.createEdge('a', 'b');
|
|
7
|
+
expect(e.weight).toBe(1);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('deleteEdgeSrcToDest hits "[0] || undefined" fallback when inEdgeMap exists but no matching edge', () => {
|
|
11
|
+
const g = new DirectedGraph<string, any>();
|
|
12
|
+
g.addVertex('a');
|
|
13
|
+
g.addVertex('b');
|
|
14
|
+
g.addVertex('c');
|
|
15
|
+
|
|
16
|
+
// Only add c->b, so b has an inEdge that does not match src=a
|
|
17
|
+
g.addEdge('c', 'b');
|
|
18
|
+
|
|
19
|
+
const removed = (g as any).deleteEdgeSrcToDest('a', 'b');
|
|
20
|
+
expect(removed).toBeUndefined();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('deleteEdgesBetween skips body when v1 or v2 is falsy (covers if(v1&&v2) false branch)', () => {
|
|
24
|
+
const g = new DirectedGraph<string, any>();
|
|
25
|
+
expect(g.deleteEdgesBetween(undefined as any, 'x' as any)).toEqual([]);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('topologicalSort("key") covers mapping else-arm when sorted contains a raw key (not a DirectedVertex)', () => {
|
|
29
|
+
const g = new DirectedGraph<string, any>();
|
|
30
|
+
g.addVertex('a');
|
|
31
|
+
|
|
32
|
+
// Corrupt vertexMap to include a non-DirectedVertex entry value.
|
|
33
|
+
(g as any)._vertexMap.set('b', 'b');
|
|
34
|
+
|
|
35
|
+
const sorted = g.topologicalSort('key') as any[];
|
|
36
|
+
expect(sorted).toContain('b');
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { DirectedGraph } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('DirectedGraph remaining branch coverage (batch 3)', () => {
|
|
4
|
+
it('createEdge uses final fallback weight=1 when defaultEdgeWeight is explicitly undefined', () => {
|
|
5
|
+
const g = new DirectedGraph<string, any>();
|
|
6
|
+
|
|
7
|
+
// Force options.defaultEdgeWeight to be undefined so `weight ?? defaultEdgeWeight ?? 1` uses the final `1`.
|
|
8
|
+
(g as any).options.defaultEdgeWeight = undefined;
|
|
9
|
+
|
|
10
|
+
const e = g.createEdge('a', 'b');
|
|
11
|
+
expect(e.weight).toBe(1);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('deleteEdgesBetween pushes both directions when both edges exist (covers v2ToV1 truthy branch)', () => {
|
|
15
|
+
const g = new DirectedGraph<string, any>();
|
|
16
|
+
g.addVertex('a');
|
|
17
|
+
g.addVertex('b');
|
|
18
|
+
|
|
19
|
+
g.addEdge('a', 'b');
|
|
20
|
+
g.addEdge('b', 'a');
|
|
21
|
+
|
|
22
|
+
const removed = g.deleteEdgesBetween('a', 'b');
|
|
23
|
+
expect(removed).toHaveLength(2);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { DirectedEdge, DirectedGraph } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('DirectedGraph additional branch coverage', () => {
|
|
4
|
+
it('static fromKeys/fromEntries build graphs (and exercises vertexValueInitializer body)', () => {
|
|
5
|
+
const g1 = DirectedGraph.fromKeys(['a', 'b']);
|
|
6
|
+
expect(g1.hasVertex('a')).toBe(true);
|
|
7
|
+
// value initializer behavior may vary; key must exist.
|
|
8
|
+
expect(g1.getVertex('b')?.key).toBe('b');
|
|
9
|
+
|
|
10
|
+
// Force execution of the initializer function body (coverage line ~212).
|
|
11
|
+
const init = (g1 as any).options?.vertexValueInitializer;
|
|
12
|
+
if (typeof init === 'function') {
|
|
13
|
+
expect(init('z')).toBe('z');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const g2 = DirectedGraph.fromEntries([
|
|
17
|
+
['x', 1],
|
|
18
|
+
['y', 2]
|
|
19
|
+
]);
|
|
20
|
+
expect(g2.getVertex('x')?.value).toBe(1);
|
|
21
|
+
expect(g2.getVertex('y')?.value).toBe(2);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('deleteEdge(srcKey) returns undefined when destVertexKey is not a key', () => {
|
|
25
|
+
const g = new DirectedGraph<string, number>();
|
|
26
|
+
g.addVertex('a');
|
|
27
|
+
g.addVertex('b');
|
|
28
|
+
g.addEdge('a', 'b');
|
|
29
|
+
|
|
30
|
+
expect(g.deleteEdge('a' as any, undefined as any)).toBeUndefined();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('outgoingEdgesOf returns [] when target missing', () => {
|
|
34
|
+
const g = new DirectedGraph<string, number>();
|
|
35
|
+
expect(g.outgoingEdgesOf('missing' as any)).toEqual([]);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('getDestinations(undefined) returns []', () => {
|
|
39
|
+
const g = new DirectedGraph<string, number>();
|
|
40
|
+
expect(g.getDestinations(undefined)).toEqual([]);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('getEndsOfEdge returns undefined when edge missing, and hits the else-branch when endpoint lookup fails', () => {
|
|
44
|
+
const g = new DirectedGraph<string, number>();
|
|
45
|
+
g.addVertex('a');
|
|
46
|
+
g.addVertex('b');
|
|
47
|
+
|
|
48
|
+
const eMissing = new DirectedEdge('a', 'b', 1);
|
|
49
|
+
expect(g.getEndsOfEdge(eMissing as any)).toBeUndefined();
|
|
50
|
+
|
|
51
|
+
// Force hasEdge=true but _getVertex failure to hit the `else { return undefined; }` branch (coverage line ~568).
|
|
52
|
+
const origHasEdge = (g as any).hasEdge;
|
|
53
|
+
const origGetVertex = (g as any)._getVertex;
|
|
54
|
+
(g as any).hasEdge = () => true;
|
|
55
|
+
(g as any)._getVertex = () => undefined;
|
|
56
|
+
try {
|
|
57
|
+
expect(g.getEndsOfEdge(new DirectedEdge('a', 'b', 1) as any)).toBeUndefined();
|
|
58
|
+
} finally {
|
|
59
|
+
(g as any).hasEdge = origHasEdge;
|
|
60
|
+
(g as any)._getVertex = origGetVertex;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('_addEdge returns false when vertices are missing, and when _getVertex returns undefined', () => {
|
|
65
|
+
const g = new DirectedGraph<string, number>();
|
|
66
|
+
|
|
67
|
+
// Missing vertices => early return false
|
|
68
|
+
expect((g as any)._addEdge(new DirectedEdge('a', 'b', 1))).toBe(false);
|
|
69
|
+
|
|
70
|
+
g.addVertex('a');
|
|
71
|
+
g.addVertex('b');
|
|
72
|
+
|
|
73
|
+
const origGetVertex = (g as any)._getVertex;
|
|
74
|
+
(g as any)._getVertex = () => undefined;
|
|
75
|
+
try {
|
|
76
|
+
// hasVertex() is still true, but srcVertex/destVertex become undefined => else return false
|
|
77
|
+
expect((g as any)._addEdge(new DirectedEdge('a', 'b', 1))).toBe(false);
|
|
78
|
+
} finally {
|
|
79
|
+
(g as any)._getVertex = origGetVertex;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { MapGraph } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('MapGraph remaining branch coverage', () => {
|
|
4
|
+
it('_createInstance falls back to this.originCoord/this.bottomRight when options omit them (?? rhs)', () => {
|
|
5
|
+
const g = new MapGraph<number, number>([10, 20], [30, 40]);
|
|
6
|
+
|
|
7
|
+
// No-arg call hits (options || {}) rhs.
|
|
8
|
+
const inst = (g as any)._createInstance();
|
|
9
|
+
expect(inst).toBeInstanceOf(MapGraph);
|
|
10
|
+
|
|
11
|
+
// Empty options hits originCoord/bottomRight ?? rhs.
|
|
12
|
+
const instEmpty = (g as any)._createInstance({});
|
|
13
|
+
expect(instEmpty).toBeInstanceOf(MapGraph);
|
|
14
|
+
|
|
15
|
+
// Verify fallbacks were used.
|
|
16
|
+
expect((inst as any).originCoord).toEqual([10, 20]);
|
|
17
|
+
expect((inst as any).bottomRight).toEqual([30, 40]);
|
|
18
|
+
|
|
19
|
+
const inst2 = (g as any)._createInstance({ bottomRight: undefined });
|
|
20
|
+
expect((inst2 as any).bottomRight).toEqual([30, 40]);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { UndirectedGraph } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('UndirectedGraph remaining branch coverage (batch 2)', () => {
|
|
4
|
+
it('createEdge uses final fallback weight=1 when defaultEdgeWeight is explicitly undefined', () => {
|
|
5
|
+
const g = new UndirectedGraph<string, any>();
|
|
6
|
+
(g as any).options.defaultEdgeWeight = undefined;
|
|
7
|
+
|
|
8
|
+
const e = g.createEdge('a', 'b');
|
|
9
|
+
expect(e.weight).toBe(1);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('getEndsOfEdge hits else-return branch when hasEdge=true but endpoint vertex is missing', () => {
|
|
13
|
+
const g = new UndirectedGraph<string, any>();
|
|
14
|
+
g.addVertex('a');
|
|
15
|
+
g.addVertex('b');
|
|
16
|
+
|
|
17
|
+
const edge = g.createEdge('a', 'b');
|
|
18
|
+
|
|
19
|
+
const origHasEdge = (g as any).hasEdge;
|
|
20
|
+
const origGetVertex = (g as any)._getVertex;
|
|
21
|
+
|
|
22
|
+
(g as any).hasEdge = () => true;
|
|
23
|
+
(g as any)._getVertex = (key: any) => {
|
|
24
|
+
if (key === 'a') return undefined;
|
|
25
|
+
return origGetVertex.call(g, key);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
expect(g.getEndsOfEdge(edge as any)).toBeUndefined();
|
|
30
|
+
} finally {
|
|
31
|
+
(g as any).hasEdge = origHasEdge;
|
|
32
|
+
(g as any)._getVertex = origGetVertex;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { UndirectedEdge, UndirectedGraph } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('UndirectedGraph additional branch coverage', () => {
|
|
4
|
+
it('createEdge falls back to hard-coded weight=1 when weight and defaultEdgeWeight are both undefined', () => {
|
|
5
|
+
const g = new UndirectedGraph<string, any>();
|
|
6
|
+
const e = g.createEdge('a', 'b');
|
|
7
|
+
expect(e.weight).toBe(1);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('getEdge returns undefined via edgeMap falsy branch when vertices exist but no edgeMap entry', () => {
|
|
11
|
+
const g = new UndirectedGraph<string, any>();
|
|
12
|
+
g.addVertex('a');
|
|
13
|
+
g.addVertex('b');
|
|
14
|
+
|
|
15
|
+
// No edge inserted => _edgeMap.get(vertex1) is undefined => edgeMap becomes undefined
|
|
16
|
+
expect(g.getEdge('a', 'b')).toBeUndefined();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('deleteEdgeBetween executes "|| undefined" fallback when v1Edges exists but no matching edge is found', () => {
|
|
20
|
+
const g = new UndirectedGraph<string, any>();
|
|
21
|
+
g.addVertex('a');
|
|
22
|
+
g.addVertex('b');
|
|
23
|
+
g.addVertex('c');
|
|
24
|
+
|
|
25
|
+
// Create a--c edge so v1Edges exists for a, but there is no a--b edge.
|
|
26
|
+
g.addEdge('a', 'c');
|
|
27
|
+
|
|
28
|
+
expect(g.deleteEdgeBetween('a', 'b')).toBeUndefined();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('deleteEdge(key, missingOtherKey) returns undefined via early return branch', () => {
|
|
32
|
+
const g = new UndirectedGraph<string, any>();
|
|
33
|
+
g.addVertex('a');
|
|
34
|
+
g.addVertex('b');
|
|
35
|
+
g.addEdge('a', 'b');
|
|
36
|
+
|
|
37
|
+
expect(g.deleteEdge('a' as any, undefined as any)).toBeUndefined();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('deleteVertex(vertexInstance) covers non-key input branch', () => {
|
|
41
|
+
const g = new UndirectedGraph<string, any>();
|
|
42
|
+
g.addVertex('a');
|
|
43
|
+
|
|
44
|
+
const v = g.getVertex('a')!;
|
|
45
|
+
expect(g.deleteVertex(v as any)).toBe(true);
|
|
46
|
+
expect(g.hasVertex('a')).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('degreeOf returns 0 via "|| 0" fallback when vertex exists but has no incident edges', () => {
|
|
50
|
+
const g = new UndirectedGraph<string, any>();
|
|
51
|
+
g.addVertex('solo');
|
|
52
|
+
expect(g.degreeOf('solo')).toBe(0);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('getEndsOfEdge returns undefined when hasEdge is true but endpoint lookup fails', () => {
|
|
56
|
+
const g = new UndirectedGraph<string, any>();
|
|
57
|
+
g.addVertex('a');
|
|
58
|
+
g.addVertex('b');
|
|
59
|
+
g.addEdge('a', 'b');
|
|
60
|
+
|
|
61
|
+
const e = g.getEdge('a', 'b')!;
|
|
62
|
+
|
|
63
|
+
// Corrupt internal vertex map so hasEdge stays true but _getVertex fails.
|
|
64
|
+
const vm = (g as any)._vertexMap as Map<any, any>;
|
|
65
|
+
const saved = vm.get('b');
|
|
66
|
+
vm.delete('b');
|
|
67
|
+
try {
|
|
68
|
+
expect(g.getEndsOfEdge(e as any)).toBeUndefined();
|
|
69
|
+
} finally {
|
|
70
|
+
vm.set('b', saved);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('_addEdge returns false when _getVertex yields undefined for an endpoint (covers endVertex===undefined branch)', () => {
|
|
75
|
+
const g = new UndirectedGraph<string, any>();
|
|
76
|
+
g.addVertex('a');
|
|
77
|
+
g.addVertex('b');
|
|
78
|
+
|
|
79
|
+
const origGetVertex = (g as any)._getVertex;
|
|
80
|
+
(g as any)._getVertex = () => undefined;
|
|
81
|
+
try {
|
|
82
|
+
expect((g as any)._addEdge(new UndirectedEdge('a', 'b', 1) as any)).toBe(false);
|
|
83
|
+
} finally {
|
|
84
|
+
(g as any)._getVertex = origGetVertex;
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { HashMap, LinkedHashMap } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('HashMap / LinkedHashMap additional branch coverage', () => {
|
|
4
|
+
it('HashMap.setHashFn returns early when same fn is passed (covers _hashFn===fn branch)', () => {
|
|
5
|
+
const m = new HashMap<any, any>();
|
|
6
|
+
const fn = (m as any)._hashFn;
|
|
7
|
+
expect(m.setHashFn(fn)).toBe(m);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('HashMap._getNoObjKey covers symbol-key path and non-(string/number/symbol) path', () => {
|
|
11
|
+
const m = new HashMap<any, any>();
|
|
12
|
+
|
|
13
|
+
// symbol -> hits (..&&..&& keyType!=='symbol') final operand false arm
|
|
14
|
+
const s = Symbol('k');
|
|
15
|
+
m.set(s as any, 1);
|
|
16
|
+
expect(m.get(s as any)).toBe(1);
|
|
17
|
+
|
|
18
|
+
// boolean -> forces _hashFn(key) path
|
|
19
|
+
m.set(true as any, 2);
|
|
20
|
+
expect(m.get(true as any)).toBe(2);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('LinkedHashMap.toEntryFn default throws when rawElement is not an entry (covers toEntryFn error)', () => {
|
|
24
|
+
const m = new LinkedHashMap<number, number, any>();
|
|
25
|
+
expect(() => (m as any).toEntryFn({ k: 1, v: 2 })).toThrow(/provide `options\.toEntryFn`/i);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('LinkedHashMap set/get/delete branches for weak keys and missing nodes', () => {
|
|
29
|
+
const m = new LinkedHashMap<object, number>();
|
|
30
|
+
const obj = {};
|
|
31
|
+
|
|
32
|
+
// insert weak key => new node
|
|
33
|
+
m.set(obj, 1);
|
|
34
|
+
expect(m.get(obj)).toBe(1);
|
|
35
|
+
|
|
36
|
+
// update existing weak key => else-if(node) branch
|
|
37
|
+
m.set(obj, 2);
|
|
38
|
+
expect(m.get(obj)).toBe(2);
|
|
39
|
+
|
|
40
|
+
// get missing weak key => node ? node.value : undefined false arm
|
|
41
|
+
expect(m.get({} as any)).toBeUndefined();
|
|
42
|
+
|
|
43
|
+
// delete missing weak key => if(!node) return false
|
|
44
|
+
expect(m.delete({} as any)).toBe(false);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('LinkedHashMap.deleteWhere covers weak-key delete path and noObj delete path and not-found return false', () => {
|
|
48
|
+
const m = new LinkedHashMap<any, number>();
|
|
49
|
+
const obj = {};
|
|
50
|
+
m.set('a', 1);
|
|
51
|
+
m.set(obj, 2);
|
|
52
|
+
|
|
53
|
+
// deleteWhere hits predicate true for weak key => _objMap.delete branch
|
|
54
|
+
expect(m.deleteWhere((k: any) => typeof k === 'object')).toBe(true);
|
|
55
|
+
expect(m.has(obj)).toBe(false);
|
|
56
|
+
|
|
57
|
+
// deleteWhere hits predicate true for noObj key => delete _noObjMap[hash]
|
|
58
|
+
expect(m.deleteWhere((k: any) => k === 'a')).toBe(true);
|
|
59
|
+
expect(m.has('a')).toBe(false);
|
|
60
|
+
|
|
61
|
+
// not found
|
|
62
|
+
expect(m.deleteWhere(() => false)).toBe(false);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { LinkedHashMap } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('LinkedHashMap toEntryFn remaining branch coverage', () => {
|
|
4
|
+
it('default toEntryFn returns tuple when rawElement is an entry (isEntry true branch)', () => {
|
|
5
|
+
const m = new LinkedHashMap<number, string>();
|
|
6
|
+
const fn = m.toEntryFn as (raw: any) => [number, string];
|
|
7
|
+
expect(fn([1, 'a'])).toEqual([1, 'a']);
|
|
8
|
+
});
|
|
9
|
+
});
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { Heap, FibonacciHeap } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('Heap / FibonacciHeap misc branch coverage', () => {
|
|
4
|
+
it('Heap.deleteBy covers not-found, idx=0 poll, idx=last pop, idx=middle splice paths', () => {
|
|
5
|
+
const h = new Heap<number>();
|
|
6
|
+
h.add(3);
|
|
7
|
+
h.add(1);
|
|
8
|
+
h.add(2);
|
|
9
|
+
|
|
10
|
+
expect(h.deleteBy(() => false)).toBe(false); // idx stays -1
|
|
11
|
+
|
|
12
|
+
// idx === 0
|
|
13
|
+
expect(h.deleteBy(x => x === h.peek())).toBe(true);
|
|
14
|
+
|
|
15
|
+
// ensure at least 2 elems again
|
|
16
|
+
h.add(4);
|
|
17
|
+
h.add(5);
|
|
18
|
+
|
|
19
|
+
// idx === last
|
|
20
|
+
const last = (h as any).elements[(h as any).elements.length - 1];
|
|
21
|
+
expect(h.deleteBy(x => x === last)).toBe(true);
|
|
22
|
+
|
|
23
|
+
// idx in middle
|
|
24
|
+
const mid = (h as any).elements[1];
|
|
25
|
+
expect(h.deleteBy(x => x === mid)).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('Heap.filter covers thisArg branch and else(i++) branch', () => {
|
|
29
|
+
const h = new Heap<number>();
|
|
30
|
+
h.add(1);
|
|
31
|
+
h.add(2);
|
|
32
|
+
h.add(3);
|
|
33
|
+
|
|
34
|
+
const ctx = { ok: true };
|
|
35
|
+
const out = h.filter(function (this: any, x: number) {
|
|
36
|
+
// keep only one element so the else branch runs too
|
|
37
|
+
return this.ok && x === 2;
|
|
38
|
+
}, ctx);
|
|
39
|
+
|
|
40
|
+
expect(out.toArray()).toEqual([2]);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('Heap.map throws when comparator missing, and uses thisArg branch when provided', () => {
|
|
44
|
+
const h = new Heap<number>();
|
|
45
|
+
h.add(1);
|
|
46
|
+
h.add(2);
|
|
47
|
+
|
|
48
|
+
expect(() => h.map(x => ({ x }), {} as any)).toThrow(/requires options\.comparator/i);
|
|
49
|
+
|
|
50
|
+
const ctx = { mul: 10 };
|
|
51
|
+
const mapped = h.map(
|
|
52
|
+
function (this: any, x: number) {
|
|
53
|
+
return x * this.mul;
|
|
54
|
+
},
|
|
55
|
+
{ comparator: (a: number, b: number) => a - b },
|
|
56
|
+
ctx
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
expect(mapped.peek()).toBe(10);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('Heap.mapSame covers thisArg branch', () => {
|
|
63
|
+
const h = new Heap<number>();
|
|
64
|
+
h.add(1);
|
|
65
|
+
h.add(3);
|
|
66
|
+
|
|
67
|
+
const ctx = { add: 7 };
|
|
68
|
+
const out = h.mapSame(function (this: any, x: number) {
|
|
69
|
+
return x + this.add;
|
|
70
|
+
}, ctx);
|
|
71
|
+
|
|
72
|
+
expect(out.peek()).toBe(8);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('Heap._createLike default-arg path can be called via (heap as any)._createLike()', () => {
|
|
76
|
+
const h = new Heap<number>();
|
|
77
|
+
const like = (h as any)._createLike();
|
|
78
|
+
expect(like.size).toBe(0);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('FibonacciHeap constructor throws when comparator is not a function', () => {
|
|
82
|
+
expect(() => new FibonacciHeap<number>(123 as any)).toThrow(/comparator must be a function/i);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('FibonacciHeap.consumeLinkedList(undefined) returns [] (covers !head guard)', () => {
|
|
86
|
+
const fh = new FibonacciHeap<number>();
|
|
87
|
+
expect(fh.consumeLinkedList(undefined)).toEqual([]);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('FibonacciHeap.merge covers empty-merge early return, empty-this adopt-root, and non-empty root-merge', () => {
|
|
91
|
+
const a = new FibonacciHeap<number>();
|
|
92
|
+
const b = new FibonacciHeap<number>();
|
|
93
|
+
|
|
94
|
+
// empty merge early return
|
|
95
|
+
a.merge(b);
|
|
96
|
+
expect(a.size).toBe(0);
|
|
97
|
+
|
|
98
|
+
// empty-this adopt-root
|
|
99
|
+
b.add(5);
|
|
100
|
+
a.merge(b);
|
|
101
|
+
expect(a.size).toBe(1);
|
|
102
|
+
|
|
103
|
+
// non-empty root-merge + min update paths
|
|
104
|
+
const c = new FibonacciHeap<number>();
|
|
105
|
+
c.add(1);
|
|
106
|
+
c.add(10);
|
|
107
|
+
a.merge(c);
|
|
108
|
+
expect(a.peek()).toBe(1);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Heap } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('Heap remaining branch coverage', () => {
|
|
4
|
+
it('Heap.map with options undefined hits (options ?? {}) path and throws for missing comparator', () => {
|
|
5
|
+
const h = new Heap<number>();
|
|
6
|
+
h.add(1);
|
|
7
|
+
expect(() => (h as any).map((x: number) => x, undefined)).toThrow(/requires options\.comparator/i);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('Heap.mapSame without thisArg hits thisArg===undefined branch', () => {
|
|
11
|
+
const h = new Heap<number>();
|
|
12
|
+
h.add(1);
|
|
13
|
+
h.add(2);
|
|
14
|
+
const out = h.mapSame(x => x * 2);
|
|
15
|
+
expect(out.toArray().sort((a, b) => a - b)).toEqual([2, 4]);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('Heap default comparator throws when comparing object types', () => {
|
|
19
|
+
const h = new Heap<any>();
|
|
20
|
+
expect(() => (h as any)._DEFAULT_COMPARATOR({}, 1)).toThrow(TypeError);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { MaxHeap } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Coverage-focused test for MaxHeap comparator branches.
|
|
5
|
+
* Keep existing @example tests intact.
|
|
6
|
+
*/
|
|
7
|
+
describe('MaxHeap coverage', () => {
|
|
8
|
+
it('orders numbers as a max-heap (a<b / a>b / equal branches)', () => {
|
|
9
|
+
const h = new MaxHeap<number>();
|
|
10
|
+
|
|
11
|
+
h.add(2);
|
|
12
|
+
h.add(1);
|
|
13
|
+
h.add(3);
|
|
14
|
+
h.add(3); // equal branch exercised during comparisons
|
|
15
|
+
|
|
16
|
+
expect(h.peek()).toBe(3);
|
|
17
|
+
expect(h.poll()).toBe(3);
|
|
18
|
+
expect(h.poll()).toBe(3);
|
|
19
|
+
expect(h.poll()).toBe(2);
|
|
20
|
+
expect(h.poll()).toBe(1);
|
|
21
|
+
expect(h.poll()).toBe(undefined);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('throws when comparing object types without custom comparator', () => {
|
|
25
|
+
const h = new MaxHeap<any>();
|
|
26
|
+
h.add({ k: 1 });
|
|
27
|
+
expect(() => h.add({ k: 2 })).toThrow(TypeError);
|
|
28
|
+
});
|
|
29
|
+
});
|
package/test/unit/data-structures/linked-list/doubly-linked-list.more-branches.coverage.test.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { DoublyLinkedList, DoublyLinkedListNode } from '../../../../src';
|
|
2
|
+
|
|
3
|
+
describe('DoublyLinkedList additional branch coverage', () => {
|
|
4
|
+
it('unshiftMany uses toElementFn branch when provided', () => {
|
|
5
|
+
const l = new DoublyLinkedList<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('getNode(undefined) returns undefined (covers early return)', () => {
|
|
13
|
+
const l = new DoublyLinkedList<number>();
|
|
14
|
+
l.pushMany([1, 2]);
|
|
15
|
+
expect(l.getNode(undefined)).toBeUndefined();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('setAt returns false when node does not exist', () => {
|
|
19
|
+
const l = new DoublyLinkedList<number>();
|
|
20
|
+
expect(l.setAt(0, 1)).toBe(false);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('search returns value when predicate matches (covers predicate(current) true branch)', () => {
|
|
24
|
+
const l = new DoublyLinkedList<number>();
|
|
25
|
+
l.pushMany([1, 2, 3]);
|
|
26
|
+
expect(l.search(n => n.value === 2)).toBe(2);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('mapSame covers both thisArg branches', () => {
|
|
30
|
+
const l = new DoublyLinkedList<number>();
|
|
31
|
+
l.pushMany([1, 2]);
|
|
32
|
+
|
|
33
|
+
// thisArg === undefined arm
|
|
34
|
+
expect(l.mapSame(v => v + 1).toArray()).toEqual([2, 3]);
|
|
35
|
+
|
|
36
|
+
// thisArg provided arm
|
|
37
|
+
const ctx = { add: 10 };
|
|
38
|
+
expect(
|
|
39
|
+
l
|
|
40
|
+
.mapSame(function (this: any, v: number) {
|
|
41
|
+
return v + this.add;
|
|
42
|
+
}, ctx)
|
|
43
|
+
.toArray()
|
|
44
|
+
).toEqual([11, 12]);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('_ensureNode returns the same node when input is a node (covers isNode true branch)', () => {
|
|
48
|
+
const l = new DoublyLinkedList<number>();
|
|
49
|
+
l.pushMany([1, 3]);
|
|
50
|
+
|
|
51
|
+
const existing = l.getNodeAt(0)!;
|
|
52
|
+
const newNode = new DoublyLinkedListNode(2);
|
|
53
|
+
|
|
54
|
+
// addAfter calls _ensureNode(newElementOrNode)
|
|
55
|
+
expect(l.addAfter(existing, newNode)).toBe(true);
|
|
56
|
+
expect(l.toArray()).toEqual([1, 2, 3]);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('_ensurePredicate covers isNode(target) branch via search(node)', () => {
|
|
60
|
+
const l = new DoublyLinkedList<number>();
|
|
61
|
+
l.pushMany([1, 2, 3]);
|
|
62
|
+
|
|
63
|
+
const target = l.getNodeAt(1)!;
|
|
64
|
+
expect(l.search(target)).toBe(2);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('_createLike default-arg path can be called with no args', () => {
|
|
68
|
+
const l = new DoublyLinkedList<number>();
|
|
69
|
+
const like = (l as any)._createLike();
|
|
70
|
+
expect(like.length).toBe(0);
|
|
71
|
+
});
|
|
72
|
+
});
|