/* eslint-env mocha */
const Graph = require('../../src').datastructures.Graph;
const assert = require('assert');

describe('Graph', () => {
  it('should be empty when initializing undirected graph', () => {
    const inst = new Graph();

    assert(inst.isEmpty());
    assert.equal(inst.size, 0);
    assert.deepStrictEqual(inst.vertices, []);
  });

  it('should create a graph', () => {
    const inst = new Graph();

    inst.addVertex(1);
    inst.addVertex(2);
    inst.addVertex(3);
    inst.addVertex(4);
    inst.addVertex(5);

    assert.throws(() => inst.addVertex(1));

    inst.addEdge(1, 2, 1);
    inst.addEdge(1, 3, 1);
    inst.addEdge(1, 5, 1);
    inst.addEdge(3, 4, 1);
    inst.addEdge(1, 5, 1);

    assert(!inst.isEmpty());
    assert.equal(inst.size, 5);
    assert.deepStrictEqual(inst.vertices, ['1', '2', '3', '4', '5']);
  });

  it('should get edge weight', () => {
    const inst = new Graph();

    inst.addVertex(1);
    inst.addVertex(2);
    inst.addVertex(3);
    inst.addVertex(4);
    inst.addVertex(5);

    inst.addEdge(1, 2, 1);
    inst.addEdge(1, 3, 1);
    inst.addEdge(1, 5, 1);
    inst.addEdge(3, 4, 1);
    inst.addEdge(1, 5, 1);
    inst.addEdge(5, 6, 1);
    inst.addEdge(7, 8, 1);

    assert.equal(inst.getEdgeWeight(1, 2), 1);
    assert.equal(inst.getEdgeWeight(2, 1), 1);

    assert.throws(() => inst.getEdgeWeight(1, 4));
  });

  it('should get neighbours', () => {
    const inst = new Graph();

    inst.addVertex(1);
    inst.addVertex(2);
    inst.addVertex(3);
    inst.addVertex(4);
    inst.addVertex(5);

    inst.addEdge(1, 2, 1);
    inst.addEdge(1, 3, 1);
    inst.addEdge(1, 5, 1);
    inst.addEdge(3, 4, 1);
    inst.addEdge(1, 5, 1);

    assert.deepStrictEqual(inst.getNeighbours(1), ['2', '3', '5']);
  });

  it('should be empty when initializing directed graph', () => {
    const inst = new Graph(true);

    assert(inst.isEmpty());
    assert.equal(inst.size, 0);
    assert.deepStrictEqual(inst.vertices, []);
  });

  it('should get neighbours from directed graph', () => {
    const inst = new Graph(true);

    inst.addVertex(1);
    inst.addVertex(2);
    inst.addVertex(3);
    inst.addVertex(4);
    inst.addVertex(5);

    inst.addEdge(1, 2, 1);
    inst.addEdge(1, 3, 1);
    inst.addEdge(1, 5, 1);
    inst.addEdge(3, 4, 1);

    assert.deepStrictEqual(inst.getNeighbours(1), ['2', '3', '5']);
    assert.deepStrictEqual(inst.getNeighbours(3), ['4']);
  });

  it('should check bfs traversal', () => {
    const inst = new Graph(true);

    inst.addVertex(1);
    inst.addVertex(2);
    inst.addVertex(3);
    inst.addVertex(4);
    inst.addVertex(5);

    inst.addEdge(1, 2, 1);
    inst.addEdge(1, 3, 1);
    inst.addEdge(1, 5, 1);
    inst.addEdge(5, 2, 1);
    inst.addEdge(3, 4, 1);

    const traversal = [];

    const cb = v => traversal.push(v);
    inst.bfs(1, cb);

    assert.deepStrictEqual(traversal, ['1', '2', '3', '5', '4']);
  });

  it('should check if edge is removed', () => {
    const inst = new Graph();

    inst.addVertex(1);
    inst.addVertex(2);
    inst.addVertex(3);
    inst.addVertex(4);
    inst.addVertex(5);

    inst.addEdge(1, 2);
    inst.addEdge(1, 3);
    inst.addEdge(1, 5);
    inst.addEdge(3, 4);

    assert.deepStrictEqual(inst.getNeighbours(1), ['2', '3', '5']);
    assert.deepStrictEqual(inst.getNeighbours(3), ['1', '4']);

    inst.removeEdge(1, 2);
    assert.deepStrictEqual(inst.getNeighbours(1), ['3', '5']);

    inst.removeEdge(1, 3);
    assert.deepStrictEqual(inst.getNeighbours(1), ['5']);
    assert.deepStrictEqual(inst.getNeighbours(3), ['4']);
  });

  it('should check if vertex is removed', () => {
    const inst = new Graph();

    inst.addVertex(1);
    inst.addVertex(2);
    inst.addVertex(3);
    inst.addVertex(4);
    inst.addVertex(5);

    inst.addEdge(1, 2);
    inst.addEdge(1, 3);
    inst.addEdge(1, 5);
    inst.addEdge(1, 4);
    inst.addEdge(3, 4);

    assert.deepStrictEqual(inst.getNeighbours(1), ['2', '3', '4', '5']);
    assert.deepStrictEqual(inst.getNeighbours(3), ['1', '4']);

    inst.removeVertex(5);
    assert.deepStrictEqual(inst.getNeighbours(1), ['2', '3', '4']);
    assert.deepStrictEqual(inst.getNeighbours(3), ['1', '4']);

    inst.removeVertex(4);
    assert.deepStrictEqual(inst.getNeighbours(1), ['2', '3']);
    assert.deepStrictEqual(inst.getNeighbours(3), ['1']);
  });
});

@@ -2789,16 +2789,19 @@
 raversal
+One
  = %5B%5D;%0A%0A
@@ -2812,16 +2812,19 @@
 const cb
+One
  = v =%3E 
@@ -2832,16 +2832,19 @@
 raversal
+One
 .push(v)
@@ -2863,16 +2863,19 @@
 fs(1, cb
+One
 );%0A%0A    
@@ -2906,16 +2906,19 @@
 raversal
+One
 , %5B'1', 
@@ -2934,24 +2934,174 @@
  '5', '4'%5D);
+%0A%0A    const traversalTwo = %5B%5D;%0A%0A    const cbTwo = v =%3E traversalTwo.push(v);%0A    inst.bfs(2, cbTwo);%0A%0A    assert.deepStrictEqual(traversalTwo, %5B'2'%5D);
 %0A  %7D);%0A%0A  it

Test Graph: BFS for directed graph