# Cucumber BDD Integration This document explains how the Cucumber BDD testing framework is integrated into Festipod. ## Overview Festipod uses **Cucumber.js** with **TypeScript** for Behavior-Driven Development testing. All feature files are written in **French** using Gherkin syntax. The integration uses static source code analysis rather than browser automation. ## Architecture ``` Feature Files (French Gherkin) ↓ Cucumber Parser (language: "fr") ↓ Step Definition Matching ↓ World Instance (FestipodWorld) ↓ Inline Detection Logic (screen-specific regex patterns) ↓ Chai Assertions ↓ JSON + HTML Reports ``` ## Directory Structure ``` features/ ├── support/ │ ├── world.ts # Custom World class with state management │ └── hooks.ts # Before/After lifecycle hooks ├── step_definitions/ │ ├── navigation.steps.ts # Screen navigation steps │ ├── form.steps.ts # Form validation steps │ └── screen.steps.ts # Content verification steps ├── user/ # User-related features (9 files) ├── event/ # Event features (5 files) ├── workshop/ # Workshop features (6 files) ├── meeting/ # Meeting features (1 file) └── notif/ # Notification features (3 files) ``` ## Configuration The `cucumber.json` file configures the test runner: ```json { "default": { "import": [ "features/support/**/*.ts", "features/step_definitions/**/*.ts" ], "paths": ["features/**/*.feature"], "format": [ "progress-bar", "json:reports/cucumber-report.json", "html:reports/cucumber-report.html" ], "language": "fr", "formatOptions": { "snippetInterface": "async-await" }, "strict": false } } ``` - **language: "fr"** - Uses French Gherkin keywords (Fonctionnalité, Scénario, Étant donné, Quand, Alors) - **strict: false** - Allows pending scenarios to be reported without failing the test suite - **Reports** - Generates both JSON (for CI) and HTML (human-readable) reports ## World Class The `FestipodWorld` class (`features/support/world.ts`) maintains test state: ### Tracked State | Property | Type | Description | |----------|------|-------------| | `currentRoute` | `string` | Current URL hash (e.g., `#/demo/home`) | | `currentScreenId` | `string` | Current screen identifier | | `formFields` | `Map` | Form fields with required flag and value | | `navigationHistory` | `string[]` | All visited routes | | `isAuthenticated` | `boolean` | Login state | | `screenSourceContent` | `string` | Raw TypeScript source of current screen | ### Key Methods - `navigateTo(route)` - Navigate to a screen, load its source code - `hasField(fieldName)` - Check if a semantic field exists using regex detectors - `hasText(text)` - Check if text exists in screen source - `hasElement(selector)` - Check for JSX elements - `getRenderedText()` - Get the full source code for matching ### Screen Name Mapping French screen names are mapped to screen IDs: ```typescript screenNameMap = { 'accueil': 'home', 'créer un événement': 'create-event', 'détail événement': 'event-detail', 'mon profil': 'profile', 'profil utilisateur': 'user-profile', // ... etc } ``` ### Screen-Specific Field Detectors Field detection is screen-specific, defined in `screenFieldDetectors` map. Each screen has its own set of regex patterns to identify UI elements: **event-detail screen:** | Field | Detection Pattern | |-------|-------------------| | Titre | `content` | | Date | 📅 emoji + French month name + year | | Heure | 🕓 emoji + time pattern (e.g., 14h30) | | Lieu | 📍 emoji + capitalized location name | | Description | "À propos" section with 50+ chars of text | | Photo | `` with capitalized first/last name | | Pseudo | `@username` pattern | | Photo / Photo de profil | `\s*navigate\s*\(['"]home['"]\)\s*\}[^>]*>✕ navigate('home')}...>✕< const found = /onClick\s*=\s*\{\s*\(\)\s*=>\s*navigate\s*\(['"]home['"]\)\s*\}[^>]*>✕; } ``` ### Data Layer Data is generated by build-time scripts: - `src/data/features.ts` - Parsed feature file content - `src/data/testResults.ts` - Test execution results - `src/data/stepDefinitions.ts` - Step definition source code