pelagia-portal/Spec/TEST_PLAN.md
Hardik d769cae71e chore(inventory): remove item detail page; move SiteSelect to shared components
- Delete /inventory/items/[id] — items expand inline in the list
- Move SiteSelect from deleted [id] folder to components/inventory/site-select
- Fix admin product detail page import to use new shared path
- Fix items-table: Fragment key prop, restore Link import, plain text item names
- Fix vendor-items-table: remove broken link to deleted item detail page

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 00:07:04 +05:30

13 KiB
Raw Blame History

Pelagia Portal — Test Plan

Version: 1.0
Date: 2026-05-09
Project: Pelagia Marine Services PO Portal
Scope: Unit, Integration, and E2E test coverage across all portal features


1. Overview

This document describes the testing strategy, scope, tooling, and coverage matrix for the Pelagia Portal. It is intended as the authoritative reference for what is tested, why, and how to run each layer.

The portal manages the full lifecycle of purchase orders: creation, submission, manager review, vendor assignment, payment, and receipt confirmation. Testing focuses on correctness of state transitions, permission enforcement, and data integrity.


2. Testing Stack

Layer Tool Environment Command
Unit Vitest 2.x jsdom pnpm test
Integration Vitest 2.x Node (real DB) pnpm test:integration
E2E Playwright 1.49 Chromium (dev server) pnpm test:e2e

Key libraries: @testing-library/react, @testing-library/jest-dom, @testing-library/user-event.

Unit tests live in tests/unit/. Integration tests live in tests/integration/. E2E specs live in tests/e2e/.

Integration tests run serially in a single fork (poolOptions.forks.singleFork = true) to avoid database conflicts. Each test suite cleans up its own data via afterEach using the deletePosByTitle(PREFIX) helper.


3. Test Data & Environment

3.1 Seeded Data (prisma/seed.ts)

Entity Records Notes
Users 5 admin, manager, tech, accounts, manning
Vessels 3 MV Pelagia Star, MV Aegean Wind, MV Poseidon
Accounts 3 TECH-OPS, CREW-MGT, FUEL-BNK
Vendors 12 VND-0001 to VND-0012; VND-0003 and VND-0012 are unverified
Products 25 Spanning lubricants, filters, safety, rope, electrical, paint, navigation

Re-run with npx tsx prisma/seed.ts before integration tests if the database is reset.

3.2 Authentication Mocking

Integration tests mock @/auth to inject a session without real credentials:

vi.mock("@/auth", () => ({ auth: vi.fn() }));
vi.mocked(auth).mockResolvedValue(makeSession(userId, "MANAGER"));

makeSession(userId, role) is defined in tests/integration/helpers.ts.

3.3 Side-Effect Mocking

All integration and unit tests mock:

  • @/lib/notifier — prevents email dispatch
  • next/cache (revalidatePath) — avoids Next.js cache calls outside a server context

4. Coverage Matrix

4.1 Unit Tests

File Test File Cases Covered
lib/permissions.ts tests/unit/permissions.test.ts All 7 roles × key permissions; requirePermission throws
lib/po-state-machine.ts tests/unit/po-state-machine.test.ts canPerformAction, getTransition, requiresNote, getAvailableActions; MANAGER/ACCOUNTS expansions
lib/po-import-parser.ts tests/unit/po-import-parser.test.ts cellStr, cellNum, parseSheet (real + synthetic), parseWorkbook
lib/validations/po.ts tests/unit/validations.test.ts lineItemSchema, createPoSchema, TC defaults
components/po/po-line-items-editor.tsx tests/unit/po-line-items-editor.test.tsx Edit mode, read-only mode, totals, add/remove
components/po/po-status-badge.tsx tests/unit/po-status-badge.test.tsx All status labels
lib/utils.ts tests/unit/utils.test.ts formatCurrency, formatDate, generatePoNumber, status maps

4.2 Integration Tests

Test File Feature Scenarios
create-po.test.ts S-01, S-02, S-03 Draft, submit, line items, totals, optional fields, notifications
approval-actions.test.ts M-02, M-03, M-04, S-06, S-07 Approve, reject, request edits, vendor ID flow, resubmit
payment-actions.test.ts A-01, A-02 Payment queue, mark paid
discard-po.test.ts Discard draft Owner, MANAGER, SUPERUSER can discard; ACCOUNTS and non-owners denied; status guard; cascade cleanup
vendor-approval.test.ts Vendor gate + provide vendor ID Approval blocked without vendor; ACCOUNTS can provide vendor ID; unverified vendor rejected; AUDITOR denied
manager-po-creation.test.ts Manager creates POs MANAGER can create, submit, discard; ACCOUNTS denied; role documented for self-approval
products-search.test.ts Product search API Auth, min-length validation, name/code/description search, case-insensitive, max 10, inactive excluded, Decimal serialised
import-api.test.ts Excel import API Auth (TECHNICAL/ACCOUNTS → 403), no file, invalid file, correct parse of Sample_PO.xlsx

4.3 E2E Tests (Playwright)

Spec File Scenarios
auth.spec.ts Login, redirect on bad creds, role badge, sign-out
submitter-journey.spec.ts Create draft, add line items, submit, see status transitions
manager-approvals.spec.ts Review PO, approve with/without note, reject, request edits
accounts-payment.spec.ts Payment queue, process payment, confirm receipt
po-export.spec.ts PDF and XLSX export buttons and content

5. Permission Test Matrix

The table below documents every role's expected access to key operations. ✓ = allowed, ✗ = denied.

Operation TECHNICAL MANNING ACCOUNTS MANAGER SUPERUSER AUDITOR ADMIN
Create PO
Submit PO
Edit own draft
Discard own draft
Discard any draft
Approve PO
Reject PO
Request edits
Provide vendor ID Own PO only Own PO only
Process payment
Confirm receipt Own PO only Own PO only
Manage vendors
Manage products
Import PO
View analytics

Business rules tested explicitly:

  • A vendor must be assigned before a manager can approve a PO.
  • Only verified vendors (those with a vendorId field) may be assigned via provideVendorId.
  • Discarding is only possible on DRAFT status POs.

6. Feature-Level Test Scenarios

F-01: PO Creation & Draft Management

ID Scenario Type File
S-01 Create PO with multiple line items; verify totals Integration create-po.test.ts
S-02 Save as draft; verify status = DRAFT Integration create-po.test.ts
S-02a ACCOUNTS role denied creation Integration create-po.test.ts
S-02b MANAGER can create and save a draft Integration manager-po-creation.test.ts
S-03 Submit for approval; status = MGR_REVIEW Integration create-po.test.ts
S-04 Discard draft by owner Integration discard-po.test.ts
S-04a MANAGER discards any draft Integration discard-po.test.ts
S-04b ACCOUNTS cannot discard Integration discard-po.test.ts
S-04c Cannot discard a submitted PO Integration discard-po.test.ts

F-02: Approval Workflow

ID Scenario Type File
M-01 Manager sees pending POs E2E manager-approvals.spec.ts
M-02 Approve PO → MGR_APPROVED Integration / E2E approval-actions.test.ts
M-02a Approve with note stores managerNote Integration approval-actions.test.ts
M-02b Approval blocked — no vendor assigned Integration vendor-approval.test.ts
M-03 Reject PO with note Integration / E2E approval-actions.test.ts
M-04 Request edits → EDITS_REQUESTED Integration approval-actions.test.ts
M-04a Request vendor ID → VENDOR_ID_PENDING Integration approval-actions.test.ts
M-04b TECHNICAL denied approval Integration approval-actions.test.ts

F-03: Vendor ID Assignment

ID Scenario Type File
S-06 TECHNICAL provides vendor ID on own PO Integration approval-actions.test.ts
S-06a ACCOUNTS provides vendor ID Integration vendor-approval.test.ts
S-06b Unverified vendor rejected Integration vendor-approval.test.ts
S-06c AUDITOR cannot provide vendor ID Integration vendor-approval.test.ts
S-06d Wrong status → error Integration vendor-approval.test.ts

F-04: Payment & Receipt

ID Scenario Type File
A-01 Accounts processes payment Integration / E2E payment-actions.test.ts
A-02 Mark as paid with reference Integration / E2E payment-actions.test.ts

F-05: Excel Import

ID Scenario Type File
I-01 Parser extracts 1 line item from Sample_PO.xlsx Unit po-import-parser.test.ts
I-02 T&C rows not included in line items Unit po-import-parser.test.ts
I-03 Vendor name, PI quotation, place of delivery extracted Unit po-import-parser.test.ts
I-04 GST rate > 1 normalised to fraction Unit po-import-parser.test.ts
I-05 INSTRUCTIONS TO VENDORS row stops parsing Unit po-import-parser.test.ts
I-06 TECHNICAL / ACCOUNTS denied (403) Integration import-api.test.ts
I-07 Unauthenticated denied (401) Integration import-api.test.ts
I-08 No file → 400 Integration import-api.test.ts
I-09 Invalid binary → 400 Integration import-api.test.ts
I-10 MANAGER receives parsed results (200) Integration import-api.test.ts
I-11 Correct line item values in API response Integration import-api.test.ts
ID Scenario Type File
P-01 Unauthenticated → 401 Integration products-search.test.ts
P-02 Query < 2 chars → empty array Integration products-search.test.ts
P-03 Search by name substring Integration products-search.test.ts
P-04 Search by product code Integration products-search.test.ts
P-05 Search by description text Integration products-search.test.ts
P-06 Case-insensitive matching Integration products-search.test.ts
P-07 Max 10 results returned Integration products-search.test.ts
P-08 lastPrice serialised as number not Prisma Decimal Integration products-search.test.ts
P-09 Inactive products excluded Integration products-search.test.ts

7. Known Gaps & Out-of-Scope Items

Currently untested (acceptable gaps)

Area Reason
File upload to S3 / storage Requires live AWS credentials; tested manually in staging
Email notification content notify() is mocked; email body format tested via review
PDF/XLSX export content Snapshot-tested manually; E2E checks endpoint responds
Receipt confirmation workflow Happy path covered in E2E; integration test pending
Admin CRUD (users, vessels, accounts, products) Standard CRUD; covered by E2E smoke tests

Out of scope

  • Performance / load testing
  • Accessibility (a11y) automated checks
  • Cross-browser testing (Chromium only)
  • Mobile viewport testing

8. Running the Tests

# All unit tests (fast, no DB needed)
pnpm test

# Unit tests in watch mode during development
pnpm test:watch

# Integration tests (requires seeded DB)
pnpm test:integration

# All unit + integration
pnpm test:all

# E2E tests (requires running dev server)
pnpm test:e2e

# E2E with interactive Playwright UI
pnpm test:e2e:ui

Pre-requisites for integration tests

  1. A PostgreSQL instance running and .env pointing to it (DATABASE_URL).
  2. Schema applied: npx prisma migrate deploy (or npx prisma db push in dev).
  3. Data seeded: npx tsx prisma/seed.ts.

CI behaviour

Integration tests and E2E tests run on every PR. E2E tests retry twice on failure (playwright.config.ts). The test:all script is used for pre-merge validation.


9. Test Authorship Conventions

  • Naming: describe blocks map to feature scenarios (e.g., "S-02 — save as draft"). it blocks describe the outcome, not the action.
  • Prefix isolation: Every integration test uses a PREFIX constant (e.g., "INTTEST_DISCARD_") and cleans up with afterEach(() => deletePosByTitle(PREFIX)).
  • No test interdependence: Each test creates its own data. Tests must pass in isolation and in any order.
  • Negative tests first: Each describe block should include at least one negative (denial/error) case before or after the happy path.
  • Avoid any: Type assertions in tests should use as { id: string } or similar narrow casts, not as any.