9cc916e8bc
Add optional chaining and null checks in build scripts to handle potentially undefined array elements. Add style prop to Card, Badge, and Placeholder components, and onClick prop to Text component to support inline styling in screen components. 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);
|