# 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)
↓
Screen Source Analysis (regex field detectors)
↓
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 | ` tag.name === '@pending');
if (isPending) {
return 'pending';
}
});
```
Use `@pending` for:
- Features not yet implemented
- Email/notification features that cannot be tested via screen analysis
- Scenarios waiting for UI implementation
### Debug Information on Failure
When a scenario fails, the `After` hook attaches:
- Current route
- Current screen ID
- Navigation history
- Form fields state
- Screen source snippet (first 500 chars)
## Running Tests
```bash
# Run all tests end-to-end (runs tests + generates internal report)
bun run test:cucumber
# Sub-commands for individual steps:
bun run cucumber:run # Only run cucumber tests (generates HTML/JSON reports)
bun run cucumber:report # Only parse results to generate internal report
# Run by category tag
bun run cucumber:run --tags "@USER"
bun run cucumber:run --tags "@EVENT"
bun run cucumber:run --tags "@NOTIF"
# Run by priority
bun run cucumber:run --tags "@priority-0"
# Exclude pending tests
bun run cucumber:run --tags "not @pending"
```
## Parsing Results
After running tests, parse results for the UI:
```bash
# Generate testResults.ts from cucumber-report.json (included in test:cucumber)
bun run cucumber:report
# Regenerate step definitions data
bun run steps:extract
# Parse feature files for UI display
bun run features:parse
```
## Example Feature File
```gherkin
# language: fr
@USER @priority-0
Fonctionnalité: US-9 Visualiser la photo d'un individu
En tant qu'utilisateur
Je peux visualiser la photo d'un individu
Contexte:
Étant donné je suis connecté en tant qu'utilisateur
Scénario: Accéder au profil pour voir la photo
Étant donné je suis sur la page "mon profil"
Alors je vois l'écran "profile"
Et l'écran contient une section "Photo de profil"
Scénario: Naviguer vers le profil depuis la liste des participants
Étant donné je suis sur la page "détail événement"
Quand je clique sur un participant
Alors je suis redirigé vers "profil utilisateur"
@pending
Scénario: Fonctionnalité non encore implémentée
Étant donné je suis sur la page "mon profil"
Alors je peux modifier ma photo de profil
```
## Key Design Decisions
### Static Source Analysis
Instead of running the app in a browser, tests analyze TypeScript source files directly. This approach:
- Runs faster (no browser startup)
- Doesn't require a running server
- Validates code structure, not runtime behavior
### French-First
All Gherkin keywords and step definitions use French:
- `Fonctionnalité` instead of `Feature`
- `Scénario` instead of `Scenario`
- `Étant donné` instead of `Given`
- `Quand` instead of `When`
- `Alors` instead of `Then`
### Semantic Field Detection
Rather than checking for specific CSS selectors or test IDs, the integration uses semantic patterns to detect features. For example, detecting a "Date" field by looking for the 📅 emoji pattern makes tests resilient to UI changes.
## UI Integration
The Specs page (`#/specs`) displays feature files with:
- Collapsible scenarios (failed ones open by default)
- Test status indicators (pass/fail/skip)
- Error messages for failed tests
- Step definition source code tooltips (click "Définitions" button)
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