graphs-adt
Version:
Graph data structure with path finding and traversing algorithms
238 lines (193 loc) • 6.02 kB
text/typescript
import { Graph } from './graph';
describe('Graph - datastructure', () => {
test('Add graph nodes and edge', () => {
const g = new Graph();
g.addNode('a');
expect(g.getNode('a').key).toEqual('a');
expect(g.getNode('a').neighbours).toEqual([]);
g.addNode('b');
g.addEdge('a', 'b', 5);
expect(g.getEdge('a', 'b')).toEqual(5);
expect(g.getNode('a').neighbours[0].key).toEqual('b');
});
});
describe('Graph - path finding (undirected)', () => {
const g = new Graph();
const nodes = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
const routes = [
[['c', 'a'], 2],
[['c', 'd'], 1],
[['c', 'f'], 4],
[['b', 'd'], 4],
[['b', 'e'], 7],
[['d', 'f'], 1],
[['d', 'g'], 1],
[['f', 'g'], 3],
[['g', 'h'], 4],
[['e', 'h'], 10],
];
nodes.forEach(node => g.addNode(node));
routes.forEach(([routes, distance]: any[]) => {
const [start, destination] = routes;
g.addEdge(start, destination, distance);
});
test('dijkstra - a', () => {
const expectedResults = {
a: { distance: 0, previous: null },
b: { distance: 7, previous: 'd' },
c: { distance: 2, previous: 'a' },
d: { distance: 3, previous: 'c' },
e: { distance: 14, previous: 'b' },
f: { distance: 4, previous: 'd' },
g: { distance: 4, previous: 'd' },
h: { distance: 8, previous: 'g' },
};
expect(g.dijkstra('a')).toEqual(expectedResults);
});
test('dijkstra - e', () => {
const expectedResults = {
a: { distance: 14, previous: 'c' },
b: { distance: 7, previous: 'e' },
c: { distance: 12, previous: 'd' },
d: { distance: 11, previous: 'b' },
e: { distance: 0, previous: null },
f: { distance: 12, previous: 'd' },
g: { distance: 12, previous: 'd' },
h: { distance: 10, previous: 'e' },
};
expect(g.dijkstra('e')).toEqual(expectedResults);
});
test('A -> F', () => {
const expected = ['a', 'c', 'd', 'f'];
const result = g.getPath('a', 'f');
expect(result).toEqual(expected);
});
test('A -> H', () => {
const expected = ['a', 'c', 'd', 'g', 'h'];
const result = g.getPath('a', 'h');
expect(result).toEqual(expected);
});
test('B -> H', () => {
const expected = ['b', 'd', 'g', 'h'];
const result = g.getPath('b', 'h');
expect(result).toEqual(expected);
});
test('H -> D', () => {
const expected = ['h', 'g', 'd'];
const result = g.getPath('h', 'd');
expect(result).toEqual(expected);
});
test('unknown source error', () => {
expect(() => g.getPath('z', 'd')).toThrowError('Could not find node z');
});
test('unknown destination error', () => {
expect(() => g.getPath('a', 'z')).toThrowError('Could not find node z');
});
});
describe('Graph - path finding (directed)', () => {
const g = new Graph({
directed: true,
});
const nodes = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
const routes = [
[['a', 'c'], 2],
[['c', 'd'], 1],
[['c', 'f'], 4],
[['b', 'd'], 4],
[['b', 'e'], 7],
[['d', 'f'], 1],
[['d', 'g'], 1],
[['f', 'g'], 3],
[['g', 'h'], 4],
[['e', 'h'], 10],
];
nodes.forEach(node => g.addNode(node));
routes.forEach(([routes, distance]: any[]) => {
const [start, destination] = routes;
g.addEdge(start, destination, distance);
});
test('dijkstra - a', () => {
const expectedResults = {
a: { distance: 0, previous: null },
b: { distance: Infinity, previous: null },
c: { distance: 2, previous: 'a' },
d: { distance: 3, previous: 'c' },
e: { distance: Infinity, previous: null },
f: { distance: 4, previous: 'd' },
g: { distance: 4, previous: 'd' },
h: { distance: 8, previous: 'g' },
};
expect(g.dijkstra('a')).toEqual(expectedResults);
});
test('dijkstra - e', () => {
const expectedResults = {
a: { distance: Infinity, previous: null },
b: { distance: Infinity, previous: null },
c: { distance: Infinity, previous: null },
d: { distance: Infinity, previous: null },
e: { distance: 0, previous: null },
f: { distance: Infinity, previous: null },
g: { distance: Infinity, previous: null },
h: { distance: 10, previous: 'e' },
};
expect(g.dijkstra('e')).toEqual(expectedResults);
});
test('A -> F', () => {
const expected = ['a', 'c', 'd', 'f'];
const result = g.getPath('a', 'f');
expect(result).toEqual(expected);
});
test('A -> H', () => {
const expected = ['a', 'c', 'd', 'g', 'h'];
const result = g.getPath('a', 'h');
expect(result).toEqual(expected);
});
test('B -> H', () => {
const expected = ['b', 'd', 'g', 'h'];
const result = g.getPath('b', 'h');
expect(result).toEqual(expected);
});
test('H -> D', () => {
const expected: string[] = [];
const result = g.getPath('h', 'd');
expect(result).toEqual(expected);
});
test('unknown source error', () => {
expect(() => g.getPath('z', 'd')).toThrowError('Could not find node z');
});
test('unknown destination error', () => {
expect(() => g.getPath('a', 'z')).toThrowError('Could not find node z');
});
});
describe('Graph - traversing and searching', () => {
const graph = new Graph();
const nodes = ['a', 'b', 'c', 'd', 'e', 'f'];
const edges = [
['a', 'b'],
['a', 'e'],
['a', 'f'],
['b', 'd'],
['b', 'e'],
['c', 'b'],
['d', 'c'],
['d', 'e'],
];
nodes.map(node => graph.addNode(node));
edges.map(nodes => graph.addEdge(nodes[0], nodes[1], 0));
test('bredth first search', () => {
const order = ['a', 'b', 'e', 'f', 'd', 'c'];
let i = 0;
graph.bfs('a', (node: any) => {
expect(node.key).toEqual(order[i]);
i++;
});
});
test('depth first search', () => {
const order = ['a', 'b', 'd', 'c', 'e', 'f'];
let i = 0;
graph.dfs('a', (node: any) => {
expect(node.key).toEqual(order[i]);
i++;
});
});
});