Commit Graph

3 Commits

Author SHA1 Message Date
wmj 33a821e61d refactor: restructure navigation into 5 grouped hubs, off the 22-item flat strip
Implements the researched IA fix: mobile nav UX consensus caps primary
destinations at 4-5 (uxpin.com, fintech/banking 2026 UX research), and
this app had grown to 22 tabs in one horizontally-scrolling row —
exactly the anti-pattern that research flags for choice paralysis and
slower task completion.

New structure — 5 bottom-nav hubs, grouped by what the user is actually
trying to do, not build order:
- Home: Coverage (unchanged, still the landing screen)
- Estate: Assets, Faraid, Insurance, Wassiyah, Hibah, Family Waqf,
  Nominate, Claims (H2)
- Giving: Zakat, Sadaqah, Khairat
- Family: Tree, Trigger, Mutawalli, Manage (was 'Family', renamed to
  avoid colliding with the hub's own label), Neighbourhood
- Daily: Prayer Times, Qibla, Quran, Locate

Each hub reveals its own sub-nav one tap in, instead of every tab
competing for space in a single row. Settings moved out of the tab
strip entirely into a header gear icon, matching the banking-app pattern
of keeping settings out of primary thumb-reach real estate. The bottom
nav is now fixed (thumb-zone), sub-nav keeps the old sticky-top position.

Cross-component navigation (nav.js requestedTab, used by the Family
Tree's 'give sadaqah in memory' link) now resolves a tab label to its
owning (hub, sub-tab) pair instead of a flat index — verified live.

This touches every E2E suite: a single click on a tab's old selector no
longer reaches it (hub, then sub-tab). Added a shared gotoTab(page, label)
helper to e2e-auth-helper.cjs encapsulating the two-step navigation, and
migrated all ~22 affected test files off direct nav-button selectors —
mechanical substitution followed by manual fixes for local clickTab
wrappers, template-literal selectors, and active-state assertions that
needed to target the new .hub-tab/.subnav structure specifically.

Full regression after migration: every suite passes (one isolated
Family Tree flake confirmed clean on rerun, unrelated to navigation).
2026-08-14 14:55:09 +08:00
wmj b9a98bd97a Restore all 8 pre-auth E2E suites with a sign-in prelude; fix bugs they found
New e2e-auth-helper.cjs: shared signInFreshFamily() prelude — signs in as
the confirmed test owner account and creates a uniquely-named family per
run, so accumulated data from a previous run's assets/hibah/etc. (now
persisted in Supabase, not wiped with the browser context like localStorage
was) can never bleed into another run's percentage/coverage assertions.
All 8 suites (e2e-uat, e2e-fastpath, e2e-trust, e2e-business,
e2e-digital-vehicle, e2e-property, e2e-other, e2e-info) now call it in
place of the old anonymous page.goto(BASE).

Restoring them surfaced two real product bugs, not just test staleness:

1. WassiyahGenerator.svelte was never migrated to Supabase in the earlier
   backend work — it still called the old local storage.js load()/save()
   for assets, bequests, and witnesses, so the one-third meter silently
   read an empty local cache and always showed 0. Migrated to family-scoped
   Supabase tables (new nf_wassiyah_bequests, nf_wassiyah_settings, with
   member-scoped RLS) matching the pattern used for Hibah/Nominations/etc.

2. storage.js's exportAll() did an unguarded JSON.parse on every
   "nf."-prefixed localStorage key, but family.js stores activeFamilyId as
   a raw string (not JSON-encoded) — one malformed parse threw and silently
   aborted the whole export before the file download fired. Made exportAll
   defensive: falls back to the raw string on a parse failure instead of
   throwing.

The remaining test failures were async-timing gaps inherent to the move
from synchronous localStorage reads to async Supabase fetches: several
assertions checked <select> option counts or newly-created rows immediately
after a fixed short wait, before the async load/refresh had actually
landed. Fixed by replacing blind isVisible()/fixed-timeout checks with
proper waitFor()/polling in the test helpers (selectByText, corpus-select
population, row-creation checks) — not a product bug, but worth fixing
since the old timing assumptions no longer hold now that data is live and
shared instead of instant and local.

Results: e2e-uat 32/32, e2e-fastpath 16/16, e2e-trust 12/12,
e2e-business 10/10, e2e-digital-vehicle 10/10, e2e-property 9/9,
e2e-other 4/4, e2e-info 31/31 — 124/124. Re-verified e2e-family-agent
(12/12) and e2e-smoke-authed (24/24) still pass after the
WassiyahGenerator migration. 160/160 total across all ten suites.
2026-08-13 21:30:46 +08:00
wmj 10289e2d92 Verify property/land coverage across all three applicable fast-path channels
No code changes needed — land/property was already correctly wired through
Hibah (offer/acceptance/possession now), Waqf (dedicated corpus via Family
Waqf Designator), and Trust (via Nomination Registry, added earlier this
session). This adds explicit isolated verification since prior tests only
exercised one channel per property asset at a time.

e2e-property.cjs: three separate property assets, each covered through a
different channel, confirming Coverage Dashboard correctly attributes each
(Hibah/Waqf/Trust) and reaches 100%, and Death Trigger generates a
distinct execution packet for all three. 9/9 passing. Re-verified
e2e-uat.cjs (32/32), e2e-fastpath.cjs (16/16), e2e-trust.cjs (12/12),
e2e-business.cjs (10/10), e2e-digital-vehicle.cjs (10/10), e2e-info.cjs
(31/31) — 132/132 total, no regressions.
2026-08-13 18:18:40 +08:00