Skip to content

Commit b8b7592

Browse files
Merge pull request #208 from richardthe3rd/claude/review-flutter-app-u7YmM
Reorganize docs: archive planning, add ADRs, update implementation status
2 parents f14d73c + c9a9d74 commit b8b7592

31 files changed

Lines changed: 444 additions & 231 deletions

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,5 +150,6 @@ app.*.symbols
150150
!/dev/ci/**/Gemfile.lock
151151

152152
# Keep manually created test mocks (build_runner has version compatibility issues)
153-
!test/*.mocks.dartscreenshots/
153+
!test/*.mocks.dart
154+
screenshots/
154155
test/failures/

AGENTS.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -351,12 +351,12 @@ void main() {
351351

352352
### API Documentation
353353

354-
Full API documentation and JSON schemas are in `docs/api/`:
354+
Full API documentation and JSON schemas are in `docs/code/api/`:
355355

356-
- **[docs/api/README.md](docs/api/README.md)** - Overview and quick reference
357-
- **[docs/api/data-api-reference.md](docs/api/data-api-reference.md)** - Complete API reference
358-
- **[docs/api/beer-list-schema.json](docs/api/beer-list-schema.json)** - JSON Schema for beverage data
359-
- **[docs/api/festival-registry-schema.json](docs/api/festival-registry-schema.json)** - JSON Schema for festival config
356+
- **[docs/code/api/README.md](docs/code/api/README.md)** - Overview and quick reference
357+
- **[docs/code/api/data-api-reference.md](docs/code/api/data-api-reference.md)** - Complete API reference
358+
- **[docs/code/api/beer-list-schema.json](docs/code/api/beer-list-schema.json)** - JSON Schema for beverage data
359+
- **[docs/code/api/festival-registry-schema.json](docs/code/api/festival-registry-schema.json)** - JSON Schema for festival config
360360

361361
### Validating festivals.json
362362

README.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,9 @@ Coverage fails if it drops below 70% overall, helping maintain code quality.
128128

129129
### E2E Testing
130130

131-
- **Web E2E Tests**: Playwright tests for Flutter web builds - [Testing Flutter Web Guide](docs/tooling/flutter-web-testing.md)
132-
- **Mobile E2E Tests**: Patrol + Firebase Test Lab integration (planned) - [Testing Plan](docs/planning/patrol-firebase-testing/plan.md)
131+
- **Web E2E Tests**: Playwright tests for URL routing and accessibility smoke tests - [Testing Flutter Web Guide](docs/tooling/flutter-web-testing.md)
133132

134-
See the [Patrol Firebase Testing Summary](docs/planning/patrol-firebase-testing/summary.md) for implementation status and plan overview.
133+
See [ADR 0005](docs/adr/0005-e2e-testing-strategy.md) for the rationale behind this approach.
135134

136135
## Data API
137136

@@ -159,8 +158,6 @@ Technical documentation is available in the [docs](docs/) directory - see [docs/
159158

160159
### Testing & Quality
161160
- [Testing Flutter Web](docs/tooling/flutter-web-testing.md) - E2E testing with Playwright
162-
- [Patrol Firebase Testing Plan](docs/planning/patrol-firebase-testing/plan.md) - Mobile E2E testing strategy
163-
- [Patrol Testing Summary](docs/planning/patrol-firebase-testing/summary.md) - Quick overview and status
164161

165162
### Architecture & Deployment
166163
- [URL Routing](docs/code/routing.md) - Path-based routing implementation

docs/README.md

Lines changed: 51 additions & 174 deletions
Large diffs are not rendered by default.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# ADR 0004: Path-Based URL Strategy for Deep Linking
2+
3+
**Status**: Accepted
4+
5+
**Date**: 2025-12-21
6+
7+
**Deciders**: Engineering Team
8+
9+
**Context**: The app needed shareable, bookmarkable URLs for festival drinks, breweries, and styles. Two approaches were considered: hash-based URLs (`/#/drink/123`) and path-based URLs (`/drink/123`). The app was pre-release with no existing shared URLs or search engine indexing, so there were no backward-compatibility constraints.
10+
11+
---
12+
13+
## Decision
14+
15+
We adopted **festival-scoped, path-based URLs** with GoRouter and `usePathUrlStrategy()`.
16+
17+
### URL Structure
18+
19+
```
20+
/{festivalId} → Festival home (drinks list)
21+
/{festivalId}/favorites → Favorites for this festival
22+
/{festivalId}/drink/{drinkId} → Drink detail
23+
/{festivalId}/brewery/{id} → Brewery detail
24+
/{festivalId}/style/{styleName} → Style detail (lowercase canonical)
25+
/{festivalId}/info → Festival info
26+
/about → About (global, not festival-scoped)
27+
```
28+
29+
### Key Design Choices
30+
31+
1. **Festival ID as URL root** -- every drink/brewery/style URL is scoped to a festival, enabling cross-festival deep links
32+
2. **Lowercase canonical style URLs** -- `buildStylePath()` lowercases style names for consistent URLs
33+
3. **URL encoding** -- all user-provided IDs are encoded via `Uri.encodeComponent()`
34+
4. **Pre-release advantage** -- no redirect logic or legacy URL support needed
35+
36+
---
37+
38+
## Alternatives Considered
39+
40+
### Hash-Based URLs (`/#/drink/123`)
41+
42+
- Simpler: no server-side SPA routing config needed
43+
- Rejected because: poor SEO, unprofessional appearance, not shareable on social media
44+
45+
### Flat URLs without festival scoping (`/drink/123`)
46+
47+
- Simpler routing, fewer path segments
48+
- Rejected because: can't distinguish same drink ID across different festivals; can't share a link to "this year's festival"
49+
50+
---
51+
52+
## Consequences
53+
54+
### Positive
55+
56+
- Clean, shareable URLs that work on social media
57+
- Festival context is always visible in the URL
58+
- Browser back/forward works correctly
59+
- Bookmarks and shared links are self-contained
60+
61+
### Negative
62+
63+
- Requires SPA fallback routing on the server (Cloudflare Pages `_redirects` or `--proxy` flag on http-server)
64+
- Detail routes currently lack festival ID validation (documented as known limitation, see todos.md H3)
65+
- Festival selector UI doesn't update the URL when switching festivals (see todos.md C3)
66+
67+
---
68+
69+
## Implementation
70+
71+
- **Router**: `lib/router.dart` (GoRouter configuration)
72+
- **URL builders**: `lib/utils/navigation_helpers.dart`
73+
- **E2E tests**: `test-e2e/routing.spec.ts` (Playwright URL smoke tests)
74+
- **Server config**: `--proxy` flag on http-server for SPA fallback
75+
76+
## Related Documents
77+
78+
- `docs/code/routing.md` -- current routing implementation details
79+
- `docs/code/navigation.md` -- navigation helper API reference
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# ADR 0005: E2E Testing Strategy -- Playwright for URL Smoke Tests
2+
3+
**Status**: Accepted
4+
5+
**Date**: 2025-12-21
6+
7+
**Deciders**: Engineering Team
8+
9+
**Context**: The app needed automated end-to-end testing to validate routing and deep linking. Two approaches were evaluated: Patrol with Firebase Test Lab (native Flutter E2E on real Android devices) and Playwright (browser-based testing). Flutter web renders to a `<canvas>` element, which makes traditional DOM-based testing largely ineffective for UI interactions.
10+
11+
---
12+
13+
## Decision
14+
15+
We adopted **Playwright for URL and routing smoke tests only**, and deferred native E2E testing.
16+
17+
Playwright tests verify:
18+
- URL routing works (correct URLs after navigation)
19+
- Browser back/forward/refresh preserves routes
20+
- No critical console errors on page load
21+
- Basic ARIA label presence (accessibility smoke test)
22+
23+
Playwright tests **do not** verify:
24+
- Visual appearance, layout, or rendered text
25+
- Widget interactions (tapping buttons, filling forms)
26+
- User flows (search, filter, favorite)
27+
- Canvas-rendered content
28+
29+
Widget interactions are covered by Flutter's own `testWidgets` framework in `test/`.
30+
31+
---
32+
33+
## Alternatives Considered
34+
35+
### Patrol + Firebase Test Lab
36+
37+
A detailed plan was created (see `docs/planning/archive/patrol-firebase-testing/`) proposing:
38+
- Native Flutter E2E tests using the Patrol framework
39+
- Execution on real Android devices via Firebase Test Lab free tier (15 tests/day)
40+
- 4-5 week implementation timeline across 5 phases
41+
42+
**Why it was not implemented:**
43+
- Significant setup complexity (Firebase Test Lab, GCP service accounts, Android instrumentation builds)
44+
- 4-5 week implementation investment for a pre-release app
45+
- Free tier limit (15 tests/day) constrains CI usage
46+
- Flutter widget tests already cover interaction flows effectively
47+
- The immediate need was validating URL routing for the deep linking feature, not full native E2E
48+
49+
**When to reconsider:**
50+
- If the app ships on Android/iOS and needs device-specific testing (permissions, system dialogs, push notifications)
51+
- If visual regression testing becomes important
52+
- If Flutter widget tests prove insufficient for catching real-world bugs
53+
54+
### Flutter Integration Tests
55+
56+
Flutter's built-in `integration_test` package was considered but not prioritised. It would run the full app in a test harness and can interact with widgets directly. This remains a valid option for future investment (tracked in todos.md item #1).
57+
58+
---
59+
60+
## Consequences
61+
62+
### Positive
63+
64+
- Fast to implement (2 test files, ~440 lines)
65+
- Validates the most critical web concern: URL routing works correctly
66+
- Runs in CI without special infrastructure
67+
- ARIA label checks enforce accessibility as a side effect
68+
- No ongoing cost or quota limits
69+
70+
### Negative
71+
72+
- Cannot test actual user flows through the UI
73+
- Cannot verify that the correct screen renders for a given URL
74+
- Flutter canvas rendering means Playwright can never do meaningful UI testing for this app
75+
- Gap between "URL works" and "screen works" -- a route could return 200 but render an error state
76+
77+
---
78+
79+
## Implementation
80+
81+
- **Config**: `playwright.config.ts`
82+
- **Tests**: `test-e2e/app.spec.ts` (loading, console errors, ARIA), `test-e2e/routing.spec.ts` (URL routing, browser history)
83+
- **Approach doc**: `docs/tooling/flutter-web-testing.md`
84+
85+
## Related Documents
86+
87+
- `docs/tooling/flutter-web-testing.md` -- how Playwright works with Flutter's canvas renderer
88+
- `docs/planning/archive/patrol-firebase-testing/` -- the Patrol evaluation that was not implemented

docs/adr/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ Each ADR follows this structure:
3030
| [0001](0001-github-actions-caching-strategy.md) | GitHub Actions Caching Strategy | Accepted | 2025-12-27 |
3131
| [0002](0002-composite-actions-and-test-deduplication.md) | Composite Actions and Test Deduplication | Accepted | 2025-12-27 |
3232
| [0003](0003-parallel-build-strategy.md) | Parallel Build Strategy for Android Releases | Accepted | 2025-12-27 |
33+
| [0004](0004-path-based-url-strategy.md) | Path-Based URL Strategy for Deep Linking | Accepted | 2025-12-21 |
34+
| [0005](0005-e2e-testing-strategy.md) | E2E Testing Strategy (Playwright for URL Smoke Tests) | Accepted | 2025-12-21 |
3335

3436
## Creating a New ADR
3537

docs/code/accessibility.md

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -68,29 +68,37 @@ Comprehensive accessibility guidelines for the Cambridge Beer Festival app.
6868

6969
## Implementation Status
7070

71-
### Current Status: ❌ NOT IMPLEMENTED
72-
73-
**No accessibility features currently exist in the codebase.**
74-
75-
Zero `Semantics` widgets found in:
76-
-`lib/widgets/drink_card.dart`
77-
-`lib/screens/drinks_screen.dart`
78-
-`lib/screens/festival_info_screen.dart`
79-
-`lib/main.dart`
80-
-`lib/widgets/star_rating.dart`
81-
82-
**Impact:** App is currently unusable for screen reader users.
83-
84-
### What Needs Implementation
85-
86-
See [todos.md](../todos.md) item #6 for full details:
87-
- Favorite buttons need labels
88-
- Filter chips need state announcements
89-
- Navigation bar needs descriptive labels
90-
- Search interface needs proper semantics
91-
- Drink cards need summaries
92-
- Star ratings need value announcements
93-
- Action buttons need clear descriptions
71+
### Current Status: ✅ Implemented
72+
73+
**53+ `Semantics` widgets** are implemented across the app, with **9 dedicated accessibility tests** in `test/accessibility_test.dart`.
74+
75+
Coverage by file:
76+
-`lib/widgets/drink_card.dart` -- card semantic labels, favorite button semantics
77+
-`lib/screens/drinks_screen.dart` -- search clear button, filter chips
78+
-`lib/screens/festival_info_screen.dart` -- map, website, and GitHub buttons
79+
-`lib/main.dart` -- bottom navigation bar with descriptive labels for both tabs
80+
-`lib/widgets/star_rating.dart` -- parent rating label, individual star semantics
81+
-`lib/widgets/bottom_action_bar.dart` -- action button semantics
82+
-`lib/widgets/breadcrumb_bar.dart` -- back navigation semantics
83+
-`lib/widgets/overflow_menu.dart` -- menu button with `ExcludeSemantics` on decorative icons
84+
-`lib/widgets/info_chip.dart` -- chip semantics
85+
-`lib/widgets/festival_menu_sheets.dart` -- festival selector, settings, theme selector
86+
-`lib/widgets/environment_badge.dart` -- environment indicator semantics
87+
-`lib/screens/about_screen.dart` -- theme, GitHub, issues, licenses buttons
88+
-`lib/screens/drink_detail_screen.dart` -- action buttons, brewery link
89+
90+
### Automated Tests
91+
92+
`test/accessibility_test.dart` verifies:
93+
- Favorite button semantic labels (add/remove states)
94+
- ABV chip `ExcludeSemantics` for decorative elements
95+
- Card semantic structure and labels
96+
- Environment badge semantics
97+
- Button property (`button: true`) on interactive elements
98+
- Hint instructions for screen reader users
99+
- `ExcludeSemantics` usage on decorative icons
100+
- Filter chip selection state announcements
101+
- Retry button semantics on error states
94102

95103
---
96104

File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)