Commit Graph

2 Commits

Author SHA1 Message Date
riyadhafraa c53641c721 #245: narrow umbrella subset — toast polish, opt-out tests, Restore defaults
Picked the 3 most isolated items from the 7-item umbrella; deferred the rest
as #259/#260/#261.

#223 + #224 — singular toast + summary on partial failure (T001):
- my-orders.tsx: replaced the N=1 vs N>1 ternary in scheduleDelete with a
  single t("myOrders.clearedCount", { count }) so i18next picks _one /
  _other automatically. Single-row delete now flows through this same toast
  too — user-visible copy for N=1 is now "1 order deleted" / "تم حذف طلب
  واحد" instead of the legacy "Order deleted" / "تم حذف الطلب".
- my-orders.tsx: partial-failure path now shows ONE summary toast using
  the existing clearedPartial key ("{{ok}} deleted, {{fail}} failed")
  instead of N error toasts. Total failure (okCount===0) keeps deleteFailed.
- Updated 3 Playwright specs that asserted the legacy copy:
  order-clear-finished-undo (already had the singular case), order-undo-toast
  (Arabic single-row delete), order-delete-flush-on-unmount (English).
  Note: the legacy "myOrders.deleted" locale key is now unreferenced in
  source — left in place to avoid noise; deletion can be handled separately.

#238 — opt-out coverage in executive-meetings-notifications.test.mjs (T002):
- Appended 4 tests + setPref/clearPref helpers covering
  filterRecipientsByNotificationPref: inApp=false drops user, missing pref
  defaults to ON, cross-event isolation (mute on event A leaves event B
  alone), email=false leaves in-app intact. Helpers use ON CONFLICT on the
  verified unique index. Some scenarios overlap existing tests in
  executive-meetings.test.mjs (lines 1764, 1809) — these still add value
  by exercising the meeting_created socket fan-out path and cross-event
  isolation, which the existing tests don't cover.

#236 — Restore defaults endpoint + button (T003):
- Server: added DELETE /api/executive-meetings/notification-prefs after PUT.
  Scoped strictly to req.session.userId, returns {ok, count}. Reuses
  requireExecutiveAccess guard. Architect confirmed no cross-user leakage.
- Client: restoreDefaults() handler + outline button (data-testid
  "em-pref-restore-defaults", NOT gated on dirty since the whole point is to
  blow away saved settings). New i18n keys restoreDefaults / restored in
  both locales.
- Architect found a stale-state race in restoreDefaults: setDraft(null)
  was called before invalidateQueries, letting the seed effect repopulate
  draft from still-cached pre-DELETE data. Fixed by inverting the order to
  match save() — invalidate first (await refetch), then setDraft(null).
- Tests: appended 2 integration tests to executive-meetings.test.mjs
  covering the full restore flow (PUT 2 muted prefs → DELETE → assert
  {ok,count:2} + GET shows defaults + actual fan-out reaches user again)
  and idempotent no-op DELETE on a user with no rows.

Test results:
- executive-meetings.test.mjs: 47/47 pass (incl. 2 new DELETE tests)
- executive-meetings-notifications.test.mjs: 11/11 pass (incl. 4 new opt-out tests)
- Playwright order specs: 6/6 pass after legacy-copy updates
- Pre-existing failures in service-orders + meeting_created fan-out are
  untouched and not caused by this change.

Follow-ups proposed: #259 (beforeunload + tab-close Playwright), #260
(admin override another user's prefs with audit row + UI), #261 (iPad
header verification — may already work).
2026-05-01 07:30:00 +00:00
riyadhafraa 40534b7c8f Add Playwright spec for /my-orders unmount-flush of pending deletes
Original task (#158): /my-orders has a useEffect cleanup that, on
unmount, clears every still-running undo timer and immediately fires
the deletions for whatever IDs were queued. This unmount-flush path
was previously not covered by tests — only the "Undo" path was.

Implementation:
- New spec: artifacts/tx-os/tests/order-delete-flush-on-unmount.spec.mjs
- Mirrors the test scaffolding (DB pool, user/order seeding, login,
  language init, toast locator) used by the existing order-undo-toast
  and order-clear-finished-undo specs.
- Flow: seed a completed order, log in, go to /my-orders, click trash
  + "Yes, delete" to queue the deletion, then navigate away via the
  in-page Back button (which is wouter setLocation("/services") — an
  in-SPA route change, so MyOrdersPage actually unmounts and the
  cleanup useEffect runs).
- Asserts both required outcomes from the task spec:
  * A DELETE /api/orders/:id request is observed during the
    navigation (with a 2xx response).
  * The order row is actually gone from the DB.
- Additionally records the timestamp of the DELETE request and asserts
  it fires within 3s of the navigation (well under UNDO_WINDOW_MS).
  This guards against a regression that removes the cleanup but
  accidentally still passes because the natural 7s timer eventually
  fires anyway in the SPA — without the cleanup, the DELETE would
  arrive ~7s later and the assertion would time out.
- Clean up the seeded order id from the afterAll list when the test
  successfully deletes it via the UI, so teardown does not try to
  re-delete a missing row.

No production code changed; this is a pure test addition.

Replit-Task-Id: 655f3d3b-5fc5-4a87-a754-76ec67148186
2026-04-30 17:29:14 +00:00