Skip to content

Commit 615d6d7

Browse files
committed
test(graphs): add tests for Dijkstra, DijkstraSmallestPath, FloydWarshall, KruskalMST, and DFS
1 parent 08d8c6b commit 615d6d7

File tree

6 files changed

+161
-0
lines changed

6 files changed

+161
-0
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { GraphUnweightedUndirected } from '../DepthFirstSearchIterative.js'
2+
3+
test('DFSIterative finds existing value and rejects non-existing', () => {
4+
const g = new GraphUnweightedUndirected()
5+
g.addEdge(1, 2)
6+
g.addEdge(2, 3)
7+
g.addEdge(2, 4)
8+
g.addEdge(3, 5)
9+
10+
expect(g.DFSIterative(5, 1)).toBe(true) // path 5->3->2->1 exists
11+
expect(g.DFSIterative(5, 100)).toBe(false) // 100 not in graph
12+
})
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { GraphUnweightedUndirected } from '../DepthFirstSearchRecursive.js'
2+
3+
test('DFSRecursive finds existing value and rejects non-existing', () => {
4+
const g = new GraphUnweightedUndirected()
5+
g.addEdge(1, 2)
6+
g.addEdge(2, 3)
7+
g.addEdge(2, 4)
8+
g.addEdge(3, 5)
9+
10+
expect(g.DFSRecursive(5, 1)).toBe(true) // path 5->3->2->1 exists
11+
expect(g.DFSRecursive(5, 100)).toBe(false) // 100 not in graph
12+
})

Graphs/test/Dijkstra.test.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { createGraph, djikstra } from '../Dijkstra.js'
2+
3+
// Undirected weighted graph
4+
// 0 --2-- 1 --3-- 3 --4-- 4
5+
// | | \
6+
// 5| 1 1
7+
// | |
8+
// 2 ---- 2 ---------
9+
// From source 0, shortest distances should be:
10+
// 0:0, 1:2, 2:3 (0->1->2), 3:4 (0->1->2->3), 4:8 (0->1->2->3->4)
11+
12+
test('Dijkstra shortest distances from source 0', () => {
13+
const V = 5
14+
const E = [
15+
[0, 1, 2],
16+
[0, 2, 5],
17+
[1, 2, 1],
18+
[1, 3, 3],
19+
[2, 3, 1],
20+
[3, 4, 4]
21+
]
22+
23+
const graph = createGraph(V, E)
24+
const dist = djikstra(graph, V, 0)
25+
26+
const expected = [0, 2, 3, 4, 8]
27+
for (let i = 0; i < V; i++) {
28+
expect(dist[i][0]).toBe(expected[i])
29+
}
30+
31+
// parent of source should be -1 by implementation
32+
expect(dist[0][1]).toBe(-1)
33+
})
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { solve } from '../DijkstraSmallestPath.js'
2+
3+
// Graph represented as adjacency object where graph[u][v] = weight
4+
// Example graph:
5+
// A --1-- B --2-- C
6+
// \3 \
7+
// \ 5
8+
// \--4-- D -----
9+
// Shortest distances from A: A:0, B:1, C:3 (A->B->C), D:4 (A->D)
10+
11+
test('DijkstraSmallestPath returns shortest distances and paths', () => {
12+
const graph = {
13+
A: { B: 1, D: 4 },
14+
B: { A: 1, C: 2 },
15+
C: { B: 2, D: 5 },
16+
D: { A: 4, C: 5 }
17+
}
18+
19+
const res = solve(graph, 'A')
20+
21+
expect(res.A.dist).toBe(0)
22+
expect(res.B.dist).toBe(1)
23+
expect(res.C.dist).toBe(3)
24+
expect(res.D.dist).toBe(4)
25+
26+
// Path arrays exclude the source by implementation (solutions[s] = [])
27+
expect([...res.B]).toEqual(['B'])
28+
expect([...res.C]).toEqual(['B', 'C'])
29+
expect([...res.D]).toEqual(['D'])
30+
})

Graphs/test/FloydWarshall.test.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { FloydWarshall } from '../FloydWarshall.js'
2+
3+
test('FloydWarshall computes all-pairs shortest paths', () => {
4+
const INF = Infinity
5+
const dist = [
6+
[0, 1, 2, INF],
7+
[1, 0, INF, INF],
8+
[2, INF, 0, 1],
9+
[INF, INF, 1, 0]
10+
]
11+
12+
const out = FloydWarshall(dist)
13+
expect(out).toEqual([
14+
[0, 1, 2, 3],
15+
[1, 0, 3, 4],
16+
[2, 3, 0, 1],
17+
[3, 4, 1, 0]
18+
])
19+
})

Graphs/test/KruskalMST.test.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { GraphWeightedUndirectedAdjacencyList } from '../KruskalMST.js'
2+
3+
function totalWeight(graph) {
4+
// connections: { u: { v: w, ... }, ... }
5+
let sum = 0
6+
const seen = new Set()
7+
for (const u of Object.keys(graph.connections)) {
8+
for (const v of Object.keys(graph.connections[u])) {
9+
const key = u < v ? `${u}-${v}` : `${v}-${u}`
10+
if (!seen.has(key)) {
11+
seen.add(key)
12+
sum += graph.connections[u][v]
13+
}
14+
}
15+
}
16+
return sum
17+
}
18+
19+
test('KruskalMST builds a minimum spanning tree', () => {
20+
const g = new GraphWeightedUndirectedAdjacencyList()
21+
// Graph:
22+
// 1-2(1), 2-3(2), 3-4(1), 3-5(100), 4-5(5)
23+
g.addEdge('1', '2', 1)
24+
g.addEdge('2', '3', 2)
25+
g.addEdge('3', '4', 1)
26+
g.addEdge('3', '5', 100) // heavy edge to be excluded
27+
g.addEdge('4', '5', 5)
28+
29+
const mst = g.KruskalMST()
30+
31+
// MST should have nodes: 1,2,3,4,5
32+
expect(Object.keys(mst.connections).sort()).toEqual(['1', '2', '3', '4', '5'])
33+
34+
// It should have exactly nodes-1 = 4 edges
35+
let edgeCount = 0
36+
const seen = new Set()
37+
for (const u of Object.keys(mst.connections)) {
38+
for (const v of Object.keys(mst.connections[u])) {
39+
const key = u < v ? `${u}-${v}` : `${v}-${u}`
40+
if (!seen.has(key)) {
41+
seen.add(key)
42+
edgeCount++
43+
}
44+
}
45+
}
46+
expect(edgeCount).toBe(4)
47+
48+
// Total weight should be 1 (1-2) + 2 (2-3) + 1 (3-4) + 5 (4-5) = 9
49+
// (Edge 3-5 with weight 100 must not be selected)
50+
expect(totalWeight(mst)).toBe(9)
51+
52+
// Ensure excluded heavy edge is not present
53+
expect(mst.connections['3']['5']).toBeUndefined()
54+
expect(mst.connections['5']['3']).toBeUndefined()
55+
})

0 commit comments

Comments
 (0)