Skip to content

Commit 4771f4b

Browse files
Merge pull request #1835 from markscott-ms:tests
test(shared): add tests for architecture+pattern spectral rules
2 parents 44b13ac + 5edd901 commit 4771f4b

File tree

8 files changed

+729
-1
lines changed

8 files changed

+729
-1
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import { idsAreUnique } from './ids-are-unique';
2+
3+
describe('idsAreUnique', () => {
4+
it('should return an empty array when there is no input', () => {
5+
const input = null;
6+
const context = {
7+
document: {
8+
data: {
9+
}
10+
}
11+
};
12+
13+
const result = idsAreUnique(input, null, context);
14+
expect(result).toEqual([]);
15+
});
16+
17+
it('should return an empty array when there are no duplicate IDs', () => {
18+
const input = {};
19+
const context = {
20+
document: {
21+
data: {
22+
nodes: [
23+
{
24+
'unique-id': 'node1',
25+
'interfaces': [{'unique-id': 'intf1'}]
26+
},
27+
{
28+
'unique-id': 'node2'
29+
}
30+
],
31+
relationships: [
32+
{'unique-id': 'rel1'},
33+
{'unique-id': 'rel2'}
34+
]
35+
}
36+
}
37+
};
38+
39+
const result = idsAreUnique(input, null, context);
40+
expect(result).toEqual([]);
41+
});
42+
43+
it('should return messages for duplicate IDs within nodes', () => {
44+
const input = {};
45+
const context = {
46+
document: {
47+
data: {
48+
nodes: [
49+
{'unique-id': 'node1'},
50+
{'unique-id': 'node1'}
51+
]
52+
}
53+
}
54+
};
55+
56+
const result = idsAreUnique(input, null, context);
57+
expect(result.length).toBeGreaterThan(0);
58+
expect(result[0].message).toContain('Duplicate unique-id detected. ID: node1, path: /nodes/1/unique-id');
59+
});
60+
61+
it('should return messages for duplicate IDs within relationships', () => {
62+
const input = {};
63+
const context = {
64+
document: {
65+
data: {
66+
relationships: [
67+
{'unique-id': 'rel1'},
68+
{'unique-id': 'rel1'}
69+
]
70+
}
71+
}
72+
};
73+
74+
const result = idsAreUnique(input, null, context);
75+
expect(result.length).toBeGreaterThan(0);
76+
expect(result[0].message).toContain('Duplicate unique-id detected. ID: rel1, path: /relationships/1/unique-id');
77+
});
78+
79+
80+
it('should return messages for duplicate IDs within interfaces', () => {
81+
const input = {};
82+
const context = {
83+
document: {
84+
data: {
85+
nodes: [
86+
{
87+
'unique-id': 'node1',
88+
'interfaces': [{'unique-id': 'intf1'}]
89+
},
90+
{
91+
'unique-id': 'node2',
92+
'interfaces': [{'unique-id': 'intf1'}]
93+
}
94+
]
95+
}
96+
}
97+
};
98+
99+
const result = idsAreUnique(input, null, context);
100+
expect(result.length).toBeGreaterThan(0);
101+
expect(result[0].message).toContain('Duplicate unique-id detected. ID: intf1, path: /nodes/1/interfaces/0/unique-id');
102+
});
103+
104+
105+
106+
it('should return messages for duplicate IDs across unique-ids', () => {
107+
const input = {};
108+
const context = {
109+
document: {
110+
data: {
111+
nodes: [
112+
{'unique-id': 'node1'},
113+
{'unique-id': 'node2'}
114+
],
115+
relationships: [
116+
{'unique-id': 'node1'},
117+
{'unique-id': 'rel2'}
118+
]
119+
}
120+
}
121+
};
122+
123+
const result = idsAreUnique(input, null, context);
124+
expect(result.length).toBeGreaterThan(0);
125+
expect(result[0].message).toContain('Duplicate unique-id detected. ID: node1, path: /relationships/0/unique-id');
126+
});
127+
});

shared/src/spectral/functions/architecture/ids-are-unique.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ export function idsAreUnique(input, _, context) {
2222
detectDuplicates(interfaceIdMatches, seenIds, messages);
2323

2424
return messages;
25-
};
25+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import { interfaceIdExistsOnNode } from './interface-id-exists-on-node';
2+
3+
describe('interfaceIdExistsOnNode', () => {
4+
it('should return an empty array when there is no input', () => {
5+
const input = null;
6+
const context = {
7+
document: {
8+
data: {}
9+
}
10+
};
11+
12+
const result = interfaceIdExistsOnNode(input, null, context);
13+
expect(result).toEqual([]);
14+
});
15+
16+
it('should return an empty array when input has no interfaces', () => {
17+
const input = {};
18+
const context = {
19+
document: {
20+
data: {}
21+
}
22+
};
23+
24+
const result = interfaceIdExistsOnNode(input, null, context);
25+
expect(result).toEqual([]);
26+
});
27+
28+
it('should return a message when input is a connect relationship missing a node', () => {
29+
const input = { interfaces: ['intf1'] };
30+
const context = {
31+
document: {
32+
data: {}
33+
},
34+
path: ['/relationships/0/connects/destination']
35+
};
36+
37+
const result = interfaceIdExistsOnNode(input, null, context);
38+
expect(result.length).toBe(1);
39+
expect(result[0].message).toBe('Invalid connects relationship - no node defined.');
40+
expect(result[0].path).toEqual(['/relationships/0/connects/destination']);
41+
});
42+
43+
it('should return an empty array when the node and interface exists', () => {
44+
const input = { node: 'node1', interfaces: ['intf1'] };
45+
const context = {
46+
document: {
47+
data: {
48+
nodes: [
49+
{
50+
'unique-id': 'node1',
51+
'interfaces': [
52+
{'unique-id': 'intf1'} // will match this interface
53+
]
54+
}
55+
]
56+
}
57+
}
58+
};
59+
60+
const result = interfaceIdExistsOnNode(input, null, context);
61+
expect(result).toEqual([]);
62+
});
63+
64+
it('should return a message when the target node has no interfaces', () => {
65+
const input = { node: 'node1', interfaces: ['intf2'] };
66+
const context = {
67+
document: {
68+
data: {
69+
nodes: [{'unique-id': 'node1'}]
70+
}
71+
},
72+
path: ['/relationships/0/connects/destination']
73+
};
74+
75+
const result = interfaceIdExistsOnNode(input, null, context);
76+
expect(result.length).toBe(1);
77+
expect(result[0].message).toBe(`Node with unique-id ${input.node} has no interfaces defined, expected interfaces [${input.interfaces}].`);
78+
});
79+
80+
it('should return a message when the interface does not exist', () => {
81+
const input = { node: 'node1', interfaces: ['intf2'] };
82+
const context = {
83+
document: {
84+
data: {
85+
nodes: [
86+
{
87+
'unique-id': 'node1',
88+
'interfaces': [
89+
{'unique-id': 'intf1'}
90+
]
91+
}
92+
]
93+
}
94+
},
95+
path: ['/relationships/0/connects/destination']
96+
};
97+
98+
const result = interfaceIdExistsOnNode(input, null, context);
99+
expect(result.length).toBe(1);
100+
expect(result[0].message).toBe(`Referenced interface with ID '${input.interfaces[0]}' was not defined on the node with ID '${input.node}'.`);
101+
expect(result[0].path).toEqual(['/relationships/0/connects/destination']);
102+
});
103+
104+
it('should return a message when one interface does not exist', () => {
105+
const input = { node: 'node1', interfaces: ['intf1', 'intf2'] };
106+
const context = {
107+
document: {
108+
data: {
109+
nodes: [
110+
{
111+
'unique-id': 'node1',
112+
'interfaces': [
113+
{'unique-id': 'intf1'}
114+
]
115+
}
116+
]
117+
}
118+
},
119+
path: ['/relationships/0/connects/destination']
120+
};
121+
122+
const result = interfaceIdExistsOnNode(input, null, context);
123+
expect(result.length).toBe(1);
124+
expect(result[0].message).toBe(`Referenced interface with ID '${input.interfaces[1]}' was not defined on the node with ID '${input.node}'.`);
125+
expect(result[0].path).toEqual(['/relationships/0/connects/destination']);
126+
});
127+
});
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { interfaceIdExists } from './interface-id-exists';
2+
3+
describe('interfaceIdExists', () => {
4+
it('should return an empty array when there is no input', () => {
5+
const input = null;
6+
const context = {
7+
document: {
8+
data: {}
9+
}
10+
};
11+
12+
const result = interfaceIdExists(input, null, context);
13+
expect(result).toEqual([]);
14+
});
15+
16+
it('should return an empty array when the ID exists', () => {
17+
const input = 'intf1';
18+
const context = {
19+
document: {
20+
data: {
21+
nodes: [
22+
{
23+
'unique-id': 'node1',
24+
interfaces: [
25+
{'unique-id': 'intf1'}
26+
]
27+
}
28+
]
29+
}
30+
}
31+
};
32+
33+
const result = interfaceIdExists(input, null, context);
34+
expect(result).toEqual([]);
35+
});
36+
37+
it('should return a message when the ID does not exist', () => {
38+
const input = 'intf2';
39+
const context = {
40+
document: {
41+
data: {
42+
nodes: [
43+
{
44+
'unique-id': 'node1',
45+
interfaces: [
46+
{'unique-id': 'intf1'}
47+
]
48+
}
49+
]
50+
}
51+
},
52+
path: ['/relationships/0/connects/destination/interface']
53+
};
54+
55+
const result = interfaceIdExists(input, null, context);
56+
expect(result.length).toBe(1);
57+
expect(result[0].message).toBe(`'${input}' does not refer to the unique-id of an existing interface.`);
58+
expect(result[0].path).toEqual(['/relationships/0/connects/destination/interface']);
59+
});
60+
});
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { nodeIdExists } from './node-id-exists';
2+
3+
describe('nodeIdExists', () => {
4+
it('should return an empty array when there is no input', () => {
5+
const input = null;
6+
const context = {
7+
document: {
8+
data: {}
9+
}
10+
};
11+
12+
const result = nodeIdExists(input, null, context);
13+
expect(result).toEqual([]);
14+
});
15+
16+
it('should return an empty array when the ID exists', () => {
17+
const input = 'node1';
18+
const context = {
19+
document: {
20+
data: {
21+
nodes: [
22+
{'unique-id': 'node1'}
23+
]
24+
}
25+
}
26+
};
27+
28+
const result = nodeIdExists(input, null, context);
29+
expect(result).toEqual([]);
30+
});
31+
32+
it('should return a message when the ID does not exist', () => {
33+
const input = 'node2';
34+
const context = {
35+
document: {
36+
data: {
37+
nodes: [
38+
{'unique-id': 'node1'}
39+
]
40+
}
41+
},
42+
path: ['/relationships/0/connects/destination']
43+
};
44+
45+
const result = nodeIdExists(input, null, context);
46+
expect(result.length).toBe(1);
47+
expect(result[0].message).toBe(`'${input}' does not refer to the unique-id of an existing node.`);
48+
expect(result[0].path).toEqual(['/relationships/0/connects/destination']);
49+
});
50+
});

0 commit comments

Comments
 (0)