cyberhybridhub/FLUTTER-TDD-PLAN.md
2026-05-31 11:17:12 -05:00

8.9 KiB

Flutter Admin Portal TDD Plan

Scope: Validate the functionality defined in FLUTTER-ADMIN-PORTAL.md using test-first development across server API + Flutter UI/repository layers.

Primary objective: Ship an admin portal that reliably shows retention/cleanup/backfill history, prioritizes unresolved failures/rate limits, and presents concise expandable details.


1. Test strategy at a glance

Use a layered pyramid so core behavior is proven at the cheapest layer first:

Layer Purpose Tools
Unit (server) pin/severity/status logic, query mapping dart test
Integration (server) auth, DB query shape/order, endpoint behavior dart test + Postgres test DB
Unit (Flutter) DTO mapping, repository merge, parsing, formatting flutter test
Widget (Flutter) pinned section, newest-first list, expansion details, pagination interactions flutter test
Optional e2e/manual confidence pass with real API + seeded rows local runbook

2. Coverage targets (reasonable)

Aim for practical coverage without over-testing visual polish:

  • Server admin handler package: >= 85% line coverage
  • Server pin/severity helper logic: >= 95% line coverage
  • Flutter admin repository/models: >= 90% line coverage
  • Flutter admin widgets/screens: >= 75% line coverage
  • Critical behavior cases: 100% scenario coverage for:
    • unresolved errors pinned
    • unpin after successful retry by same kind
    • newest-first ordering
    • expanded full error text display
    • no raw data fields rendered

3. Test data model fixtures

Create reusable fixture builders for market_data_sync_runs rows:

run(id, kind, startedAt, finishedAt, rowsWritten, rowsRemoved, error)

Named fixture sets:

  1. all_success_recent_first
  2. rate_limit_unresolved
  3. failed_then_success_same_kind
  4. partial_backfill_error
  5. in_progress_stale
  6. mixed_kinds_mixed_outcomes

Keep fixtures concise; avoid raw bar payloads by design.


4. Server TDD plan

Target files (planned):

  • server/lib/handlers/market_history_admin_handler.dart
  • server/lib/trading/market_history_admin_query.dart (or equivalent helper)
  • server/test/integration/market_history_admin_handler_test.dart
  • server/test/trading/market_history_admin_logic_test.dart

4.1 RED: pin/severity/status logic unit tests

Write tests before implementation:

  1. Pinned unresolved failure
    • failed backfill with no later success => pinned
  2. Unpin after retry success
    • failed backfill then later successful backfill => old failure not pinned
  3. Pinned is per-kind
    • cleanup success does not clear backfill failure pin
  4. Rate limit classification
    • error containing 429 or rate limited => severity=rate_limit
  5. Partial success classification
    • rows_written>0 && error!=null => status=partial
  6. In-progress classification
    • finished_at==null recent => status=in_progress
    • stale threshold exceeded => severity=warning/error (per chosen policy)
  7. Newest-first ordering
    • runs sorted by started_at DESC

4.2 GREEN: minimal implementation

Implement pure helper functions first:

  • deriveSeverity(error, finishedAt, startedAt, now)
  • deriveStatus(error, finishedAt, rowsWritten, rowsRemoved)
  • computePinned(runs)
  • toSummary(run)

Keep these deterministic and injectable with clock for testability.

4.3 RED: handler integration tests

market_history_admin_handler_test.dart:

  1. 403 for non-admin token
  2. 200 + shape for admin
  3. runs newest-first
  4. pinned contains unresolved rate-limit row
  5. pinned clears when later success seeded
  6. limit respected
  7. pagination via before
  8. kind filter
  9. response excludes raw fields (no raw, no snapshot payload)

4.4 GREEN: handler + routing

Implement route:

  • GET /v1/admin/market-history/sync-runs

Wire auth middleware with admin allowlist/claim gate.

4.5 REFACTOR

  • Move query + transform logic out of handler into service/query class.
  • Ensure all SQL is parameterized.
  • Add response DTO class to reduce map-shape drift.

5. Flutter TDD plan

Planned files:

  • lib/admin/models/sync_run_event.dart
  • lib/admin/services/market_history_admin_api.dart
  • lib/admin/repositories/sync_run_log_repository.dart
  • lib/admin/screens/market_history_log_screen.dart
  • lib/admin/widgets/sync_run_expansion_tile.dart

Tests:

  • test/admin/models/sync_run_event_test.dart
  • test/admin/repositories/sync_run_log_repository_test.dart
  • test/admin/services/market_history_admin_api_test.dart
  • test/admin/widgets/sync_run_expansion_tile_test.dart
  • test/admin/screens/market_history_log_screen_test.dart

5.1 RED: model + repository unit tests

  1. Parse API response into domain model
  2. Severity/status mapping from API and fallback parsing
  3. Merge pinned + history sections
  4. Keep pinned visible above chronological list
  5. Append paged results without reordering newer rows
  6. Deduplicate by id during refresh
  7. Error state handling (401/403/500/network)

5.2 GREEN: implement model/repository

  • Implement immutable model objects
  • Implement repository APIs:
    • loadInitial()
    • refresh()
    • loadMore()
  • Include simple in-memory cache for current session

5.3 RED: service HTTP tests

Using mocked HTTP client:

  1. sends bearer token header
  2. sends limit, before, kind query params
  3. handles non-200 responses
  4. parse malformed payload guardrails

5.4 GREEN: service implementation

Mirror existing app API style (apiBaseUrl, auth token retrieval, robust parse).

5.5 RED: widget/screen tests

  1. Pinned section shown when pinned rows exist
  2. Pinned section hidden when none exist
  3. Newest row at top in history list
  4. Expansion tile details
    • shows full message text
    • does not show raw data fields
  5. Severity styling (icon/chip text present)
  6. Pull-to-refresh triggers repository refresh
  7. Scroll-to-end triggers loadMore()
  8. Loading, empty, and error states render correctly

5.6 GREEN: implement UI

  • Build screen with two sections:
    • Needs attention (pinned)
    • History (paged, newest-first)
  • Use ExpansionTile rows with concise collapsed summary.

5.7 REFACTOR

  • Extract common chips/icons/date formatters
  • Keep widget tree shallow for testability
  • Avoid business logic in widget build methods

6. API-trigger actions (optional phase C) TDD

If adding on-demand actions:

Server tests:

  • POST /v1/admin/market-data/resync returns 202 and creates run rows
  • POST /v1/admin/market-data/cleanup with archive flag routes correctly
  • auth + invalid input tests

Flutter tests:

  • retry button visible for pinned failures
  • confirm dialog for cleanup
  • action triggers refresh and shows new in-progress/success rows

This phase can be deferred without affecting MVP log validation.


7. Quality gates and CI commands

Server

cd server && dart test test/trading/market_history_admin_logic_test.dart
cd server && dart test test/integration/market_history_admin_handler_test.dart

Flutter

flutter test test/admin/models/
flutter test test/admin/repositories/
flutter test test/admin/services/
flutter test test/admin/widgets/
flutter test test/admin/screens/

Server:

cd server && dart test --coverage=coverage

Flutter:

flutter test --coverage

Add CI thresholds for the targets in Section 2.


8. Risk-driven test checklist

High-priority cases to lock down early:

  • Pin logic regression when multiple kinds interleave
  • Rate-limit text variants (429, rate limit, capitalization differences)
  • Very long error message expansion rendering
  • Pagination duplicates/holes on refresh + load-more race
  • Timezone display mismatch (started_at UTC vs local display)
  • Empty payload safety (no crashes)

9. Definition of done

The admin portal feature is considered validated when:

  1. All MVP tests listed above pass.
  2. Coverage targets in Section 2 are met.
  3. Automated acceptance tests (test/admin/acceptance/) cover:
    • newest-first order,
    • pinned unresolved issues,
    • expandable full error detail,
    • no raw payload details in UI,
    • cleanup archive toggle when enabled.
  4. CI includes these test suites and fails on regression.

Manual sanity pass (live server + seeded rows) remains recommended before production rollout.


10. Suggested implementation order

  1. Server pure logic tests + implementation
  2. Server handler integration tests + endpoint
  3. Flutter models/repository/service tests + implementation
  4. Flutter widget/screen tests + UI implementation
  5. Optional trigger actions phase
  6. Risk checklist (§8) + acceptance tests (§9)

This order keeps risky logic proven first and gives UI teams a stable API contract early.