a19bda44e1
- Replace hover-based Tooltip with click-based popover for mobile support - Fix pattern extraction regex to handle escaped apostrophes (e.g., l'écran) - Add dashed underline (1.3px) to indicate clickable steps with definitions - Enable definitions mode by default - Regenerate stepDefinitions.ts with correct patterns Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
123 lines
3.5 KiB
TypeScript
123 lines
3.5 KiB
TypeScript
// 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
|
|
// Handle escaped quotes in patterns (e.g., 'l\'écran contient')
|
|
const match = line?.match(/^(Given|When|Then)\s*\(\s*(['"`])((?:[^\\]|\\.)*?)\2/);
|
|
if (match && match[3]) {
|
|
const keyword = match[1] as 'Given' | 'When' | 'Then';
|
|
// Unescape the pattern (remove backslashes before quotes)
|
|
const pattern = match[3].replace(/\\(['"`])/g, '$1');
|
|
|
|
// 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);
|