first commit

This commit is contained in:
Sylvain Duchesne
2026-01-18 11:53:42 +01:00
commit f04f15d926
112 changed files with 24858 additions and 0 deletions
+120
View File
@@ -0,0 +1,120 @@
// Extract step definitions from feature files and generate a data file with source code
import * as fs from 'fs';
import * as path from 'path';
interface StepDefinition {
pattern: string;
keyword: 'Given' | 'When' | 'Then';
file: string;
sourceCode: string;
lineNumber: number;
}
const stepFiles = [
'features/step_definitions/navigation.steps.ts',
'features/step_definitions/form.steps.ts',
'features/step_definitions/screen.steps.ts',
];
function extractStepDefinitions(): StepDefinition[] {
const definitions: StepDefinition[] = [];
for (const filePath of stepFiles) {
const fullPath = path.join(process.cwd(), filePath);
if (!fs.existsSync(fullPath)) continue;
const content = fs.readFileSync(fullPath, 'utf-8');
const lines = content.split('\n');
const fileName = path.basename(filePath);
// Find step definitions line by line
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
// Match Given/When/Then at the start of a line
const match = line.match(/^(Given|When|Then)\s*\(\s*['"`]([^'"`]+)['"`]/);
if (match) {
const keyword = match[1] as 'Given' | 'When' | 'Then';
const pattern = match[2];
// Extract the full function body
const sourceCode = extractFunctionBody(lines, i);
definitions.push({
pattern,
keyword,
file: fileName,
sourceCode,
lineNumber: i + 1,
});
}
}
}
return definitions;
}
function extractFunctionBody(lines: string[], startLine: number): string {
// Look for the closing }); which marks the end of a step definition
for (let i = startLine; i < lines.length; i++) {
const line = lines[i].trim();
if (line === '});' || line.endsWith('});')) {
const extracted = lines.slice(startLine, i + 1);
return extracted.join('\n');
}
}
// Fallback: return just the start line if we couldn't find the end
return lines[startLine] || '';
}
async function generateStepDefinitionsFile() {
const definitions = extractStepDefinitions();
const findFunctionCode = `export function findStepDefinition(stepText: string): StepDefinitionInfo | null {
for (const def of stepDefinitions) {
// Convert Cucumber expression to regex
// {string} -> "[^"]+"
// {int} -> \\\\d+
const regexPattern = def.pattern
.replace(/\\{string\\}/g, '"[^"]+"')
.replace(/\\{int\\}/g, '\\\\d+');
try {
const regex = new RegExp(regexPattern);
if (regex.test(stepText)) {
return def;
}
} catch {
// If pattern fails, try simple includes
const simplified = def.pattern.replace(/\\{string\\}/g, '').replace(/\\{int\\}/g, '').trim();
if (stepText.includes(simplified)) {
return def;
}
}
}
return null;
}`;
const output = `// Auto-generated by scripts/extract-step-definitions.ts
// Do not edit manually - run "bun run steps:extract" to regenerate
export interface StepDefinitionInfo {
pattern: string;
keyword: 'Given' | 'When' | 'Then';
file: string;
sourceCode: string;
lineNumber: number;
}
export const stepDefinitions: StepDefinitionInfo[] = ${JSON.stringify(definitions, null, 2)};
${findFunctionCode}
`;
await Bun.write('src/data/stepDefinitions.ts', output);
console.log(`Generated ${definitions.length} step definitions`);
}
generateStepDefinitionsFile().catch(console.error);