Adds a Playwright suite (App/tests/staging/) that logs into the running staging instance (ppms-staging, :3200) and verifies each closed portal issue is actually fixed — feature level, driving the real UI, one spec per issue. To make credential login possible against the prod-mirror pelagia_test (which only holds real, mostly SSO-only users), prisma/seed-test-users.ts idempotently seeds one known-password @pelagia.local user per role, and automation/refresh-test-db.sh runs it after every daily refresh so the logins persist on staging. Result against staging: 41 passed, 1 skipped (#10 — no attachment data on staging). Two closed issues were found NOT fixed and are recorded as documented test.fail(): - #13 Accounts "payments completed this month" card is absent. - #24/#40 logout tooltip still reads "Sign out" (pipeline test issues). Docs/TESTING.md documents the suite, the seeded users, how to run it against staging, and the full issue -> script mapping. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
7.8 KiB
Testing
This repo has three test tiers (see App/CLAUDE.md → Commands):
| Tier | Tool | Scope | Command |
|---|---|---|---|
| Unit | Vitest (jsdom) | pure functions / components | pnpm test |
| Integration | Vitest (node + real DB) | server actions against a Postgres DB | pnpm test:integration |
| E2E (local) | Playwright | full UI against a local pnpm dev |
pnpm test:e2e |
This document covers a fourth, purpose-built tier:
Staging closed-issue verification (App/tests/staging/)
A feature-level Playwright suite that drives the running staging instance
(pm2 ppms-staging, port 3200 on pms1 — see ../automation/README.md → Staging)
to verify that every closed portal issue is actually fixed on the deployed build.
Unlike the local E2E suite it does not start a dev server; it logs in and clicks
through the real staging app, exactly as a user would.
Why a dedicated tier
Staging runs against pelagia_test, a daily mirror of production. That mirror only
contains real @pelagiamarine.com users — most are SSO-only and none have a password
we know — so the credentials login can't be used for automated testing. To solve this
without touching production, the refresh seeds deterministic test users (one per
role) with known passwords.
Test users (seeding)
App/prisma/seed-test-users.ts idempotently
upserts one credential-capable login per role on the throwaway @pelagia.local
domain (no collision with real accounts):
| Password | Role | |
|---|---|---|
tech@pelagia.local |
tech1234 |
TECHNICAL |
manning@pelagia.local |
manning1234 |
MANNING |
accounts@pelagia.local |
accounts1234 |
ACCOUNTS |
manager@pelagia.local |
manager1234 |
MANAGER |
superuser@pelagia.local |
super1234 |
SUPERUSER |
auditor@pelagia.local |
audit1234 |
AUDITOR |
admin@pelagia.local |
admin1234 |
ADMIN |
site@pelagia.local |
site1234 |
SITE_STAFF |
automation/refresh-test-db.sh runs this seed
automatically after every daily refresh of pelagia_test, so the logins always exist
on staging. To seed manually (e.g. before a one-off run):
DATABASE_URL="postgresql://…/pelagia_test" pnpm tsx prisma/seed-test-users.ts
Running the suite
From a machine that can reach pms1, open SSH tunnels to the staging app and the
DB (the suite reads a few fixture ids straight from pelagia_test so it stays stable
across the daily refresh):
ssh -N -L 3200:localhost:3200 -L 15432:localhost:5432 shad0w@<pms1>
Then, from App/:
PLAYWRIGHT_BASE_URL=http://localhost:3200 \
DATABASE_URL="postgresql://pelagia_user:…@localhost:15432/pelagia_test" \
pnpm exec playwright test --config playwright.staging.config.ts
PLAYWRIGHT_BASE_URL— the staging app (defaulthttp://localhost:3200).DATABASE_URL— the tunnelled staging DB, used only for read-only fixture lookups (which approved/closed PO to open, expected counts). Every assertion runs against the live UI.
What each script verifies (issue → script map)
One spec file per issue; the filename is the mapping. SKIP means the staging data
currently has no row to exercise the case (the spec self-skips with a message).
| Issue | Script | Verifies | Result |
|---|---|---|---|
| — | 00-smoke.spec.ts |
staging reachable + all seeded users can log in | PASS |
| #4 | issue-04-po-date-field.spec.ts |
optional, back/forward-datable PO Date field on the PO form | PASS |
| #5 | issue-05-approved-date-as-po-date.spec.ts |
approved PO detail shows the approval date as the PO Date | PASS |
| #6 | issue-06-closed-list-filters.spec.ts |
manager sees all CLOSED POs; submitter's Closed view excludes APPROVED | PASS |
| #8 | issue-08-export-includes-description.spec.ts |
exported PO includes the line-item optional description | PASS |
| #10 | issue-10-attachments-grouped.spec.ts |
PO detail groups attachments by type (Submission/Payment/Delivery) | SKIP (no attachment data on staging) |
| #11 | issue-11-terms-catalogue.spec.ts |
admin T&C catalogue page + dynamic PO terms editor | PASS |
| #12 | issue-12-approved-this-month-card.spec.ts |
manager 'Approved This Month' card shows the correct live count (was stuck at 0) | PASS |
| #13 | issue-13-payments-this-month-card.spec.ts |
accounts 'Payments completed this month' card | KNOWN FAIL — not implemented on staging |
| #14 | issue-14-email-to-vendor.spec.ts |
'Email to vendor' button on an approved PO with a vendor email | PASS |
| #19 | issue-19-place-of-delivery-dropdown.spec.ts |
Place of Delivery is a dropdown + admin delivery-locations page | PASS |
| #24/#40 | issue-24-40-logout-tooltip.spec.ts |
logout tooltip reads 'Log out' | KNOWN FAIL — still 'Sign out' (these were pipeline test issues) |
| #26/#41 | issue-26-41-total-po-card.spec.ts |
'Total Purchase Orders' card count correct (#41) + links to history (#26) | PASS |
| #31 | issue-31-history-multi-status.spec.ts |
PO history filter accepts multiple OR-ed statuses | PASS |
| #32 | issue-32-approved-month-clickthrough.spec.ts |
'Approved This Month' card links to history filtered by approval date | PASS |
| #44 | issue-44-line-item-units.spec.ts |
line-item unit dropdown includes months and year(s) | PASS |
| #50 | issue-50-rupee-compact-format.spec.ts |
approved-spend card uses ₹ with compact L/Cr formatting | PASS |
| #53 | issue-53-cancel-po-modal.spec.ts |
manager Cancel-PO modal with type-'cancel'-to-confirm guard | PASS |
| #57 | issue-57-vendor-search-catalogue.spec.ts |
/catalogue/vendors searchable by vendor id, id shown next to name | PASS |
| #96 | issue-96-sidebar-collapsible.spec.ts |
sidebar sections collapsible, collapsed by default, single-open | PASS |
| #104 | issue-104-history-pagination.spec.ts |
/history items-per-page pagination | PASS |
| #109 | issue-109-new-po-vendor-search.spec.ts |
new-PO vendor field is a searchable combobox (name + code) | PASS |
| #75/#76/#79/#81/#83/#86 | crewing-epics.spec.ts |
each crewing epic's primary surface renders for an authorised role | PASS |
Issues not covered by a staging spec (and why)
| Issue | Reason |
|---|---|
| #1 | "Add CHANGELOG.md" — pipeline bootstrap; verified by the file existing at the repo root, not a runtime feature. |
| #3, #42 | Explicit pipeline / token test issues ("no action needed; close without a fix"). |
| #7 | Inventory-on-approval — the inventory surface is gated by NEXT_PUBLIC_INVENTORY_ENABLED, which is false on staging, so it is not UI-verifiable there. Covered by the tests/integration inventory tests. |
| #17 | GST CAPTCHA extraction — depends on the live external GST portal (GstService); not deterministically testable. |
| #18 | "Prompt to save draft on navigate-away" — a client-side beforeunload guard; not reliably driveable in headless Playwright. |
| Crewing deep flows (#77 pipeline, #78 onboarding, #80 PPE, #82 appraisal, #85 sign-off) | State-machine flows covered by the existing integration suites (tests/integration/applications.test.ts, onboarding.test.ts, appraisal.test.ts, signoff.test.ts, etc.). The staging suite smoke-checks the epic surfaces render. |
Findings (verification result)
Running the suite against staging surfaced two closed issues that are not actually fixed on the current build:
- #13 — the Accounts dashboard has no "Payments completed this month" card (only "Ready for Payment" and "Payment Queue Value").
- #24 / #40 — the logout control tooltip still reads "Sign out", not "Log out". (Both were pipeline / button-simulation test issues, likely closed without a code change.)
These are encoded as test.fail() specs so the suite stays green while the gaps are
recorded; if either is fixed later, its spec flips to passing and flags the
annotation for removal.