- Port modern clean theme (DM Sans, orange accent, app-* CSS classes) and screen redesigns from festipod-mockups; replace sketchy Ubuntu theme. New shared components: BottomNav, EventCover, EventMeetingPoints, Toast, AvatarStack, Tag, RelevanceIcon. - Restructure from prototyping shell to real mobile web app: path-based routing (History API), Gallery/DemoMode/PhoneFrame removed, Storybook setup for screen/component browsing. - ConnectScreen ported from mockup (QR-based user connection); routed at /profile/connect, wired from FriendsListScreen. - Dev-only auto-seed of NG wallet when empty (gated on NODE_ENV !== 'production'); bootstrapWallet already self-checks for non-empty ngSet so safe even in race conditions. - Render-based @ui test infrastructure: happy-dom + LocalDataProvider + RouterProvider via src/shared/test-harness/renderHelper.tsx, exposed on the world as renderedDoc. world.hasText/hasField/hasElement prefer the rendered DOM and fall back to source for backward compatibility. - Migrate 25 brittle @ui assertions from regex-on-source to DOM queries; delete implementation-detail tests (showDuplicateWarning, importableEvents, importedFrom — anti-patterns per the new contract). Update feature files where the UI changed: "Mes amis" → "Mon réseau", "Mes événements à venir" → "À venir" on home, Thématique removed from create-event wizard, etc. - Path-based @e2e steps (pushState + popstate dispatch) replacing the legacy "#/demo/…" hash routing tied to the deleted Gallery. - Add .project/knowledge/test-layer-contracts.md defining the role of each test layer (@ui = display with seed data + DOM, @data = mutations through NG broker, @e2e = critical user journeys) with anti-patterns and migration consequences. Test status: 75 passed / 71 skipped (explicit "non implémenté") / 2 failed (pre-existing @wip on ngSet.delete() NG ORM limitation). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4.1 KiB
BDD Testing
Cucumber/Gherkin BDD specs in French with multi-layer step definitions.
Overview
- 26 feature files (US-1 to US-26), all in French
- Categories: EVENT, WORKSHOP, USER, MEETING, NOTIF
- Priorities: 0 (Impossible), 1 (Haute), 2 (Moyenne), 3 (Basse)
- Current results: 51 passed, 7 failed, 75 skipped (133 scenarios total)
Multi-Layer BDD
Each module has step directories for three test layers:
src/modules/event/steps/
ui/ # UI/screen assertions (source analysis)
data/ # Data layer assertions (Playwright + broker)
e2e/ # E2E assertions (Playwright + broker + real app UI)
Shared steps (cross-domain) live in src/shared/steps/ui/.
Feature Files
Collocated with their module:
src/modules/event/features/us-13-creer-evenement.feature
src/modules/user/features/us-23-connexion-utilisateurs.feature
src/modules/workshop/features/us-1-visualiser-atelier-termine.feature
...
Tagged with @CATEGORY @priority-N for filtering.
Step Definitions
Shared Steps (src/shared/steps/ui/)
| File | Purpose |
|---|---|
navigation.steps.ts |
Screen navigation, authentication, click/select actions, section/button/field assertions |
form.steps.ts |
Form field validation, required fields, import/duplicate detection |
screen.steps.ts |
Screen content assertions (participants, events, profiles, QR codes) |
How UI Steps Work
@ui steps render the screen with LocalDataProvider (seed data) and RouterProvider via happy-dom, then assert on the rendered DOM. The render helper lives in src/shared/test-harness/renderHelper.tsx and is invoked from world.ts:renderCurrentScreen() on every navigateTo(...).
See test-layer-contracts for what @ui is allowed to test and the patterns to follow (and avoid).
Legacy: screenFileMap, screenFieldDetectors, screenExpectedContent, screenRequiredFields in world.ts are vestiges of an earlier source-code-grep approach. hasText/hasField/hasElement now prefer the rendered DOM and fall back to source so unmigrated steps keep working during the transition.
Screen Name Resolution
French names in .feature files map to screen IDs via screenNameMap:
"accueil"→home"détail événement"→event-detail"mon profil"→profile"relayer un événement"→create-event
Cucumber Configuration
cucumber.json:
{
"default": {
"import": [
"src/shared/support/**/*.ts",
"src/shared/steps/**/*.ts",
"src/modules/*/steps/**/*.ts"
],
"paths": ["src/modules/*/features/**/*.feature"],
"language": "fr"
}
}
Requires tsx loader: node --import tsx/esm node_modules/.bin/cucumber-js
Auto-Generated Files
Scripts in scripts/ parse features and steps into TypeScript data files consumed by the prototyping tool:
| Script | Input | Output |
|---|---|---|
parse-features.ts |
src/modules/*/features/*.feature |
src/shared/data/features.ts |
parse-test-results.ts |
reports/cucumber-report.json |
src/shared/data/testResults.ts |
extract-step-definitions.ts |
src/shared/steps/ui/*.ts |
src/shared/data/stepDefinitions.ts |
Run all: bun run test:cucumber
Data-Layer Testing
@data scenarios test through the real NextGraph broker. See data-layer-testing for full architecture.
E2E Testing
@e2e scenarios test the real app running in the broker iframe. See data-layer-testing for architecture. Key differences from @data:
- Uses the real app (not a test harness) served on a local HTTP port
- Interacts via Playwright locators and
evaluate()on the app iframe - Tests actual UI behavior: navigation, redirects, button clicks, screen content
- Requires real broker mode (fails with
Errorif broker unavailable)
Adding New Steps
- Module-specific: Create in
src/modules/{module}/steps/ui/ - Cross-domain: Add to
src/shared/steps/ui/ - Import
FestipodWorldtype from../../support/world(shared) or adjust relative path - Run
bun run steps:extractto regenerate tooltip data