# 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`](../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`](../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): | Email | 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`](../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): ```bash 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): ```bash ssh -N -L 3200:localhost:3200 -L 15432:localhost:5432 shad0w@ ``` Then, from `App/`: ```bash 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 (default `http://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.