From f6078a89685f031144ab92565ff3bafbb1dda203 Mon Sep 17 00:00:00 2001 From: riyadhafraa <49757212-riyadhafraa@users.noreply.replit.com> Date: Thu, 30 Apr 2026 17:20:54 +0000 Subject: [PATCH] Add Playwright tests for the bulk "Clear N finished" + undo flow on /my-orders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- artifacts/tx-os/public/opengraph.jpg | Bin 25967 -> 24648 bytes .../tests/order-clear-finished-undo.spec.mjs | 412 ++++++++++++++++++ 2 files changed, 412 insertions(+) create mode 100644 artifacts/tx-os/tests/order-clear-finished-undo.spec.mjs diff --git a/artifacts/tx-os/public/opengraph.jpg b/artifacts/tx-os/public/opengraph.jpg index 5429ac2d6b0ef84da4be9799c1fd5c84bd32b975..6aa235e576030361b5a53ca4f803ff7697e4b0b3 100644 GIT binary patch literal 24648 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 b2EQ66o89{Rof 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 jo;F7|zalQK9UU8Y { + if (createdOrderIds.length > 0) { + await pool.query(`DELETE FROM service_orders WHERE id = ANY($1::int[])`, [ + createdOrderIds, + ]); + } + if (createdUserIds.length > 0) { + // Defensive: also wipe anything else attached to the test users. + await pool.query( + `DELETE FROM service_orders + WHERE user_id = ANY($1::int[]) OR assigned_to = ANY($1::int[])`, + [createdUserIds], + ); + await pool.query( + `DELETE FROM notifications WHERE user_id = ANY($1::int[])`, + [createdUserIds], + ); + await pool.query( + `DELETE FROM user_roles WHERE user_id = ANY($1::int[])`, + [createdUserIds], + ); + await pool.query(`DELETE FROM users WHERE id = ANY($1::int[])`, [ + createdUserIds, + ]); + } + await pool.end(); +}); + +async function setLanguage(page, lang) { + // i18n.ts reads `localStorage.getItem("tx-lang")` at module-init time, so + // seed it before any page script runs. + await page.addInitScript((l) => { + try { + window.localStorage.setItem("tx-lang", l); + } catch { + /* localStorage may not be available before navigation; safe to ignore */ + } + }, lang); +} + +async function loginViaUi(page, username, password) { + await page.goto("/login"); + await page.locator("#username").fill(username); + await page.locator("#password").fill(password); + await Promise.all([ + page.waitForURL((url) => !url.pathname.endsWith("/login"), { + timeout: 15_000, + }), + page.locator('form button[type="submit"]').click(), + ]); +} + +// Locate the live toast root. The shadcn Toaster renders Radix's +// as an
    containing one
  1. per active +// toast. We pick the most recently opened one. +function toastRegion(page) { + return page.locator('li[data-state="open"]').last(); +} + +// Track DELETE /api/orders/:id calls so we can assert on them. +function trackDeletes(page, ids) { + const seen = new Set(); + const expected = new Set(ids.map((id) => `/api/orders/${id}`)); + page.on("request", (req) => { + const path = new URL(req.url()).pathname; + if (req.method() === "DELETE" && expected.has(path)) { + seen.add(path); + } + }); + return { + seen, + sawAnyDelete: () => seen.size > 0, + sawAllDeletes: () => seen.size === ids.length, + }; +} + +test.describe("My Orders bulk Clear-finished + undo flow", () => { + test("English plural: Clear 3 finished + Undo restores all rows", async ({ + page, + }) => { + const user = await createUser("clear_undo_en", "en"); + const service = await getAvailableService(); + const serviceName = service.nameEn; + + const ids = await insertFinishedOrders(user.id, service.id, 3, "completed"); + + await setLanguage(page, "en"); + await loginViaUi(page, user.username, TEST_PASSWORD); + await page.goto("/my-orders"); + + // All 3 cards should be visible up front. + const cards = page + .locator(".glass-panel.rounded-xl") + .filter({ hasText: serviceName }); + await expect(cards).toHaveCount(3); + + // The "Clear N finished" button uses myOrders.clearFinished_other for N>=2. + const clearBtn = page.getByRole("button", { + name: "Clear 3 finished", + exact: true, + }); + await expect(clearBtn).toBeVisible(); + + // Fail the test if any DELETE goes out — Undo must cancel the timer. + const tracker = trackDeletes(page, ids); + + await clearBtn.click(); + const confirmDialog = page.getByRole("alertdialog"); + await expect(confirmDialog).toBeVisible(); + await confirmDialog + .getByRole("button", { name: "Yes, clear", exact: true }) + .click(); + + // Cards are filtered out of the list while delete is pending. + await expect(cards).toHaveCount(0); + + // Plural toast: myOrders.clearedCount_other => "{count} orders deleted". + const toast = toastRegion(page); + await expect(toast).toContainText("3 orders deleted"); + + // Click Undo well inside the 7s window. + await toast.getByRole("button", { name: "Undo" }).click(); + + // Cards reappear immediately. + await expect(cards).toHaveCount(3); + + // Wait past the original delete window to make sure the scheduled + // shared-timer DELETE never fires for any of the IDs. + await page.waitForTimeout(UNDO_WINDOW_MS + 1500); + + expect(tracker.sawAnyDelete()).toBe(false); + + // All 3 rows still exist in the DB. + expect(await countExisting(ids)).toBe(3); + + // Cards still visible after the wait. + await expect(cards).toHaveCount(3); + }); + + test("English plural: Clear 2 finished + timer expiry deletes all rows", async ({ + page, + }) => { + const user = await createUser("clear_expire_en", "en"); + const service = await getAvailableService(); + const serviceName = service.nameEn; + + // Mix completed + cancelled to confirm both finished states are swept. + const completedIds = await insertFinishedOrders( + user.id, + service.id, + 1, + "completed", + ); + const cancelledIds = await insertFinishedOrders( + user.id, + service.id, + 1, + "cancelled", + ); + const ids = [...completedIds, ...cancelledIds]; + + await setLanguage(page, "en"); + await loginViaUi(page, user.username, TEST_PASSWORD); + await page.goto("/my-orders"); + + const cards = page + .locator(".glass-panel.rounded-xl") + .filter({ hasText: serviceName }); + await expect(cards).toHaveCount(2); + + const tracker = trackDeletes(page, ids); + + const clearBtn = page.getByRole("button", { + name: "Clear 2 finished", + exact: true, + }); + await clearBtn.click(); + const confirmDialog = page.getByRole("alertdialog"); + await expect(confirmDialog).toBeVisible(); + await confirmDialog + .getByRole("button", { name: "Yes, clear", exact: true }) + .click(); + + // Plural toast appears with "2 orders deleted". + const toast = toastRegion(page); + await expect(toast).toContainText("2 orders deleted"); + + // Cards are gone from the list while delete is pending. + await expect(cards).toHaveCount(0); + + // Wait for the shared timer to fire and BOTH DELETE calls to complete. + await expect + .poll(() => tracker.seen.size, { + timeout: UNDO_WINDOW_MS + 10_000, + intervals: [250, 500, 1000], + }) + .toBe(2); + + // Both rows are removed from the DB. + await expect + .poll(() => countExisting(ids), { + timeout: 5000, + intervals: [250, 500], + }) + .toBe(0); + + // Cards stay gone. + await expect(cards).toHaveCount(0); + }); + + test("Arabic singular: Clear 1 finished uses the singular toast title", async ({ + page, + }) => { + const user = await createUser("clear_singular_ar", "ar"); + const service = await getAvailableService(); + const serviceName = service.nameAr; + + const [orderId] = await insertFinishedOrders( + user.id, + service.id, + 1, + "completed", + ); + + await setLanguage(page, "ar"); + await loginViaUi(page, user.username, TEST_PASSWORD); + await page.goto("/my-orders"); + + const cards = page + .locator(".glass-panel.rounded-xl") + .filter({ hasText: serviceName }); + await expect(cards).toHaveCount(1); + + // Fail the test if a DELETE actually goes out — Undo must cancel the timer. + const tracker = trackDeletes(page, [orderId]); + + // Arabic clearFinished_one = "مسح طلب منتهٍ". + const clearBtn = page.getByRole("button", { + name: "مسح طلب منتهٍ", + exact: true, + }); + await expect(clearBtn).toBeVisible(); + await clearBtn.click(); + + const confirmDialog = page.getByRole("alertdialog"); + await expect(confirmDialog).toBeVisible(); + // Arabic clearConfirm = "نعم، امسح". + await confirmDialog + .getByRole("button", { name: "نعم، امسح", exact: true }) + .click(); + + // Card filtered out while pending. + await expect(cards).toHaveCount(0); + + // Singular branch in scheduleDelete uses myOrders.deleted (NOT + // clearedCount_one). In Arabic that is "تم حذف الطلب". + const toast = toastRegion(page); + await expect(toast).toContainText("تم حذف الطلب"); + + // Undo within the window. Arabic undo label = "تراجع". + await toast.getByRole("button", { name: "تراجع" }).click(); + + // Card returns immediately. + await expect(cards).toHaveCount(1); + + // Wait past the original delete window to confirm the timer was cancelled. + await page.waitForTimeout(UNDO_WINDOW_MS + 1500); + + expect(tracker.sawAnyDelete()).toBe(false); + expect(await countExisting([orderId])).toBe(1); + await expect(cards).toHaveCount(1); + }); +});