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 f6078a8968 Add Playwright tests for the bulk "Clear N finished" + undo flow on /my-orders
Task #157 asked for end-to-end coverage of the bulk-delete path on
/my-orders, which goes through the same scheduleDelete() in
artifacts/tx-os/src/pages/my-orders.tsx as the single-card delete but
uses a single shared setTimeout that owns multiple order IDs and a
different (i18n plural) toast title. None of that was exercised by
the existing order-undo-toast.spec.mjs.

New file: artifacts/tx-os/tests/order-clear-finished-undo.spec.mjs

Three tests, all using the same DB-seeding + login pattern as the
existing undo-toast spec:

1. English plural + Undo: seeds 3 finished orders, clicks
   "Clear 3 finished", confirms, asserts the plural toast
   ("3 orders deleted" => myOrders.clearedCount_other), clicks Undo
   inside the 7s window, then waits past UNDO_WINDOW_MS and asserts
   that NO DELETE /api/orders/:id requests went out, all 3 rows still
   exist in the DB, and all 3 cards are visible again. This is the
   core regression guard for the multi-id shared-timer logic.

2. English plural + timer expiry: seeds 1 completed + 1 cancelled
   order (to confirm both finished states are swept), clicks
   "Clear 2 finished", asserts the plural toast, does NOT click Undo,
   polls until both DELETE responses fire and both DB rows are gone.

3. Arabic singular bulk path: seeds 1 finished order, clicks the
   Arabic "Clear 1 finished" button, confirms, asserts the singular
   toast title. NOTE: when ids.length === 1 the bulk path falls
   through to myOrders.deleted ("تم حذف الطلب"), NOT
   clearedCount_one — so the test asserts actual current behavior and
   the comment explains why. Then Undoes and verifies the row stays.

Deviation from task spec: the task said "Both the singular ('1 order
deleted') and plural ('{count} orders deleted') toast titles are
exercised at least once." The plural string is exercised, but the
literal "1 order deleted" string (clearedCount_one) is unreachable
in the current code — scheduleDelete uses myOrders.deleted for the
single-id case. I tested the actual singular branch instead and
filed follow-up #223 to either route the single-id bulk case through
clearedCount_one or remove the dead translation key. Also filed
follow-up #224 for the unused clearedPartial string (partial-failure
toast for bulk clear).

Verified locally: all 3 new tests pass via
  pnpm --filter @workspace/tx-os exec playwright test \
    tests/order-clear-finished-undo.spec.mjs
(3 passed in ~47s, exit 0). No existing files were modified.

Replit-Task-Id: ba9e23a5-d8ff-4376-ab8c-d03d6a5f15e4
2026-04-30 17:20:54 +00:00