|
1 | 1 | import { describe, expect, it } from 'vitest' |
| 2 | +import { featureEntries, featureNames } from '../config.js' |
2 | 3 | import { getInfoOutput } from '../info.js' |
3 | | -import { |
4 | | - getFeatureEntries, |
5 | | - getInstallationModes, |
6 | | - stackDefinitions, |
7 | | - stackNames, |
8 | | -} from '../stacks/index.js' |
9 | 4 |
|
10 | | -describe('getInfoOutput — no filter', () => { |
| 5 | +describe('getInfoOutput', () => { |
11 | 6 | it('returns valid JSON', () => { |
12 | 7 | expect(() => JSON.parse(getInfoOutput())).not.toThrow() |
13 | 8 | }) |
14 | 9 |
|
15 | | - it('has stacks and modes top-level keys', () => { |
| 10 | + it('has features and modes top-level keys', () => { |
16 | 11 | const output = JSON.parse(getInfoOutput()) |
17 | | - expect(output).toHaveProperty('stacks') |
18 | | - expect(output).toHaveProperty('modes') |
| 12 | + expect(Object.keys(output)).toEqual(['features', 'modes']) |
19 | 13 | }) |
20 | 14 |
|
21 | | - it('includes every defined stack', () => { |
| 15 | + it('lists every feature', () => { |
22 | 16 | const output = JSON.parse(getInfoOutput()) |
23 | | - expect(Object.keys(output.stacks)).toEqual(stackNames) |
24 | | - }) |
25 | | - |
26 | | - it('each stack lists its features', () => { |
27 | | - const output = JSON.parse(getInfoOutput()) |
28 | | - |
29 | | - for (const stack of stackNames) { |
30 | | - const expected = Object.keys(stackDefinitions[stack].features) |
31 | | - expect(Object.keys(output.stacks[stack].features)).toEqual(expected) |
32 | | - } |
33 | | - }) |
34 | | - |
35 | | - it('each stack reports its package manager and label', () => { |
36 | | - const output = JSON.parse(getInfoOutput()) |
37 | | - |
38 | | - for (const stack of stackNames) { |
39 | | - expect(output.stacks[stack].label).toBe(stackDefinitions[stack].label) |
40 | | - expect(output.stacks[stack].packageManager).toBe(stackDefinitions[stack].packageManager) |
41 | | - } |
| 17 | + expect(Object.keys(output.features)).toEqual(featureNames) |
42 | 18 | }) |
43 | 19 |
|
44 | 20 | it('each feature has description and default', () => { |
45 | 21 | const output = JSON.parse(getInfoOutput()) |
46 | 22 |
|
47 | | - for (const stack of stackNames) { |
48 | | - for (const name of Object.keys(stackDefinitions[stack].features)) { |
49 | | - const feature = output.stacks[stack].features[name] |
50 | | - expect(feature).toHaveProperty('description') |
51 | | - expect(feature).toHaveProperty('default') |
52 | | - expect(typeof feature.description).toBe('string') |
53 | | - expect(typeof feature.default).toBe('boolean') |
54 | | - } |
| 23 | + for (const name of featureNames) { |
| 24 | + const feature = output.features[name] |
| 25 | + expect(typeof feature.description).toBe('string') |
| 26 | + expect(typeof feature.default).toBe('boolean') |
55 | 27 | } |
56 | 28 | }) |
57 | 29 |
|
58 | 30 | it('includes postInstall only for features that declare it', () => { |
59 | 31 | const output = JSON.parse(getInfoOutput()) |
60 | 32 |
|
61 | | - for (const stack of stackNames) { |
62 | | - for (const [name, def] of getFeatureEntries(stack)) { |
63 | | - const feature = output.stacks[stack].features[name] |
64 | | - if (def.postInstall) { |
65 | | - expect(feature.postInstall).toEqual(def.postInstall) |
66 | | - } else { |
67 | | - expect(feature).not.toHaveProperty('postInstall') |
68 | | - } |
69 | | - } |
70 | | - } |
71 | | - }) |
72 | | - |
73 | | - it('surfaces requires only for features that declare a dependency', () => { |
74 | | - const output = JSON.parse(getInfoOutput()) |
75 | | - |
76 | | - for (const stack of stackNames) { |
77 | | - for (const [name, def] of getFeatureEntries(stack)) { |
78 | | - const feature = output.stacks[stack].features[name] |
79 | | - if (def.requires) { |
80 | | - expect(feature.requires).toEqual(def.requires) |
81 | | - } else { |
82 | | - expect(feature).not.toHaveProperty('requires') |
83 | | - } |
| 33 | + for (const [name, def] of featureEntries) { |
| 34 | + const feature = output.features[name] |
| 35 | + if (def.postInstall) { |
| 36 | + expect(feature.postInstall).toEqual(def.postInstall) |
| 37 | + } else { |
| 38 | + expect(feature).not.toHaveProperty('postInstall') |
84 | 39 | } |
85 | 40 | } |
86 | 41 | }) |
87 | 42 |
|
88 | 43 | it('does not leak label, packages, or paths into feature output', () => { |
89 | 44 | const output = JSON.parse(getInfoOutput()) |
90 | 45 |
|
91 | | - for (const stack of stackNames) { |
92 | | - for (const name of Object.keys(stackDefinitions[stack].features)) { |
93 | | - const feature = output.stacks[stack].features[name] |
94 | | - expect(feature).not.toHaveProperty('label') |
95 | | - expect(feature).not.toHaveProperty('packages') |
96 | | - expect(feature).not.toHaveProperty('paths') |
97 | | - } |
98 | | - } |
99 | | - }) |
100 | | - |
101 | | - it('modes contains full and custom', () => { |
102 | | - const output = JSON.parse(getInfoOutput()) |
103 | | - expect(output.modes).toHaveProperty('full') |
104 | | - expect(output.modes).toHaveProperty('custom') |
105 | | - }) |
106 | | - |
107 | | - it('modes documents the default mode', () => { |
108 | | - const output = JSON.parse(getInfoOutput()) |
109 | | - expect(output.modes).toHaveProperty('default') |
110 | | - }) |
111 | | - |
112 | | - it('lists the modes each stack accepts, so agents never send a rejected one', () => { |
113 | | - const output = JSON.parse(getInfoOutput()) |
114 | | - |
115 | | - for (const stack of stackNames) { |
116 | | - expect(output.stacks[stack].modes).toEqual(getInstallationModes(stack)) |
| 46 | + for (const name of featureNames) { |
| 47 | + const feature = output.features[name] |
| 48 | + expect(feature).not.toHaveProperty('label') |
| 49 | + expect(feature).not.toHaveProperty('packages') |
| 50 | + expect(feature).not.toHaveProperty('paths') |
117 | 51 | } |
118 | | - |
119 | | - expect(output.stacks.evm.modes).not.toContain('default') |
120 | 52 | }) |
121 | 53 |
|
122 | | - it('reports canton as a stack with no features and no modes', () => { |
| 54 | + it('documents exactly the full and custom modes', () => { |
123 | 55 | const output = JSON.parse(getInfoOutput()) |
124 | | - |
125 | | - expect(output.stacks.canton.features).toEqual({}) |
126 | | - expect(output.stacks.canton.modes).toEqual([]) |
127 | | - }) |
128 | | -}) |
129 | | - |
130 | | -describe('getInfoOutput — filter by stack', () => { |
131 | | - it('returns only the requested stack', () => { |
132 | | - const output = JSON.parse(getInfoOutput('canton')) |
133 | | - expect(Object.keys(output.stacks)).toEqual(['canton']) |
134 | | - }) |
135 | | - |
136 | | - it('throws on unknown stack filter', () => { |
137 | | - expect(() => getInfoOutput('does-not-exist')).toThrow(/Unknown stack 'does-not-exist'/) |
138 | | - }) |
139 | | - |
140 | | - it('filtering by evm hides canton', () => { |
141 | | - const output = JSON.parse(getInfoOutput('evm')) |
142 | | - expect(Object.keys(output.stacks)).toEqual(['evm']) |
| 56 | + expect(Object.keys(output.modes)).toEqual(['full', 'custom']) |
143 | 57 | }) |
144 | 58 | }) |
0 commit comments