@auto-engineer/component-implementor-react 1.97.2 → 1.99.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-test.log +6 -6
- package/.turbo/turbo-type-check.log +1 -1
- package/CHANGELOG.md +99 -0
- package/dist/src/commands/implement-component.d.ts +19 -0
- package/dist/src/commands/implement-component.d.ts.map +1 -1
- package/dist/src/commands/implement-component.js +116 -34
- package/dist/src/commands/implement-component.js.map +1 -1
- package/dist/src/commands/implement-component.test.js +352 -33
- package/dist/src/commands/implement-component.test.js.map +1 -1
- package/dist/src/extract-exports.d.ts +6 -0
- package/dist/src/extract-exports.d.ts.map +1 -0
- package/dist/src/extract-exports.js +46 -0
- package/dist/src/extract-exports.js.map +1 -0
- package/dist/src/generate-story-deterministic.d.ts +30 -0
- package/dist/src/generate-story-deterministic.d.ts.map +1 -0
- package/dist/src/generate-story-deterministic.js +229 -0
- package/dist/src/generate-story-deterministic.js.map +1 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/pipeline/run-pipeline.d.ts +69 -0
- package/dist/src/pipeline/run-pipeline.d.ts.map +1 -0
- package/dist/src/pipeline/run-pipeline.js +78 -0
- package/dist/src/pipeline/run-pipeline.js.map +1 -0
- package/dist/src/pipeline/run-pipeline.test.d.ts +2 -0
- package/dist/src/pipeline/run-pipeline.test.d.ts.map +1 -0
- package/dist/src/pipeline/run-pipeline.test.js +247 -0
- package/dist/src/pipeline/run-pipeline.test.js.map +1 -0
- package/dist/src/pipeline/steps/generate-component.d.ts +4 -0
- package/dist/src/pipeline/steps/generate-component.d.ts.map +1 -0
- package/dist/src/pipeline/steps/generate-component.js +50 -0
- package/dist/src/pipeline/steps/generate-component.js.map +1 -0
- package/dist/src/pipeline/steps/generate-component.test.d.ts.map +1 -0
- package/dist/src/pipeline/steps/generate-component.test.js +106 -0
- package/dist/src/pipeline/steps/generate-component.test.js.map +1 -0
- package/dist/src/pipeline/steps/generate-story.d.ts +3 -0
- package/dist/src/pipeline/steps/generate-story.d.ts.map +1 -0
- package/dist/src/pipeline/steps/generate-story.js +14 -0
- package/dist/src/pipeline/steps/generate-story.js.map +1 -0
- package/dist/src/pipeline/steps/generate-story.test.d.ts.map +1 -0
- package/dist/src/pipeline/steps/generate-story.test.js +41 -0
- package/dist/src/pipeline/steps/generate-story.test.js.map +1 -0
- package/dist/src/pipeline/steps/generate-test.d.ts +4 -0
- package/dist/src/pipeline/steps/generate-test.d.ts.map +1 -0
- package/dist/src/pipeline/steps/generate-test.js +19 -0
- package/dist/src/pipeline/steps/generate-test.js.map +1 -0
- package/dist/src/pipeline/steps/generate-test.test.d.ts.map +1 -0
- package/dist/src/pipeline/steps/generate-test.test.js +60 -0
- package/dist/src/pipeline/steps/generate-test.test.js.map +1 -0
- package/dist/src/pipeline/steps/lint-fix-loop.d.ts +4 -0
- package/dist/src/pipeline/steps/lint-fix-loop.d.ts.map +1 -0
- package/dist/src/pipeline/steps/lint-fix-loop.js +45 -0
- package/dist/src/pipeline/steps/lint-fix-loop.js.map +1 -0
- package/dist/src/pipeline/steps/lint-fix-loop.test.d.ts +2 -0
- package/dist/src/pipeline/steps/lint-fix-loop.test.d.ts.map +1 -0
- package/dist/src/pipeline/steps/lint-fix-loop.test.js +119 -0
- package/dist/src/pipeline/steps/lint-fix-loop.test.js.map +1 -0
- package/dist/src/pipeline/steps/story-fix-loop.d.ts +4 -0
- package/dist/src/pipeline/steps/story-fix-loop.d.ts.map +1 -0
- package/dist/src/pipeline/steps/story-fix-loop.js +34 -0
- package/dist/src/pipeline/steps/story-fix-loop.js.map +1 -0
- package/dist/src/pipeline/steps/story-fix-loop.test.d.ts +2 -0
- package/dist/src/pipeline/steps/story-fix-loop.test.d.ts.map +1 -0
- package/dist/src/pipeline/steps/story-fix-loop.test.js +94 -0
- package/dist/src/pipeline/steps/story-fix-loop.test.js.map +1 -0
- package/dist/src/pipeline/steps/storybook-test.d.ts +3 -0
- package/dist/src/pipeline/steps/storybook-test.d.ts.map +1 -0
- package/dist/src/pipeline/steps/storybook-test.js +22 -0
- package/dist/src/pipeline/steps/storybook-test.js.map +1 -0
- package/dist/src/pipeline/steps/storybook-test.test.d.ts +2 -0
- package/dist/src/pipeline/steps/storybook-test.test.d.ts.map +1 -0
- package/dist/src/pipeline/steps/storybook-test.test.js +66 -0
- package/dist/src/pipeline/steps/storybook-test.test.js.map +1 -0
- package/dist/src/pipeline/steps/test-fix-loop.d.ts +4 -0
- package/dist/src/pipeline/steps/test-fix-loop.d.ts.map +1 -0
- package/dist/src/pipeline/steps/test-fix-loop.js +44 -0
- package/dist/src/pipeline/steps/test-fix-loop.js.map +1 -0
- package/dist/src/pipeline/steps/test-fix-loop.test.d.ts +2 -0
- package/dist/src/pipeline/steps/test-fix-loop.test.d.ts.map +1 -0
- package/dist/src/pipeline/steps/test-fix-loop.test.js +168 -0
- package/dist/src/pipeline/steps/test-fix-loop.test.js.map +1 -0
- package/dist/src/pipeline/steps/type-fix-loop.d.ts +4 -0
- package/dist/src/pipeline/steps/type-fix-loop.d.ts.map +1 -0
- package/dist/src/pipeline/steps/type-fix-loop.js +43 -0
- package/dist/src/pipeline/steps/type-fix-loop.js.map +1 -0
- package/dist/src/pipeline/steps/type-fix-loop.test.d.ts +2 -0
- package/dist/src/pipeline/steps/type-fix-loop.test.d.ts.map +1 -0
- package/dist/src/pipeline/steps/type-fix-loop.test.js +112 -0
- package/dist/src/pipeline/steps/type-fix-loop.test.js.map +1 -0
- package/dist/src/pipeline/steps/visual-test.d.ts +3 -0
- package/dist/src/pipeline/steps/visual-test.d.ts.map +1 -0
- package/dist/src/pipeline/steps/visual-test.js +4 -0
- package/dist/src/pipeline/steps/visual-test.js.map +1 -0
- package/dist/src/pipeline/steps/visual-test.test.d.ts +2 -0
- package/dist/src/pipeline/steps/visual-test.test.d.ts.map +1 -0
- package/dist/src/pipeline/steps/visual-test.test.js +9 -0
- package/dist/src/pipeline/steps/visual-test.test.js.map +1 -0
- package/dist/src/project-context.d.ts +10 -0
- package/dist/src/project-context.d.ts.map +1 -0
- package/dist/src/project-context.js +178 -0
- package/dist/src/project-context.js.map +1 -0
- package/dist/src/prompt.d.ts +39 -7
- package/dist/src/prompt.d.ts.map +1 -1
- package/dist/src/prompt.js +233 -23
- package/dist/src/prompt.js.map +1 -1
- package/dist/src/prompt.test.js +225 -9
- package/dist/src/prompt.test.js.map +1 -1
- package/dist/src/scaffold.d.ts +49 -0
- package/dist/src/scaffold.d.ts.map +1 -0
- package/dist/src/scaffold.js +208 -0
- package/dist/src/scaffold.js.map +1 -0
- package/dist/src/spec-contract.js +1 -1
- package/dist/src/spec-contract.js.map +1 -1
- package/dist/src/spec-contract.test.d.ts +2 -0
- package/dist/src/spec-contract.test.d.ts.map +1 -0
- package/dist/src/spec-contract.test.js +21 -0
- package/dist/src/spec-contract.test.js.map +1 -0
- package/dist/src/tools/lint-runner.d.ts +7 -0
- package/dist/src/tools/lint-runner.d.ts.map +1 -0
- package/dist/src/tools/lint-runner.js +48 -0
- package/dist/src/tools/lint-runner.js.map +1 -0
- package/dist/src/tools/lint-runner.test.d.ts +2 -0
- package/dist/src/tools/lint-runner.test.d.ts.map +1 -0
- package/dist/src/tools/lint-runner.test.js +90 -0
- package/dist/src/tools/lint-runner.test.js.map +1 -0
- package/dist/src/tools/storybook-runner.d.ts +6 -0
- package/dist/src/tools/storybook-runner.d.ts.map +1 -0
- package/dist/src/tools/storybook-runner.js +25 -0
- package/dist/src/tools/storybook-runner.js.map +1 -0
- package/dist/src/tools/storybook-runner.test.d.ts +2 -0
- package/dist/src/tools/storybook-runner.test.d.ts.map +1 -0
- package/dist/src/tools/storybook-runner.test.js +43 -0
- package/dist/src/tools/storybook-runner.test.js.map +1 -0
- package/dist/src/tools/test-runner.d.ts +9 -0
- package/dist/src/tools/test-runner.d.ts.map +1 -0
- package/dist/src/tools/test-runner.js +74 -0
- package/dist/src/tools/test-runner.js.map +1 -0
- package/dist/src/tools/test-runner.test.d.ts +2 -0
- package/dist/src/tools/test-runner.test.d.ts.map +1 -0
- package/dist/src/tools/test-runner.test.js +177 -0
- package/dist/src/tools/test-runner.test.js.map +1 -0
- package/dist/src/tools/type-checker.d.ts +6 -0
- package/dist/src/tools/type-checker.d.ts.map +1 -0
- package/dist/src/tools/type-checker.js +36 -0
- package/dist/src/tools/type-checker.js.map +1 -0
- package/dist/src/tools/type-checker.test.d.ts +2 -0
- package/dist/src/tools/type-checker.test.d.ts.map +1 -0
- package/dist/src/tools/type-checker.test.js +96 -0
- package/dist/src/tools/type-checker.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/inputs/model-a/spec-deltas.json +1460 -0
- package/inputs/model-b/spec-deltas.json +1424 -0
- package/inputs/model-c/spec-deltas.json +1432 -0
- package/inputs/model-d/spec-deltas.json +967 -0
- package/inputs/model-e/spec-deltas.json +2292 -0
- package/ketchup-plan.md +43 -8
- package/package.json +3 -3
- package/scoring-heuristic.md +138 -0
- package/scripts/improve.ts +23 -18
- package/src/commands/implement-component.test.ts +420 -37
- package/src/commands/implement-component.ts +163 -35
- package/src/extract-exports.ts +53 -0
- package/src/generate-story-deterministic.ts +267 -0
- package/src/index.ts +12 -0
- package/src/pipeline/run-pipeline.test.ts +292 -0
- package/src/pipeline/run-pipeline.ts +160 -0
- package/src/pipeline/steps/generate-component.test.ts +130 -0
- package/src/pipeline/steps/generate-component.ts +60 -0
- package/src/pipeline/steps/generate-story.test.ts +54 -0
- package/src/pipeline/steps/generate-story.ts +17 -0
- package/src/pipeline/steps/generate-test.test.ts +75 -0
- package/src/pipeline/steps/generate-test.ts +25 -0
- package/src/pipeline/steps/lint-fix-loop.test.ts +155 -0
- package/src/pipeline/steps/lint-fix-loop.ts +59 -0
- package/src/pipeline/steps/story-fix-loop.test.ts +123 -0
- package/src/pipeline/steps/story-fix-loop.ts +47 -0
- package/src/pipeline/steps/storybook-test.test.ts +82 -0
- package/src/pipeline/steps/storybook-test.ts +27 -0
- package/src/pipeline/steps/test-fix-loop.test.ts +201 -0
- package/src/pipeline/steps/test-fix-loop.ts +56 -0
- package/src/pipeline/steps/type-fix-loop.test.ts +145 -0
- package/src/pipeline/steps/type-fix-loop.ts +55 -0
- package/src/pipeline/steps/visual-test.test.ts +10 -0
- package/src/pipeline/steps/visual-test.ts +5 -0
- package/src/project-context.ts +205 -0
- package/src/prompt.test.ts +253 -8
- package/src/prompt.ts +301 -23
- package/src/scaffold.ts +281 -0
- package/src/spec-contract.test.ts +23 -0
- package/src/spec-contract.ts +1 -1
- package/src/tools/lint-runner.test.ts +112 -0
- package/src/tools/lint-runner.ts +52 -0
- package/src/tools/storybook-runner.test.ts +53 -0
- package/src/tools/storybook-runner.ts +29 -0
- package/src/tools/test-runner.test.ts +213 -0
- package/src/tools/test-runner.ts +84 -0
- package/src/tools/type-checker.test.ts +120 -0
- package/src/tools/type-checker.ts +42 -0
- package/vitest.config.ts +9 -1
- package/dist/src/generate-component.d.ts +0 -4
- package/dist/src/generate-component.d.ts.map +0 -1
- package/dist/src/generate-component.js +0 -14
- package/dist/src/generate-component.js.map +0 -1
- package/dist/src/generate-component.test.d.ts.map +0 -1
- package/dist/src/generate-component.test.js +0 -73
- package/dist/src/generate-component.test.js.map +0 -1
- package/dist/src/generate-story.d.ts +0 -4
- package/dist/src/generate-story.d.ts.map +0 -1
- package/dist/src/generate-story.js +0 -14
- package/dist/src/generate-story.js.map +0 -1
- package/dist/src/generate-story.test.d.ts.map +0 -1
- package/dist/src/generate-story.test.js +0 -58
- package/dist/src/generate-story.test.js.map +0 -1
- package/dist/src/generate-test.d.ts +0 -4
- package/dist/src/generate-test.d.ts.map +0 -1
- package/dist/src/generate-test.js +0 -14
- package/dist/src/generate-test.js.map +0 -1
- package/dist/src/generate-test.test.d.ts.map +0 -1
- package/dist/src/generate-test.test.js +0 -77
- package/dist/src/generate-test.test.js.map +0 -1
- package/dist/src/reconcile.d.ts +0 -8
- package/dist/src/reconcile.d.ts.map +0 -1
- package/dist/src/reconcile.js +0 -18
- package/dist/src/reconcile.js.map +0 -1
- package/dist/src/reconcile.test.d.ts +0 -2
- package/dist/src/reconcile.test.d.ts.map +0 -1
- package/dist/src/reconcile.test.js +0 -108
- package/dist/src/reconcile.test.js.map +0 -1
- package/src/generate-component.test.ts +0 -89
- package/src/generate-component.ts +0 -16
- package/src/generate-story.test.ts +0 -71
- package/src/generate-story.ts +0 -16
- package/src/generate-test.test.ts +0 -93
- package/src/generate-test.ts +0 -16
- package/src/reconcile.test.ts +0 -127
- package/src/reconcile.ts +0 -27
- /package/dist/src/{generate-component.test.d.ts → pipeline/steps/generate-component.test.d.ts} +0 -0
- /package/dist/src/{generate-story.test.d.ts → pipeline/steps/generate-story.test.d.ts} +0 -0
- /package/dist/src/{generate-test.test.d.ts → pipeline/steps/generate-test.test.d.ts} +0 -0
package/src/prompt.test.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
import {
|
|
3
3
|
buildComponentPrompt,
|
|
4
|
+
buildLintFixPrompt,
|
|
4
5
|
buildReconcilerPrompt,
|
|
6
|
+
buildStoryFixPrompt,
|
|
5
7
|
buildStoryPrompt,
|
|
8
|
+
buildTestFixPrompt,
|
|
6
9
|
buildTestPrompt,
|
|
10
|
+
buildTypeFixPrompt,
|
|
7
11
|
componentPromptSections,
|
|
8
12
|
reconcilerPromptSections,
|
|
9
13
|
storyPromptSections,
|
|
@@ -17,16 +21,18 @@ const specDeltas = {
|
|
|
17
21
|
styling: ['applies elevated style when raised=true'],
|
|
18
22
|
};
|
|
19
23
|
|
|
24
|
+
const projectSection = '## Project Dependencies\ntest project context';
|
|
25
|
+
|
|
20
26
|
describe('prompt builders', () => {
|
|
21
27
|
describe('buildComponentPrompt', () => {
|
|
22
28
|
it('returns system and prompt', () => {
|
|
23
|
-
const result = buildComponentPrompt({ componentName: 'Card', specDeltas });
|
|
29
|
+
const result = buildComponentPrompt({ componentName: 'Card', specDeltas, projectSection });
|
|
24
30
|
expect(result.system).toBeTruthy();
|
|
25
31
|
expect(result.prompt).toBeTruthy();
|
|
26
32
|
});
|
|
27
33
|
|
|
28
34
|
it('system prompt contains all sections', () => {
|
|
29
|
-
const { system } = buildComponentPrompt({ componentName: 'Card', specDeltas });
|
|
35
|
+
const { system } = buildComponentPrompt({ componentName: 'Card', specDeltas, projectSection });
|
|
30
36
|
expect(system).toContain('YOUR INPUT');
|
|
31
37
|
expect(system).toContain('YOUR OUTPUT');
|
|
32
38
|
expect(system).toContain('METHODOLOGY');
|
|
@@ -35,7 +41,7 @@ describe('prompt builders', () => {
|
|
|
35
41
|
});
|
|
36
42
|
|
|
37
43
|
it('user prompt includes component name and spec deltas', () => {
|
|
38
|
-
const { prompt } = buildComponentPrompt({ componentName: 'Card', specDeltas });
|
|
44
|
+
const { prompt } = buildComponentPrompt({ componentName: 'Card', specDeltas, projectSection });
|
|
39
45
|
expect(prompt).toContain('**Card**');
|
|
40
46
|
expect(prompt).toContain('renders a Card element');
|
|
41
47
|
expect(prompt).toContain('shows skeleton when loading');
|
|
@@ -46,25 +52,32 @@ describe('prompt builders', () => {
|
|
|
46
52
|
componentName: 'Card',
|
|
47
53
|
specDeltas,
|
|
48
54
|
existingComponent: 'export function Card() {}',
|
|
55
|
+
projectSection,
|
|
49
56
|
});
|
|
50
57
|
expect(prompt).toContain('## Existing Component');
|
|
51
58
|
expect(prompt).toContain('export function Card() {}');
|
|
52
59
|
});
|
|
53
60
|
|
|
54
61
|
it('user prompt omits existing component section when not provided', () => {
|
|
55
|
-
const { prompt } = buildComponentPrompt({ componentName: 'Card', specDeltas });
|
|
62
|
+
const { prompt } = buildComponentPrompt({ componentName: 'Card', specDeltas, projectSection });
|
|
56
63
|
expect(prompt).not.toContain('## Existing Component');
|
|
57
64
|
});
|
|
65
|
+
|
|
66
|
+
it('user prompt includes project section', () => {
|
|
67
|
+
const { prompt } = buildComponentPrompt({ componentName: 'Card', specDeltas, projectSection });
|
|
68
|
+
expect(prompt).toContain('## Project Dependencies');
|
|
69
|
+
expect(prompt).toContain('test project context');
|
|
70
|
+
});
|
|
58
71
|
});
|
|
59
72
|
|
|
60
73
|
describe('buildTestPrompt', () => {
|
|
61
74
|
it('system prompt establishes tests as source of truth', () => {
|
|
62
|
-
const { system } = buildTestPrompt({ componentName: 'Card', specDeltas });
|
|
75
|
+
const { system } = buildTestPrompt({ componentName: 'Card', specDeltas, projectSection });
|
|
63
76
|
expect(system).toContain('source of truth');
|
|
64
77
|
});
|
|
65
78
|
|
|
66
79
|
it('user prompt includes spec deltas', () => {
|
|
67
|
-
const { prompt } = buildTestPrompt({ componentName: 'Card', specDeltas });
|
|
80
|
+
const { prompt } = buildTestPrompt({ componentName: 'Card', specDeltas, projectSection });
|
|
68
81
|
expect(prompt).toContain('## Spec Deltas');
|
|
69
82
|
expect(prompt).toContain('calls onSelect when clicked');
|
|
70
83
|
});
|
|
@@ -74,26 +87,90 @@ describe('prompt builders', () => {
|
|
|
74
87
|
componentName: 'Card',
|
|
75
88
|
specDeltas,
|
|
76
89
|
existingComponent: 'existing code',
|
|
90
|
+
projectSection,
|
|
77
91
|
});
|
|
78
92
|
expect(prompt).toContain('## Existing Component');
|
|
79
93
|
expect(prompt).toContain('existing code');
|
|
80
94
|
});
|
|
95
|
+
|
|
96
|
+
it('user prompt includes project section', () => {
|
|
97
|
+
const { prompt } = buildTestPrompt({ componentName: 'Card', specDeltas, projectSection });
|
|
98
|
+
expect(prompt).toContain('## Project Dependencies');
|
|
99
|
+
expect(prompt).toContain('test project context');
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('system prompt contains Tailwind test rule', () => {
|
|
103
|
+
const { system } = buildTestPrompt({ componentName: 'Card', specDeltas, projectSection });
|
|
104
|
+
expect(system).toContain('Tailwind classes, not inline styles');
|
|
105
|
+
expect(system).toContain('toHaveClass');
|
|
106
|
+
expect(system).toContain('NEVER use `toHaveStyle()`');
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('system prompt contains semantic element verification rule', () => {
|
|
110
|
+
const { system } = buildTestPrompt({ componentName: 'Card', specDeltas, projectSection });
|
|
111
|
+
expect(system).toContain('Verify semantic elements from component source');
|
|
112
|
+
expect(system).toContain('getByText');
|
|
113
|
+
});
|
|
81
114
|
});
|
|
82
115
|
|
|
83
116
|
describe('buildStoryPrompt', () => {
|
|
84
117
|
it('system prompt covers CSF3 and story conventions', () => {
|
|
85
|
-
const { system } = buildStoryPrompt({
|
|
118
|
+
const { system } = buildStoryPrompt({
|
|
119
|
+
componentName: 'Card',
|
|
120
|
+
specDeltas,
|
|
121
|
+
projectSection,
|
|
122
|
+
componentImportPath: '@/components/Card',
|
|
123
|
+
});
|
|
86
124
|
expect(system).toContain('CSF3');
|
|
87
125
|
expect(system).toContain('Meta');
|
|
88
126
|
expect(system).toContain('StoryObj');
|
|
89
127
|
});
|
|
90
128
|
|
|
91
129
|
it('user prompt includes spec deltas without component code', () => {
|
|
92
|
-
const { prompt } = buildStoryPrompt({
|
|
130
|
+
const { prompt } = buildStoryPrompt({
|
|
131
|
+
componentName: 'Card',
|
|
132
|
+
specDeltas,
|
|
133
|
+
projectSection,
|
|
134
|
+
componentImportPath: '@/components/Card',
|
|
135
|
+
});
|
|
93
136
|
expect(prompt).toContain('## Spec Deltas');
|
|
94
137
|
expect(prompt).toContain('applies elevated style when raised=true');
|
|
95
138
|
expect(prompt).not.toContain('## Component Code');
|
|
96
139
|
});
|
|
140
|
+
|
|
141
|
+
it('user prompt includes component code when provided', () => {
|
|
142
|
+
const { prompt } = buildStoryPrompt({
|
|
143
|
+
componentName: 'Card',
|
|
144
|
+
specDeltas,
|
|
145
|
+
projectSection,
|
|
146
|
+
componentImportPath: '@/components/Card',
|
|
147
|
+
componentCode: 'export function Card() {}',
|
|
148
|
+
});
|
|
149
|
+
expect(prompt).toContain('## Component Code');
|
|
150
|
+
expect(prompt).toContain('export function Card() {}');
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('user prompt includes project section', () => {
|
|
154
|
+
const { prompt } = buildStoryPrompt({
|
|
155
|
+
componentName: 'Card',
|
|
156
|
+
specDeltas,
|
|
157
|
+
projectSection,
|
|
158
|
+
componentImportPath: '@/components/Card',
|
|
159
|
+
});
|
|
160
|
+
expect(prompt).toContain('## Project Dependencies');
|
|
161
|
+
expect(prompt).toContain('test project context');
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('user prompt includes component import path', () => {
|
|
165
|
+
const { prompt } = buildStoryPrompt({
|
|
166
|
+
componentName: 'Card',
|
|
167
|
+
specDeltas,
|
|
168
|
+
projectSection,
|
|
169
|
+
componentImportPath: '@/components/Card',
|
|
170
|
+
});
|
|
171
|
+
expect(prompt).toContain('## Component Import Path');
|
|
172
|
+
expect(prompt).toContain("import { Card } from '@/components/Card'");
|
|
173
|
+
});
|
|
97
174
|
});
|
|
98
175
|
|
|
99
176
|
describe('buildReconcilerPrompt', () => {
|
|
@@ -103,6 +180,7 @@ describe('prompt builders', () => {
|
|
|
103
180
|
componentCode: 'component source',
|
|
104
181
|
testCode: 'test source',
|
|
105
182
|
storyCode: 'story source',
|
|
183
|
+
projectSection,
|
|
106
184
|
};
|
|
107
185
|
|
|
108
186
|
it('system prompt establishes test immutability', () => {
|
|
@@ -129,6 +207,96 @@ describe('prompt builders', () => {
|
|
|
129
207
|
expect(prompt).toContain('## Existing Component');
|
|
130
208
|
expect(prompt).toContain('old code');
|
|
131
209
|
});
|
|
210
|
+
|
|
211
|
+
it('user prompt includes project section', () => {
|
|
212
|
+
const { prompt } = buildReconcilerPrompt(reconcileInput);
|
|
213
|
+
expect(prompt).toContain('## Project Dependencies');
|
|
214
|
+
expect(prompt).toContain('test project context');
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
describe('buildComponentPrompt handles undefined specDelta fields', () => {
|
|
219
|
+
const specDeltasWithUndefined = {
|
|
220
|
+
structure: ['renders a Card element'],
|
|
221
|
+
rendering: undefined as unknown as string[],
|
|
222
|
+
interaction: undefined as unknown as string[],
|
|
223
|
+
styling: ['applies elevated style when raised=true'],
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
it('returns valid result when rendering and interaction are undefined', () => {
|
|
227
|
+
const result = buildComponentPrompt({
|
|
228
|
+
componentName: 'Card',
|
|
229
|
+
specDeltas: specDeltasWithUndefined,
|
|
230
|
+
projectSection,
|
|
231
|
+
});
|
|
232
|
+
expect(result.system).toBeTruthy();
|
|
233
|
+
expect(result.prompt).toBeTruthy();
|
|
234
|
+
expect(result.prompt).toContain('renders a Card element');
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
describe('buildTestPrompt handles undefined specDelta fields', () => {
|
|
239
|
+
const specDeltasWithUndefined = {
|
|
240
|
+
structure: undefined as unknown as string[],
|
|
241
|
+
rendering: ['shows skeleton when loading'],
|
|
242
|
+
interaction: undefined as unknown as string[],
|
|
243
|
+
styling: ['applies elevated style when raised=true'],
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
it('returns valid result when structure and interaction are undefined', () => {
|
|
247
|
+
const result = buildTestPrompt({
|
|
248
|
+
componentName: 'Card',
|
|
249
|
+
specDeltas: specDeltasWithUndefined,
|
|
250
|
+
projectSection,
|
|
251
|
+
});
|
|
252
|
+
expect(result.system).toBeTruthy();
|
|
253
|
+
expect(result.prompt).toBeTruthy();
|
|
254
|
+
expect(result.prompt).toContain('shows skeleton when loading');
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
describe('buildStoryPrompt handles undefined specDelta fields', () => {
|
|
259
|
+
const specDeltasWithUndefined = {
|
|
260
|
+
structure: ['renders a Card element'],
|
|
261
|
+
rendering: undefined as unknown as string[],
|
|
262
|
+
interaction: ['calls onSelect when clicked'],
|
|
263
|
+
styling: undefined as unknown as string[],
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
it('returns valid result when rendering and styling are undefined', () => {
|
|
267
|
+
const result = buildStoryPrompt({
|
|
268
|
+
componentName: 'Card',
|
|
269
|
+
specDeltas: specDeltasWithUndefined,
|
|
270
|
+
projectSection,
|
|
271
|
+
componentImportPath: '@/components/Card',
|
|
272
|
+
});
|
|
273
|
+
expect(result.system).toBeTruthy();
|
|
274
|
+
expect(result.prompt).toBeTruthy();
|
|
275
|
+
expect(result.prompt).toContain('renders a Card element');
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
describe('buildReconcilerPrompt handles undefined specDelta fields', () => {
|
|
280
|
+
const specDeltasWithUndefined = {
|
|
281
|
+
structure: ['renders a Card element'],
|
|
282
|
+
rendering: ['shows skeleton when loading'],
|
|
283
|
+
interaction: undefined as unknown as string[],
|
|
284
|
+
styling: undefined as unknown as string[],
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
it('returns valid result when interaction and styling are undefined', () => {
|
|
288
|
+
const result = buildReconcilerPrompt({
|
|
289
|
+
componentName: 'Card',
|
|
290
|
+
specDeltas: specDeltasWithUndefined,
|
|
291
|
+
componentCode: 'component source',
|
|
292
|
+
testCode: 'test source',
|
|
293
|
+
storyCode: 'story source',
|
|
294
|
+
projectSection,
|
|
295
|
+
});
|
|
296
|
+
expect(result.system).toBeTruthy();
|
|
297
|
+
expect(result.prompt).toBeTruthy();
|
|
298
|
+
expect(result.prompt).toContain('renders a Card element');
|
|
299
|
+
});
|
|
132
300
|
});
|
|
133
301
|
|
|
134
302
|
describe('exported prompt sections', () => {
|
|
@@ -160,4 +328,81 @@ describe('prompt builders', () => {
|
|
|
160
328
|
}
|
|
161
329
|
});
|
|
162
330
|
});
|
|
331
|
+
|
|
332
|
+
describe('buildTypeFixPrompt', () => {
|
|
333
|
+
it('includes errors, component code, and test code', () => {
|
|
334
|
+
const result = buildTypeFixPrompt({
|
|
335
|
+
componentCode: 'const x: number = "bad"',
|
|
336
|
+
testCode: 'import { Card } from "./Card"',
|
|
337
|
+
errors: ['src/Card.tsx(1,7): error TS2322: Type string not assignable to number'],
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
expect(result.system).toContain('TypeScript error fixer');
|
|
341
|
+
expect(result.system).toContain('two code blocks');
|
|
342
|
+
expect(result.prompt).toContain('## TypeScript Errors');
|
|
343
|
+
expect(result.prompt).toContain('error TS2322');
|
|
344
|
+
expect(result.prompt).toContain('## Component Code');
|
|
345
|
+
expect(result.prompt).toContain('const x: number = "bad"');
|
|
346
|
+
expect(result.prompt).toContain('## Test Code');
|
|
347
|
+
expect(result.prompt).toContain('import { Card } from "./Card"');
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
describe('buildTestFixPrompt', () => {
|
|
352
|
+
it('includes failures, output, component code, and test code', () => {
|
|
353
|
+
const result = buildTestFixPrompt({
|
|
354
|
+
componentCode: 'export function Card() { return <div /> }',
|
|
355
|
+
testCode: 'expect(screen.getByRole("button")).toBeInTheDocument()',
|
|
356
|
+
failures: ['renders button: Expected element not found'],
|
|
357
|
+
testOutput: 'FAIL src/Card.test.tsx',
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
expect(result.system).toContain('test failure fixer');
|
|
361
|
+
expect(result.system).toContain('source of truth');
|
|
362
|
+
expect(result.prompt).toContain('## Test Failures');
|
|
363
|
+
expect(result.prompt).toContain('Expected element not found');
|
|
364
|
+
expect(result.prompt).toContain('## Test Output');
|
|
365
|
+
expect(result.prompt).toContain('FAIL src/Card.test.tsx');
|
|
366
|
+
expect(result.prompt).toContain('## Component Code');
|
|
367
|
+
expect(result.prompt).toContain('## Test Code');
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
describe('buildLintFixPrompt', () => {
|
|
372
|
+
it('includes errors, component code, and test code', () => {
|
|
373
|
+
const result = buildLintFixPrompt({
|
|
374
|
+
componentCode: 'var x = 1',
|
|
375
|
+
testCode: 'var y = 2',
|
|
376
|
+
errors: ['src/Card.tsx:1:1 lint/style/useConst: Use const instead of var'],
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
expect(result.system).toContain('lint error fixer');
|
|
380
|
+
expect(result.system).toContain('two code blocks');
|
|
381
|
+
expect(result.prompt).toContain('## Lint Errors');
|
|
382
|
+
expect(result.prompt).toContain('useConst');
|
|
383
|
+
expect(result.prompt).toContain('## Component Code');
|
|
384
|
+
expect(result.prompt).toContain('var x = 1');
|
|
385
|
+
expect(result.prompt).toContain('## Test Code');
|
|
386
|
+
expect(result.prompt).toContain('var y = 2');
|
|
387
|
+
});
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
describe('buildStoryFixPrompt', () => {
|
|
391
|
+
it('includes errors, story code, and component code as reference', () => {
|
|
392
|
+
const result = buildStoryFixPrompt({
|
|
393
|
+
storyCode: 'import { Card } from "./Card"',
|
|
394
|
+
componentCode: 'export function Card() {}',
|
|
395
|
+
errors: ['src/Card.stories.tsx(1,10): error TS2305: Module has no exported member'],
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
expect(result.system).toContain('Storybook story fixer');
|
|
399
|
+
expect(result.system).toContain('one code block');
|
|
400
|
+
expect(result.prompt).toContain('## TypeScript Errors');
|
|
401
|
+
expect(result.prompt).toContain('error TS2305');
|
|
402
|
+
expect(result.prompt).toContain('## Story Code');
|
|
403
|
+
expect(result.prompt).toContain('import { Card } from "./Card"');
|
|
404
|
+
expect(result.prompt).toContain('## Component Code (reference)');
|
|
405
|
+
expect(result.prompt).toContain('export function Card() {}');
|
|
406
|
+
});
|
|
407
|
+
});
|
|
163
408
|
});
|