2020-08-27 23:30:53 +00:00
|
|
|
import { expect } from 'chai';
|
2020-08-28 04:07:58 +00:00
|
|
|
import { match } from 'sinon';
|
2020-08-27 23:30:53 +00:00
|
|
|
|
2020-08-28 04:07:58 +00:00
|
|
|
import {
|
|
|
|
cleanName,
|
|
|
|
dotGraph,
|
|
|
|
Edge,
|
|
|
|
edgeStyle,
|
|
|
|
EdgeType,
|
|
|
|
graphChange,
|
|
|
|
graphProject,
|
|
|
|
labelEdges,
|
|
|
|
mergeEdges,
|
|
|
|
} from '../src/graph';
|
2020-08-27 23:30:53 +00:00
|
|
|
import { ChangeVerb } from '../src/resolve';
|
|
|
|
|
2020-08-20 22:08:57 +00:00
|
|
|
describe('graph tools', () => {
|
|
|
|
describe('label edges', () => {
|
2020-08-27 23:30:53 +00:00
|
|
|
it('should include rule labels', () => {
|
|
|
|
const edges: Array<Edge> = [];
|
|
|
|
|
|
|
|
labelEdges({
|
|
|
|
adds: [{
|
|
|
|
name: 'foo',
|
|
|
|
}],
|
|
|
|
name: 'source',
|
|
|
|
priority: 1,
|
|
|
|
removes: [{
|
|
|
|
name: 'bar',
|
|
|
|
}],
|
|
|
|
requires: [{
|
|
|
|
name: 'bin',
|
|
|
|
}],
|
|
|
|
}, edges);
|
|
|
|
|
|
|
|
const EXPECTED_EDGES = 3;
|
|
|
|
expect(edges).to.be.an.instanceOf(Array).and.to.have.lengthOf(EXPECTED_EDGES);
|
|
|
|
expect(edges).to.deep.include({
|
|
|
|
source: 'source',
|
|
|
|
target: 'foo',
|
|
|
|
type: EdgeType.FORWARD,
|
|
|
|
verb: ChangeVerb.CREATED,
|
|
|
|
});
|
|
|
|
expect(edges).to.deep.include({
|
|
|
|
source: 'source',
|
|
|
|
target: 'bar',
|
|
|
|
type: EdgeType.FORWARD,
|
|
|
|
verb: ChangeVerb.REMOVED,
|
|
|
|
});
|
|
|
|
expect(edges).to.deep.include({
|
|
|
|
source: 'source',
|
|
|
|
target: 'bin',
|
|
|
|
type: EdgeType.FORWARD,
|
|
|
|
verb: ChangeVerb.REQUIRED,
|
|
|
|
});
|
|
|
|
});
|
2020-08-20 22:08:57 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('graph labels', () => {
|
2020-08-27 23:30:53 +00:00
|
|
|
it('should create nodes for each label', () => {
|
|
|
|
const graph = graphProject({
|
|
|
|
flags: [{
|
|
|
|
adds: [],
|
|
|
|
color: 'aabbcc',
|
|
|
|
name: 'foo',
|
|
|
|
priority: 0,
|
|
|
|
removes: [],
|
|
|
|
requires: [],
|
|
|
|
}],
|
|
|
|
name: '',
|
|
|
|
states: [],
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(graph.nodes).to.be.an.instanceOf(Array);
|
|
|
|
expect(graph.nodes).to.deep.include({
|
|
|
|
color: 'aabbcc',
|
|
|
|
name: 'foo',
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-08-20 22:08:57 +00:00
|
|
|
it('should create edges for each change rule');
|
|
|
|
it('should create edges for each state change');
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('clean name', () => {
|
2020-08-27 23:30:53 +00:00
|
|
|
it('should remove special characters', () => {
|
|
|
|
expect(cleanName('$foo')).to.equal('foo');
|
|
|
|
expect(cleanName('foo$')).to.equal('foo');
|
|
|
|
expect(cleanName('foo$bar')).to.equal('foo_bar');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should remove duplicate escape characters', () => {
|
|
|
|
expect(cleanName('foo$$bar')).to.equal('foo_bar');
|
|
|
|
expect(cleanName('foo__bar')).to.equal('foo_bar');
|
|
|
|
});
|
2020-08-20 22:08:57 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('edge style', () => {
|
2020-08-27 23:30:53 +00:00
|
|
|
it('should color edges', () => {
|
|
|
|
expect(edgeStyle({
|
|
|
|
source: 'foo',
|
|
|
|
target: 'bar',
|
|
|
|
type: EdgeType.BOTH,
|
|
|
|
verb: ChangeVerb.CREATED,
|
|
|
|
})).to.include('color=');
|
|
|
|
});
|
2020-08-20 22:08:57 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('node style', () => {
|
|
|
|
it('should label nodes');
|
|
|
|
it('should color nodes');
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('dot formatter', () => {
|
2020-08-27 23:30:53 +00:00
|
|
|
it('should print nodes', () => {
|
|
|
|
const graph = dotGraph({
|
|
|
|
children: [],
|
|
|
|
edges: [],
|
|
|
|
name: '',
|
|
|
|
nodes: [{
|
|
|
|
color: '',
|
|
|
|
name: 'foo',
|
|
|
|
}, {
|
|
|
|
color: '',
|
|
|
|
name: 'bar',
|
|
|
|
}],
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(graph).to.include('foo [color=');
|
|
|
|
expect(graph).to.include('bar [color=');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should print edges', () => {
|
|
|
|
const graph = dotGraph({
|
|
|
|
children: [],
|
|
|
|
edges: [{
|
|
|
|
source: 'foo',
|
|
|
|
target: 'bar',
|
|
|
|
type: EdgeType.BOTH,
|
|
|
|
verb: ChangeVerb.CREATED,
|
|
|
|
}],
|
|
|
|
name: '',
|
|
|
|
nodes: [],
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(graph).to.include('foo -> bar');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should cluster children', () => {
|
|
|
|
const graph = dotGraph({
|
|
|
|
children: [{
|
|
|
|
children: [],
|
|
|
|
edges: [],
|
|
|
|
name: 'foo',
|
|
|
|
nodes: [],
|
|
|
|
}],
|
|
|
|
edges: [],
|
|
|
|
name: 'bar',
|
|
|
|
nodes: [],
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(graph).to.include('subgraph cluster_foo');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should label the root digraph', () => {
|
|
|
|
const graph = dotGraph({
|
|
|
|
children: [],
|
|
|
|
edges: [],
|
|
|
|
name: 'foo',
|
|
|
|
nodes: [],
|
|
|
|
});
|
|
|
|
|
|
|
|
expect(graph).to.include('digraph foo');
|
|
|
|
});
|
2020-08-20 22:08:57 +00:00
|
|
|
});
|
2020-08-28 04:07:58 +00:00
|
|
|
|
|
|
|
describe('merge edges helper', () => {
|
|
|
|
it('should merge opposing edges', () => {
|
|
|
|
const edges = mergeEdges([{
|
|
|
|
source: 'foo',
|
|
|
|
target: 'bar',
|
|
|
|
type: EdgeType.FORWARD,
|
|
|
|
verb: ChangeVerb.CREATED,
|
|
|
|
}, {
|
|
|
|
source: 'bar',
|
|
|
|
target: 'foo',
|
|
|
|
type: EdgeType.FORWARD,
|
|
|
|
verb: ChangeVerb.CREATED,
|
|
|
|
}]);
|
|
|
|
|
|
|
|
expect(edges).to.have.lengthOf(1).and.to.deep.include({
|
|
|
|
source: 'foo',
|
|
|
|
target: 'bar',
|
|
|
|
type: EdgeType.BOTH,
|
|
|
|
verb: ChangeVerb.CREATED,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should merge identical edges', () => {
|
|
|
|
const edges = mergeEdges([{
|
|
|
|
source: 'foo',
|
|
|
|
target: 'bar',
|
|
|
|
type: EdgeType.FORWARD,
|
|
|
|
verb: ChangeVerb.CREATED,
|
|
|
|
}, {
|
|
|
|
source: 'foo',
|
|
|
|
target: 'bar',
|
|
|
|
type: EdgeType.FORWARD,
|
|
|
|
verb: ChangeVerb.CREATED,
|
|
|
|
}]);
|
|
|
|
|
|
|
|
expect(edges).to.have.lengthOf(1).and.to.deep.include({
|
|
|
|
source: 'foo',
|
|
|
|
target: 'bar',
|
|
|
|
type: EdgeType.FORWARD,
|
|
|
|
verb: ChangeVerb.CREATED,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should prefer both type to forward', () => {
|
|
|
|
const edges = mergeEdges([{
|
|
|
|
source: 'foo',
|
|
|
|
target: 'bar',
|
|
|
|
type: EdgeType.FORWARD,
|
|
|
|
verb: ChangeVerb.CREATED,
|
|
|
|
}, {
|
|
|
|
source: 'bar',
|
|
|
|
target: 'foo',
|
|
|
|
type: EdgeType.BOTH,
|
|
|
|
verb: ChangeVerb.CREATED,
|
|
|
|
}]);
|
|
|
|
|
|
|
|
expect(edges).to.have.lengthOf(1).and.to.deep.include({
|
|
|
|
source: 'foo',
|
|
|
|
target: 'bar',
|
|
|
|
type: EdgeType.BOTH,
|
|
|
|
verb: ChangeVerb.CREATED,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not merge different verbs', () => {
|
|
|
|
const edges = mergeEdges([{
|
|
|
|
source: 'foo',
|
|
|
|
target: 'bar',
|
|
|
|
type: EdgeType.FORWARD,
|
|
|
|
verb: ChangeVerb.CREATED,
|
|
|
|
}, {
|
|
|
|
source: 'bar',
|
|
|
|
target: 'foo',
|
|
|
|
type: EdgeType.FORWARD,
|
|
|
|
verb: ChangeVerb.REQUIRED,
|
|
|
|
}]);
|
|
|
|
|
|
|
|
const EXPECTED_EDGES = 2;
|
|
|
|
expect(edges).to.have.lengthOf(EXPECTED_EDGES);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('graph change', () => {
|
|
|
|
it('should add state change node', () => {
|
|
|
|
const graph = {
|
|
|
|
children: [],
|
|
|
|
edges: [],
|
|
|
|
name: '',
|
|
|
|
nodes: [],
|
|
|
|
};
|
|
|
|
graphChange(graph, {
|
|
|
|
adds: [],
|
|
|
|
matches: [{
|
|
|
|
name: 'bar',
|
|
|
|
}, {
|
|
|
|
name: 'bin',
|
|
|
|
}],
|
|
|
|
removes: [],
|
|
|
|
}, 'foo', 0);
|
|
|
|
|
|
|
|
expect(graph.nodes).to.have.lengthOf(1).and.to.deep.include({
|
|
|
|
color: 'aaaaaa',
|
|
|
|
name: 'foo with (bar,bin)',
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should add state change edge', () => {
|
|
|
|
const graph = {
|
|
|
|
children: [],
|
|
|
|
edges: [],
|
|
|
|
name: '',
|
|
|
|
nodes: [],
|
|
|
|
};
|
|
|
|
graphChange(graph, {
|
|
|
|
adds: [],
|
|
|
|
matches: [{
|
|
|
|
name: 'bar',
|
|
|
|
}, {
|
|
|
|
name: 'bin',
|
|
|
|
}],
|
|
|
|
removes: [],
|
|
|
|
}, 'foo', 0);
|
|
|
|
|
|
|
|
const EXPECTED_EDGES = 3;
|
|
|
|
expect(graph.edges).to.have.lengthOf(EXPECTED_EDGES).and.to.deep.include({
|
|
|
|
source: 'foo',
|
|
|
|
target: 'foo with (bar,bin)',
|
|
|
|
type: EdgeType.FORWARD,
|
|
|
|
verb: ChangeVerb.BECAME,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should add normal edges', () => {
|
|
|
|
const graph = {
|
|
|
|
children: [],
|
|
|
|
edges: [],
|
|
|
|
name: '',
|
|
|
|
nodes: [],
|
|
|
|
};
|
|
|
|
graphChange(graph, {
|
|
|
|
adds: [{
|
|
|
|
name: 'bar',
|
|
|
|
}],
|
|
|
|
matches: [],
|
|
|
|
removes: [{
|
|
|
|
name: 'bin',
|
|
|
|
}],
|
|
|
|
}, 'foo', 0);
|
|
|
|
|
|
|
|
const EXPECTED_EDGES = 3;
|
|
|
|
expect(graph.edges).to.have.lengthOf(EXPECTED_EDGES).and.to.deep.include({
|
|
|
|
source: 'foo with ()',
|
|
|
|
target: 'bar',
|
|
|
|
type: EdgeType.FORWARD,
|
|
|
|
verb: ChangeVerb.CREATED,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2020-08-20 22:08:57 +00:00
|
|
|
});
|