codemeld 2.1.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/README.md +514 -0
- package/bin/cli.js +2 -0
- package/dist/ai/agent.d.ts +124 -0
- package/dist/ai/agent.d.ts.map +1 -0
- package/dist/ai/agent.js +289 -0
- package/dist/ai/agent.js.map +1 -0
- package/dist/ai/index.d.ts +10 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +10 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/prompts.d.ts +35 -0
- package/dist/ai/prompts.d.ts.map +1 -0
- package/dist/ai/prompts.js +166 -0
- package/dist/ai/prompts.js.map +1 -0
- package/dist/ai/refinement-loop.d.ts +29 -0
- package/dist/ai/refinement-loop.d.ts.map +1 -0
- package/dist/ai/refinement-loop.js +180 -0
- package/dist/ai/refinement-loop.js.map +1 -0
- package/dist/ai/tools.d.ts +17 -0
- package/dist/ai/tools.d.ts.map +1 -0
- package/dist/ai/tools.js +353 -0
- package/dist/ai/tools.js.map +1 -0
- package/dist/ai/visual-compare.d.ts +43 -0
- package/dist/ai/visual-compare.d.ts.map +1 -0
- package/dist/ai/visual-compare.js +176 -0
- package/dist/ai/visual-compare.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +179 -0
- package/dist/cli.js.map +1 -0
- package/dist/converter.d.ts +10 -0
- package/dist/converter.d.ts.map +1 -0
- package/dist/converter.js +836 -0
- package/dist/converter.js.map +1 -0
- package/dist/deconverter.d.ts +19 -0
- package/dist/deconverter.d.ts.map +1 -0
- package/dist/deconverter.js +188 -0
- package/dist/deconverter.js.map +1 -0
- package/dist/frameworks/angular-adapter.d.ts +27 -0
- package/dist/frameworks/angular-adapter.d.ts.map +1 -0
- package/dist/frameworks/angular-adapter.js +617 -0
- package/dist/frameworks/angular-adapter.js.map +1 -0
- package/dist/frameworks/index.d.ts +10 -0
- package/dist/frameworks/index.d.ts.map +1 -0
- package/dist/frameworks/index.js +21 -0
- package/dist/frameworks/index.js.map +1 -0
- package/dist/frameworks/nextjs-adapter.d.ts +22 -0
- package/dist/frameworks/nextjs-adapter.d.ts.map +1 -0
- package/dist/frameworks/nextjs-adapter.js +392 -0
- package/dist/frameworks/nextjs-adapter.js.map +1 -0
- package/dist/frameworks/react-adapter.d.ts +21 -0
- package/dist/frameworks/react-adapter.d.ts.map +1 -0
- package/dist/frameworks/react-adapter.js +71 -0
- package/dist/frameworks/react-adapter.js.map +1 -0
- package/dist/frameworks/svelte-adapter.d.ts +27 -0
- package/dist/frameworks/svelte-adapter.d.ts.map +1 -0
- package/dist/frameworks/svelte-adapter.js +519 -0
- package/dist/frameworks/svelte-adapter.js.map +1 -0
- package/dist/frameworks/types.d.ts +78 -0
- package/dist/frameworks/types.d.ts.map +1 -0
- package/dist/frameworks/types.js +2 -0
- package/dist/frameworks/types.js.map +1 -0
- package/dist/frameworks/vue-adapter.d.ts +34 -0
- package/dist/frameworks/vue-adapter.d.ts.map +1 -0
- package/dist/frameworks/vue-adapter.js +632 -0
- package/dist/frameworks/vue-adapter.js.map +1 -0
- package/dist/generators/accessibility-generator.d.ts +43 -0
- package/dist/generators/accessibility-generator.d.ts.map +1 -0
- package/dist/generators/accessibility-generator.js +507 -0
- package/dist/generators/accessibility-generator.js.map +1 -0
- package/dist/generators/asset-handler.d.ts +14 -0
- package/dist/generators/asset-handler.d.ts.map +1 -0
- package/dist/generators/asset-handler.js +79 -0
- package/dist/generators/asset-handler.js.map +1 -0
- package/dist/generators/build-verifier.d.ts +8 -0
- package/dist/generators/build-verifier.d.ts.map +1 -0
- package/dist/generators/build-verifier.js +64 -0
- package/dist/generators/build-verifier.js.map +1 -0
- package/dist/generators/component-extractor.d.ts +25 -0
- package/dist/generators/component-extractor.d.ts.map +1 -0
- package/dist/generators/component-extractor.js +146 -0
- package/dist/generators/component-extractor.js.map +1 -0
- package/dist/generators/component-generator.d.ts +12 -0
- package/dist/generators/component-generator.d.ts.map +1 -0
- package/dist/generators/component-generator.js +724 -0
- package/dist/generators/component-generator.js.map +1 -0
- package/dist/generators/deploy-generator.d.ts +9 -0
- package/dist/generators/deploy-generator.d.ts.map +1 -0
- package/dist/generators/deploy-generator.js +409 -0
- package/dist/generators/deploy-generator.js.map +1 -0
- package/dist/generators/error-boundary.d.ts +5 -0
- package/dist/generators/error-boundary.d.ts.map +1 -0
- package/dist/generators/error-boundary.js +59 -0
- package/dist/generators/error-boundary.js.map +1 -0
- package/dist/generators/form-generator.d.ts +42 -0
- package/dist/generators/form-generator.d.ts.map +1 -0
- package/dist/generators/form-generator.js +662 -0
- package/dist/generators/form-generator.js.map +1 -0
- package/dist/generators/hooks-generator.d.ts +40 -0
- package/dist/generators/hooks-generator.d.ts.map +1 -0
- package/dist/generators/hooks-generator.js +297 -0
- package/dist/generators/hooks-generator.js.map +1 -0
- package/dist/generators/html-generator.d.ts +27 -0
- package/dist/generators/html-generator.d.ts.map +1 -0
- package/dist/generators/html-generator.js +772 -0
- package/dist/generators/html-generator.js.map +1 -0
- package/dist/generators/jquery-converter.d.ts +41 -0
- package/dist/generators/jquery-converter.d.ts.map +1 -0
- package/dist/generators/jquery-converter.js +594 -0
- package/dist/generators/jquery-converter.js.map +1 -0
- package/dist/generators/pattern-implementer.d.ts +26 -0
- package/dist/generators/pattern-implementer.d.ts.map +1 -0
- package/dist/generators/pattern-implementer.js +336 -0
- package/dist/generators/pattern-implementer.js.map +1 -0
- package/dist/generators/performance-generator.d.ts +51 -0
- package/dist/generators/performance-generator.d.ts.map +1 -0
- package/dist/generators/performance-generator.js +428 -0
- package/dist/generators/performance-generator.js.map +1 -0
- package/dist/generators/router-generator.d.ts +21 -0
- package/dist/generators/router-generator.d.ts.map +1 -0
- package/dist/generators/router-generator.js +178 -0
- package/dist/generators/router-generator.js.map +1 -0
- package/dist/generators/scaffolder.d.ts +28 -0
- package/dist/generators/scaffolder.d.ts.map +1 -0
- package/dist/generators/scaffolder.js +266 -0
- package/dist/generators/scaffolder.js.map +1 -0
- package/dist/generators/seo-generator.d.ts +29 -0
- package/dist/generators/seo-generator.d.ts.map +1 -0
- package/dist/generators/seo-generator.js +223 -0
- package/dist/generators/seo-generator.js.map +1 -0
- package/dist/generators/test-generator.d.ts +19 -0
- package/dist/generators/test-generator.d.ts.map +1 -0
- package/dist/generators/test-generator.js +398 -0
- package/dist/generators/test-generator.js.map +1 -0
- package/dist/generators/type-generator.d.ts +33 -0
- package/dist/generators/type-generator.d.ts.map +1 -0
- package/dist/generators/type-generator.js +663 -0
- package/dist/generators/type-generator.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/parsers/css-processor.d.ts +23 -0
- package/dist/parsers/css-processor.d.ts.map +1 -0
- package/dist/parsers/css-processor.js +129 -0
- package/dist/parsers/css-processor.js.map +1 -0
- package/dist/parsers/framework-parser.d.ts +48 -0
- package/dist/parsers/framework-parser.d.ts.map +1 -0
- package/dist/parsers/framework-parser.js +770 -0
- package/dist/parsers/framework-parser.js.map +1 -0
- package/dist/parsers/html-parser.d.ts +12 -0
- package/dist/parsers/html-parser.d.ts.map +1 -0
- package/dist/parsers/html-parser.js +444 -0
- package/dist/parsers/html-parser.js.map +1 -0
- package/dist/parsers/js-analyzer.d.ts +199 -0
- package/dist/parsers/js-analyzer.d.ts.map +1 -0
- package/dist/parsers/js-analyzer.js +680 -0
- package/dist/parsers/js-analyzer.js.map +1 -0
- package/dist/parsers/js-resolver.d.ts +8 -0
- package/dist/parsers/js-resolver.d.ts.map +1 -0
- package/dist/parsers/js-resolver.js +45 -0
- package/dist/parsers/js-resolver.js.map +1 -0
- package/dist/parsers/tailwind-detector.d.ts +23 -0
- package/dist/parsers/tailwind-detector.d.ts.map +1 -0
- package/dist/parsers/tailwind-detector.js +104 -0
- package/dist/parsers/tailwind-detector.js.map +1 -0
- package/dist/tests/advanced-features.test.d.ts +2 -0
- package/dist/tests/advanced-features.test.d.ts.map +1 -0
- package/dist/tests/advanced-features.test.js +235 -0
- package/dist/tests/advanced-features.test.js.map +1 -0
- package/dist/tests/css-modules.test.d.ts +2 -0
- package/dist/tests/css-modules.test.d.ts.map +1 -0
- package/dist/tests/css-modules.test.js +61 -0
- package/dist/tests/css-modules.test.js.map +1 -0
- package/dist/tests/css-processor.test.d.ts +2 -0
- package/dist/tests/css-processor.test.d.ts.map +1 -0
- package/dist/tests/css-processor.test.js +48 -0
- package/dist/tests/css-processor.test.js.map +1 -0
- package/dist/tests/html-parser.test.d.ts +2 -0
- package/dist/tests/html-parser.test.d.ts.map +1 -0
- package/dist/tests/html-parser.test.js +78 -0
- package/dist/tests/html-parser.test.js.map +1 -0
- package/dist/tests/integration.test.d.ts +2 -0
- package/dist/tests/integration.test.d.ts.map +1 -0
- package/dist/tests/integration.test.js +65 -0
- package/dist/tests/integration.test.js.map +1 -0
- package/dist/tests/js-analyzer.test.d.ts +2 -0
- package/dist/tests/js-analyzer.test.d.ts.map +1 -0
- package/dist/tests/js-analyzer.test.js +58 -0
- package/dist/tests/js-analyzer.test.js.map +1 -0
- package/dist/tests/naming.test.d.ts +2 -0
- package/dist/tests/naming.test.d.ts.map +1 -0
- package/dist/tests/naming.test.js +43 -0
- package/dist/tests/naming.test.js.map +1 -0
- package/dist/tests/router-generator.test.d.ts +2 -0
- package/dist/tests/router-generator.test.d.ts.map +1 -0
- package/dist/tests/router-generator.test.js +60 -0
- package/dist/tests/router-generator.test.js.map +1 -0
- package/dist/tui/chat.d.ts +13 -0
- package/dist/tui/chat.d.ts.map +1 -0
- package/dist/tui/chat.js +499 -0
- package/dist/tui/chat.js.map +1 -0
- package/dist/tui/design-guide.d.ts +41 -0
- package/dist/tui/design-guide.d.ts.map +1 -0
- package/dist/tui/design-guide.js +184 -0
- package/dist/tui/design-guide.js.map +1 -0
- package/dist/tui/input.d.ts +30 -0
- package/dist/tui/input.d.ts.map +1 -0
- package/dist/tui/input.js +239 -0
- package/dist/tui/input.js.map +1 -0
- package/dist/tui/renderer.d.ts +48 -0
- package/dist/tui/renderer.d.ts.map +1 -0
- package/dist/tui/renderer.js +212 -0
- package/dist/tui/renderer.js.map +1 -0
- package/dist/tui/tools.d.ts +14 -0
- package/dist/tui/tools.d.ts.map +1 -0
- package/dist/tui/tools.js +1370 -0
- package/dist/tui/tools.js.map +1 -0
- package/dist/types.d.ts +93 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/config.d.ts +20 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +33 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/formatter.d.ts +5 -0
- package/dist/utils/formatter.d.ts.map +1 -0
- package/dist/utils/formatter.js +68 -0
- package/dist/utils/formatter.js.map +1 -0
- package/dist/utils/logger.d.ts +8 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +19 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/naming.d.ts +17 -0
- package/dist/utils/naming.d.ts.map +1 -0
- package/dist/utils/naming.js +48 -0
- package/dist/utils/naming.js.map +1 -0
- package/dist/utils/report.d.ts +56 -0
- package/dist/utils/report.d.ts.map +1 -0
- package/dist/utils/report.js +339 -0
- package/dist/utils/report.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate a vitest.config.ts file for the converted project.
|
|
3
|
+
*/
|
|
4
|
+
export function generateVitestConfig() {
|
|
5
|
+
return `/// <reference types="vitest" />
|
|
6
|
+
import { defineConfig } from 'vite';
|
|
7
|
+
import react from '@vitejs/plugin-react';
|
|
8
|
+
|
|
9
|
+
export default defineConfig({
|
|
10
|
+
plugins: [react()],
|
|
11
|
+
test: {
|
|
12
|
+
globals: true,
|
|
13
|
+
environment: 'jsdom',
|
|
14
|
+
setupFiles: ['./src/test/setup.ts'],
|
|
15
|
+
css: true,
|
|
16
|
+
include: ['src/**/*.{test,spec}.{ts,tsx}'],
|
|
17
|
+
coverage: {
|
|
18
|
+
provider: 'v8',
|
|
19
|
+
reporter: ['text', 'json', 'html'],
|
|
20
|
+
include: ['src/components/**/*.tsx'],
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
`;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Generate the test setup file (src/test/setup.ts) with testing-library matchers.
|
|
28
|
+
*/
|
|
29
|
+
export function generateTestSetup() {
|
|
30
|
+
return `import '@testing-library/jest-dom/vitest';
|
|
31
|
+
import { cleanup } from '@testing-library/react';
|
|
32
|
+
import { afterEach } from 'vitest';
|
|
33
|
+
|
|
34
|
+
// Automatic cleanup after each test
|
|
35
|
+
afterEach(() => {
|
|
36
|
+
cleanup();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Mock window.matchMedia for components that use media queries
|
|
40
|
+
Object.defineProperty(window, 'matchMedia', {
|
|
41
|
+
writable: true,
|
|
42
|
+
value: (query: string) => ({
|
|
43
|
+
matches: false,
|
|
44
|
+
media: query,
|
|
45
|
+
onchange: null,
|
|
46
|
+
addListener: () => {},
|
|
47
|
+
removeListener: () => {},
|
|
48
|
+
addEventListener: () => {},
|
|
49
|
+
removeEventListener: () => {},
|
|
50
|
+
dispatchEvent: () => false,
|
|
51
|
+
}),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Mock IntersectionObserver for scroll-based components
|
|
55
|
+
class MockIntersectionObserver {
|
|
56
|
+
observe() {}
|
|
57
|
+
unobserve() {}
|
|
58
|
+
disconnect() {}
|
|
59
|
+
}
|
|
60
|
+
Object.defineProperty(window, 'IntersectionObserver', {
|
|
61
|
+
writable: true,
|
|
62
|
+
value: MockIntersectionObserver,
|
|
63
|
+
});
|
|
64
|
+
`;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Generate a test file for a specific component.
|
|
68
|
+
*/
|
|
69
|
+
export function generateComponentTest(component, analysis) {
|
|
70
|
+
const imports = buildImports(component, analysis);
|
|
71
|
+
const tests = buildTests(component, analysis);
|
|
72
|
+
return `${imports}
|
|
73
|
+
|
|
74
|
+
describe('${component.name}', () => {
|
|
75
|
+
${tests}
|
|
76
|
+
});
|
|
77
|
+
`;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Return the devDependency packages needed for the test infrastructure.
|
|
81
|
+
*/
|
|
82
|
+
export function generateTestPackageDeps() {
|
|
83
|
+
return {
|
|
84
|
+
'vitest': '^1.6.0',
|
|
85
|
+
'@testing-library/react': '^15.0.0',
|
|
86
|
+
'@testing-library/jest-dom': '^6.4.0',
|
|
87
|
+
'@testing-library/user-event': '^14.5.0',
|
|
88
|
+
'@vitest/coverage-v8': '^1.6.0',
|
|
89
|
+
'jsdom': '^24.0.0',
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
// Internal helpers
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
function needsRouter(component) {
|
|
96
|
+
return (component.jsx.includes('<Link') ||
|
|
97
|
+
component.jsx.includes('<NavLink') ||
|
|
98
|
+
component.jsx.includes('useNavigate') ||
|
|
99
|
+
component.jsx.includes('useLocation') ||
|
|
100
|
+
component.hooks.has('useNavigate') ||
|
|
101
|
+
component.hooks.has('useLocation'));
|
|
102
|
+
}
|
|
103
|
+
function hasForm(component, analysis) {
|
|
104
|
+
if (component.jsx.includes('<form') || component.jsx.includes('<Form'))
|
|
105
|
+
return true;
|
|
106
|
+
if (analysis?.interactivePatterns?.formHandlers?.length)
|
|
107
|
+
return true;
|
|
108
|
+
if (analysis?.interactivePatterns?.formValidations?.length)
|
|
109
|
+
return true;
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
function buildImports(component, analysis) {
|
|
113
|
+
const lines = [];
|
|
114
|
+
// Core testing imports
|
|
115
|
+
lines.push(`import { describe, it, expect, vi } from 'vitest';`);
|
|
116
|
+
// Determine which testing-library utilities we need
|
|
117
|
+
const tlUtils = new Set(['render', 'screen']);
|
|
118
|
+
if (component.eventHandlers.length || hasForm(component, analysis)) {
|
|
119
|
+
tlUtils.add('fireEvent');
|
|
120
|
+
}
|
|
121
|
+
if (analysis?.fetchCalls?.length) {
|
|
122
|
+
tlUtils.add('waitFor');
|
|
123
|
+
}
|
|
124
|
+
lines.push(`import { ${[...tlUtils].join(', ')} } from '@testing-library/react';`);
|
|
125
|
+
if (component.eventHandlers.length || hasForm(component, analysis)) {
|
|
126
|
+
lines.push(`import userEvent from '@testing-library/user-event';`);
|
|
127
|
+
}
|
|
128
|
+
// Router wrapper
|
|
129
|
+
if (needsRouter(component)) {
|
|
130
|
+
lines.push(`import { MemoryRouter } from 'react-router-dom';`);
|
|
131
|
+
}
|
|
132
|
+
// Component under test
|
|
133
|
+
lines.push(`import ${component.name} from './${component.name}';`);
|
|
134
|
+
return lines.join('\n');
|
|
135
|
+
}
|
|
136
|
+
function indent(text, level) {
|
|
137
|
+
const pad = ' '.repeat(level);
|
|
138
|
+
return text
|
|
139
|
+
.split('\n')
|
|
140
|
+
.map((l) => (l.trim() ? pad + l : ''))
|
|
141
|
+
.join('\n');
|
|
142
|
+
}
|
|
143
|
+
function renderCall(component) {
|
|
144
|
+
if (needsRouter(component)) {
|
|
145
|
+
return `render(
|
|
146
|
+
<MemoryRouter>
|
|
147
|
+
<${component.name} />
|
|
148
|
+
</MemoryRouter>
|
|
149
|
+
)`;
|
|
150
|
+
}
|
|
151
|
+
return `render(<${component.name} />)`;
|
|
152
|
+
}
|
|
153
|
+
function buildTests(component, analysis) {
|
|
154
|
+
const blocks = [];
|
|
155
|
+
// 1. Basic render test
|
|
156
|
+
blocks.push(buildRenderTest(component));
|
|
157
|
+
// 2. Snapshot test
|
|
158
|
+
blocks.push(buildSnapshotTest(component));
|
|
159
|
+
// 3. State interaction tests
|
|
160
|
+
if (component.stateVars.length > 0) {
|
|
161
|
+
blocks.push(buildStateTests(component));
|
|
162
|
+
}
|
|
163
|
+
// 4. Event handler tests
|
|
164
|
+
if (component.eventHandlers.length > 0) {
|
|
165
|
+
blocks.push(buildEventHandlerTests(component));
|
|
166
|
+
}
|
|
167
|
+
// 5. Form submission tests
|
|
168
|
+
if (hasForm(component, analysis)) {
|
|
169
|
+
blocks.push(buildFormTests(component, analysis));
|
|
170
|
+
}
|
|
171
|
+
// 6. Async / fetch tests
|
|
172
|
+
if (analysis?.fetchCalls?.length) {
|
|
173
|
+
blocks.push(buildAsyncTests(component, analysis));
|
|
174
|
+
}
|
|
175
|
+
return blocks.join('\n\n');
|
|
176
|
+
}
|
|
177
|
+
// -- Individual test builders -----------------------------------------------
|
|
178
|
+
function buildRenderTest(component) {
|
|
179
|
+
return indent(`it('renders without crashing', () => {
|
|
180
|
+
${renderCall(component)};
|
|
181
|
+
expect(document.querySelector('.${camelToKebab(component.name)}') || document.body.firstChild).toBeTruthy();
|
|
182
|
+
});`, 1);
|
|
183
|
+
}
|
|
184
|
+
function buildSnapshotTest(component) {
|
|
185
|
+
return indent(`it('matches snapshot', () => {
|
|
186
|
+
const { container } = ${renderCall(component)};
|
|
187
|
+
expect(container).toMatchSnapshot();
|
|
188
|
+
});`, 1);
|
|
189
|
+
}
|
|
190
|
+
function buildStateTests(component) {
|
|
191
|
+
const tests = component.stateVars.map((sv) => {
|
|
192
|
+
const label = camelToWords(sv.name);
|
|
193
|
+
// If the initial value is a boolean, we can test toggle behaviour
|
|
194
|
+
if (sv.initialValue === 'false' || sv.initialValue === 'true') {
|
|
195
|
+
return indent(`it('toggles ${label} state', async () => {
|
|
196
|
+
const user = userEvent.setup();
|
|
197
|
+
${renderCall(component)};
|
|
198
|
+
|
|
199
|
+
// Find the interactive element that likely controls "${sv.name}"
|
|
200
|
+
const toggleEl =
|
|
201
|
+
screen.queryByRole('button', { name: new RegExp('${label}', 'i') }) ??
|
|
202
|
+
screen.queryByText(new RegExp('${label}', 'i'));
|
|
203
|
+
|
|
204
|
+
if (toggleEl) {
|
|
205
|
+
await user.click(toggleEl);
|
|
206
|
+
// After click the DOM should have changed
|
|
207
|
+
expect(toggleEl).toBeInTheDocument();
|
|
208
|
+
}
|
|
209
|
+
});`, 1);
|
|
210
|
+
}
|
|
211
|
+
// Numeric counters
|
|
212
|
+
if (/^\d+$/.test(sv.initialValue)) {
|
|
213
|
+
return indent(`it('updates ${label} state', async () => {
|
|
214
|
+
const user = userEvent.setup();
|
|
215
|
+
${renderCall(component)};
|
|
216
|
+
|
|
217
|
+
// Look for an element displaying the initial value
|
|
218
|
+
const display = screen.queryByText('${sv.initialValue}');
|
|
219
|
+
if (display) {
|
|
220
|
+
expect(display).toBeInTheDocument();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Attempt to find a button that changes the value
|
|
224
|
+
const trigger =
|
|
225
|
+
screen.queryByRole('button', { name: new RegExp('${label}|increment|add', 'i') }) ??
|
|
226
|
+
screen.queryByRole('button');
|
|
227
|
+
if (trigger) {
|
|
228
|
+
await user.click(trigger);
|
|
229
|
+
}
|
|
230
|
+
});`, 1);
|
|
231
|
+
}
|
|
232
|
+
// String / generic state
|
|
233
|
+
return indent(`it('manages ${label} state', () => {
|
|
234
|
+
const { container } = ${renderCall(component)};
|
|
235
|
+
// "${sv.name}" initialised to ${sv.initialValue}
|
|
236
|
+
expect(container).toBeTruthy();
|
|
237
|
+
});`, 1);
|
|
238
|
+
});
|
|
239
|
+
return tests.join('\n\n');
|
|
240
|
+
}
|
|
241
|
+
function buildEventHandlerTests(component) {
|
|
242
|
+
const tests = component.eventHandlers.map((eh) => {
|
|
243
|
+
const eventName = eh.event.replace(/^on/, '').toLowerCase();
|
|
244
|
+
const label = camelToWords(eh.handler);
|
|
245
|
+
// Map common React event names to fireEvent methods
|
|
246
|
+
const fireEventMethod = mapEventToFireEvent(eventName);
|
|
247
|
+
return indent(`it('handles ${eventName} event (${label})', async () => {
|
|
248
|
+
const user = userEvent.setup();
|
|
249
|
+
${renderCall(component)};
|
|
250
|
+
|
|
251
|
+
// Find the element that has the ${eventName} handler
|
|
252
|
+
const target =
|
|
253
|
+
screen.queryByRole('button') ??
|
|
254
|
+
screen.queryByRole('link') ??
|
|
255
|
+
document.querySelector('${eh.elementSelector || '*'}');
|
|
256
|
+
|
|
257
|
+
if (target) {
|
|
258
|
+
${fireEventMethod === 'click'
|
|
259
|
+
? 'await user.click(target);'
|
|
260
|
+
: `fireEvent.${fireEventMethod}(target);`}
|
|
261
|
+
// Verify the component is still mounted after event
|
|
262
|
+
expect(target).toBeInTheDocument();
|
|
263
|
+
}
|
|
264
|
+
});`, 1);
|
|
265
|
+
});
|
|
266
|
+
return tests.join('\n\n');
|
|
267
|
+
}
|
|
268
|
+
function buildFormTests(component, analysis) {
|
|
269
|
+
const formHandlers = analysis?.interactivePatterns?.formHandlers ?? [];
|
|
270
|
+
const hasEmail = formHandlers.some((fh) => fh.isEmail);
|
|
271
|
+
const emailBlock = hasEmail
|
|
272
|
+
? `
|
|
273
|
+
// Fill in email field
|
|
274
|
+
const emailInput = screen.queryByRole('textbox', { name: /email/i }) ??
|
|
275
|
+
screen.queryByPlaceholderText(/email/i) ??
|
|
276
|
+
container.querySelector('input[type="email"]');
|
|
277
|
+
if (emailInput) {
|
|
278
|
+
await user.clear(emailInput);
|
|
279
|
+
await user.type(emailInput, 'test@example.com');
|
|
280
|
+
expect(emailInput).toHaveValue('test@example.com');
|
|
281
|
+
}`
|
|
282
|
+
: '';
|
|
283
|
+
return indent(`it('handles form submission', async () => {
|
|
284
|
+
const user = userEvent.setup();
|
|
285
|
+
const { container } = ${renderCall(component)};
|
|
286
|
+
|
|
287
|
+
const form = container.querySelector('form');
|
|
288
|
+
expect(form).toBeTruthy();
|
|
289
|
+
|
|
290
|
+
// Fill in text inputs
|
|
291
|
+
const textInputs = container.querySelectorAll('input[type="text"], input:not([type])');
|
|
292
|
+
for (const input of textInputs) {
|
|
293
|
+
await user.clear(input as HTMLElement);
|
|
294
|
+
await user.type(input as HTMLElement, 'test value');
|
|
295
|
+
}
|
|
296
|
+
${emailBlock}
|
|
297
|
+
|
|
298
|
+
// Submit
|
|
299
|
+
const submitBtn =
|
|
300
|
+
screen.queryByRole('button', { name: /submit|send|save/i }) ??
|
|
301
|
+
container.querySelector('button[type="submit"]') ??
|
|
302
|
+
container.querySelector('input[type="submit"]');
|
|
303
|
+
if (submitBtn) {
|
|
304
|
+
await user.click(submitBtn);
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it('validates required fields', async () => {
|
|
309
|
+
const user = userEvent.setup();
|
|
310
|
+
const { container } = ${renderCall(component)};
|
|
311
|
+
|
|
312
|
+
// Try submitting without filling required fields
|
|
313
|
+
const submitBtn =
|
|
314
|
+
screen.queryByRole('button', { name: /submit|send|save/i }) ??
|
|
315
|
+
container.querySelector('button[type="submit"]');
|
|
316
|
+
if (submitBtn) {
|
|
317
|
+
await user.click(submitBtn);
|
|
318
|
+
// Check if validation messages appear
|
|
319
|
+
const errorMessages = container.querySelectorAll('[class*="error"], [class*="invalid"], [role="alert"]');
|
|
320
|
+
// Component should still be mounted
|
|
321
|
+
expect(container).toBeTruthy();
|
|
322
|
+
}
|
|
323
|
+
});`, 1);
|
|
324
|
+
}
|
|
325
|
+
function buildAsyncTests(component, analysis) {
|
|
326
|
+
const fetchCalls = analysis.fetchCalls ?? [];
|
|
327
|
+
const firstFetch = fetchCalls[0];
|
|
328
|
+
const url = firstFetch?.url ?? '/api/data';
|
|
329
|
+
return indent(`it('handles async data fetching', async () => {
|
|
330
|
+
// Mock fetch
|
|
331
|
+
const mockData = { data: 'test' };
|
|
332
|
+
const fetchSpy = vi.spyOn(globalThis, 'fetch').mockResolvedValue(
|
|
333
|
+
new Response(JSON.stringify(mockData), {
|
|
334
|
+
status: 200,
|
|
335
|
+
headers: { 'Content-Type': 'application/json' },
|
|
336
|
+
}),
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
${renderCall(component)};
|
|
340
|
+
|
|
341
|
+
await waitFor(() => {
|
|
342
|
+
// Verify fetch was called
|
|
343
|
+
expect(fetchSpy).toHaveBeenCalled();
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
fetchSpy.mockRestore();
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
it('handles fetch error gracefully', async () => {
|
|
350
|
+
const fetchSpy = vi.spyOn(globalThis, 'fetch').mockRejectedValue(
|
|
351
|
+
new Error('Network error'),
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
${renderCall(component)};
|
|
355
|
+
|
|
356
|
+
await waitFor(() => {
|
|
357
|
+
expect(fetchSpy).toHaveBeenCalled();
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
// Component should not crash on error
|
|
361
|
+
expect(document.body.firstChild).toBeTruthy();
|
|
362
|
+
|
|
363
|
+
fetchSpy.mockRestore();
|
|
364
|
+
});`, 1);
|
|
365
|
+
}
|
|
366
|
+
// -- Utility helpers --------------------------------------------------------
|
|
367
|
+
function camelToKebab(str) {
|
|
368
|
+
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
|
369
|
+
}
|
|
370
|
+
function camelToWords(str) {
|
|
371
|
+
return str
|
|
372
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
373
|
+
.replace(/[_-]/g, ' ')
|
|
374
|
+
.toLowerCase();
|
|
375
|
+
}
|
|
376
|
+
function mapEventToFireEvent(event) {
|
|
377
|
+
const map = {
|
|
378
|
+
click: 'click',
|
|
379
|
+
submit: 'submit',
|
|
380
|
+
change: 'change',
|
|
381
|
+
input: 'input',
|
|
382
|
+
focus: 'focus',
|
|
383
|
+
blur: 'blur',
|
|
384
|
+
keydown: 'keyDown',
|
|
385
|
+
keyup: 'keyUp',
|
|
386
|
+
keypress: 'keyPress',
|
|
387
|
+
mouseover: 'mouseOver',
|
|
388
|
+
mouseout: 'mouseOut',
|
|
389
|
+
mouseenter: 'mouseEnter',
|
|
390
|
+
mouseleave: 'mouseLeave',
|
|
391
|
+
scroll: 'scroll',
|
|
392
|
+
resize: 'resize',
|
|
393
|
+
touchstart: 'touchStart',
|
|
394
|
+
touchend: 'touchEnd',
|
|
395
|
+
};
|
|
396
|
+
return map[event] ?? 'click';
|
|
397
|
+
}
|
|
398
|
+
//# sourceMappingURL=test-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-generator.js","sourceRoot":"","sources":["../../src/generators/test-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ExtractedComponent, StateVariable } from '../types.js';
|
|
2
|
+
import type { AnalyzedJS, FetchCall } from '../parsers/js-analyzer.js';
|
|
3
|
+
export interface PropType {
|
|
4
|
+
name: string;
|
|
5
|
+
type: string;
|
|
6
|
+
required: boolean;
|
|
7
|
+
defaultValue?: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Analyzes component JSX for props usage and infers TypeScript types
|
|
12
|
+
* from usage context. Scans for `{props.x}` and destructured props patterns.
|
|
13
|
+
*/
|
|
14
|
+
export declare function inferPropTypes(component: ExtractedComponent): PropType[];
|
|
15
|
+
/**
|
|
16
|
+
* Generates complete TypeScript interface definitions for a component's props and state.
|
|
17
|
+
*/
|
|
18
|
+
export declare function generateTypeDefinitions(component: ExtractedComponent, analysis?: AnalyzedJS): string;
|
|
19
|
+
/**
|
|
20
|
+
* Analyzes fetch call URLs and patterns to generate response type interfaces.
|
|
21
|
+
* Groups endpoints by path and generates typed response interfaces.
|
|
22
|
+
*/
|
|
23
|
+
export declare function inferApiResponseType(fetchCalls: FetchCall[]): string;
|
|
24
|
+
/**
|
|
25
|
+
* Generates global type definitions file content suitable for a `global.d.ts` file.
|
|
26
|
+
*/
|
|
27
|
+
export declare function generateGlobalTypes(): string;
|
|
28
|
+
/**
|
|
29
|
+
* Maps state variable names and initial values to TypeScript types.
|
|
30
|
+
* Analyzes literal values and setter usage patterns to infer accurate types.
|
|
31
|
+
*/
|
|
32
|
+
export declare function inferStateTypes(stateVars: StateVariable[]): Map<string, string>;
|
|
33
|
+
//# sourceMappingURL=type-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-generator.d.ts","sourceRoot":"","sources":["../../src/generators/type-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAEvE,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,kBAAkB,GAAG,QAAQ,EAAE,CA8ExE;AA8LD;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,kBAAkB,EAAE,QAAQ,CAAC,EAAE,UAAU,GAAG,MAAM,CAmEpG;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,MAAM,CAgDpE;AA8CD;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CA8G5C;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAS/E"}
|