<commit_before><commit_msg>Add tests for directed cycle processor<commit_after>const expect = require('chai').expect;

let DirectedGraph;
let graph;
let DirectedCycle;
let cycleProcessor;

try {
  DirectedGraph = require('../../../../structures/graphs/Directed');
  graph = new DirectedGraph();
  DirectedCycle = require('../../../../structures/graphs/processors/directed/Cycle');
  cycleProcessor = new DirectedCycle();
} catch (e) {
  throw new Error('DirectedCycle could not be tested due to faulty import, ' +
    'likely from an incorrect file path or exporting a non-constructor from ' +
    'the processor or graph files.');
}

describe('DirectedCycle', () => {
  beforeEach(() => {
    graph = new DirectedGraph();
    const edges = [
      [0, 7],
      [0, 1],
      [1, 2],
      [2, 4],
      [1, 3],
      [3, 5],
    ];

    /*
      No cycles initially:
      
      0 -> 7
        -> 1 -> 2 -> 4
             -> 3 -> 5
    */
    
    edges.forEach(edge => graph.addEdge(edge));

    cycleProcessor = new DirectedCycle(graph);
  });

  it('should be extensible', () => {
    expect(cycleProcessor).to.be.extensible;
  });

  it('should have properties granted from constructor call', () => {
    expect(cycleProcessor).to.have.all.keys(
      'graph',
      'hasCycle',
      'initialized',
    );
  });
  
  it('should not be initialized before its initialize method is called', () => {
    expect(cycleProcessor.initialized).to.be.false;
  });

  it('should initially have hasCycle set to null', () => {
    expect(cycleProcessor.hasCycle).to.equal(null);
  });

  it('should have a graph of type object', () => {
    expect(cycleProcessor.graph).to.be.an('object');
  });

  describe('#initialize', () => {
    it('should return false if the graph does not contain a cycle', () => {
      expect(cycleProcessor.initialize()).to.be.false;
    });
    
    it('should set hasCycle to false if the graph does not contain a cycle', () => {
      cycleProcessor.initialize();

      expect(cycleProcessor.hasCycle).to.be.false;
    });
    
    it('should return true if the graph contains a cycle', () => {
      graph = new DirectedGraph();
      const edges = [
        [0, 7],
        [0, 1],
        [1, 2],
        [2, 4],
        [1, 3],
        [3, 5],
        [5, 0],
      ];
  
      /*
        Cycle where 5 points to 0
      
        0 -> 7
          -> 1 -> 2 -> 4
               -> 3 -> 5 -> cycle 0
      */
      
      edges.forEach(edge => graph.addEdge(edge));
  
      cycleProcessor = new DirectedCycle(graph);
      expect(cycleProcessor.initialize()).to.be.true;
    });
    
    it('should set hasCycle to true if the graph contains a cycle', () => {
      graph = new DirectedGraph();
      const edges = [
        [0, 7],
        [0, 1],
        [1, 2],
        [2, 4],
        [1, 3],
        [3, 5],
        [5, 0],
      ];
  
      /*
        Cycle where 5 points to 0
      
        0 -> 7
          -> 1 -> 2 -> 4
               -> 3 -> 5 -> cycle 0
      */
      
      edges.forEach(edge => graph.addEdge(edge));
      cycleProcessor = new DirectedCycle(graph);

      cycleProcessor.initialize()

      expect(cycleProcessor.hasCycle).to.be.true;
    });
    
    it('should set the initialized property to true', () => {
      cycleProcessor.initialize();

      expect(cycleProcessor.initialized).to.be.true;
    });

    it('should throw an error if called twice', () => {
      cycleProcessor.initialize();

      expect(() => cycleProcessor.initialize()).to.throw(Error);
    });
  });
});
{'fraction_non_alphanumeric': 0.15994358251057827, 'fraction_numerical': 0.018899858956276445, 'mean_word_length': 2.0490111779879623, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5382929', 'n_tokens_mistral': 1129, 'n_tokens_neox': 1067, 'n_words': 280}