test(e2e): add API CRUD specs for time-tracking, projects, billing, contracts (PMS-155) #136
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/pms-155-e2e-core-modules"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Adds Playwright E2E API specs for the next batch of real PSA modules (PMS-155, "fill out E2E testing for the rest"): time-tracking, projects, billing, and contracts. Each spec drives a full create/read/update/list/delete lifecycle against the deployed API through the existing bearer-token request fixture, matching the style of the existing tickets/contacts specs.
This is the first batch; the remaining real modules (tenants extras, calendar/dispatch, sla, assets, knowledge_base, notifications, rmm, reports, settings, audit) are left for follow-up PRs to keep the diff reviewable and contain deploy-gate risk.
Module gating (important)
These four modules are tenant-gated and default to DISABLED:
is_module_enabledCOALESCEs a missingmodule_configrow toFALSE, so every route behind aRequireModuleEnabledextractor 404s until the module is on. Each spec enables its module first via the admin-onlyPUT /api/v1/settings/modules/{module}route (newlib/factories.enableModulehelper), so the specs run regardless of the staging tenant's current config. The enable persists on the E2E tenant; that is configuration, not swept residue.No new-route deadlock: unlike PMS-149, the routes under test already ship in staging, so the specs assert real responses directly rather than tolerating a pre-deploy 405.
Coverage shape (driven by what is cleanable)
Mechanics
tests/audit_hooks.rs).managed_services, payment_methodcheck, item_typeproduct, rounding_methodnearest) are taken from the migration CHECK constraints.apiproject'stestMatchis widened to pick up the four new specs.Verification
npx tsc --noEmitclean.npx playwright test --listshows all four new specs under theapiproject.🤖 Generated with Claude Code
Fills E2E coverage for the next batch of real PSA modules. Each spec drives a full create/read/update/list/delete lifecycle against the deployed API via the existing bearer-token request fixture, mirroring the tickets/contacts specs. These four modules are tenant-gated and default to DISABLED (is_module_enabled COALESCEs a missing module_config row to FALSE), so every spec enables its module up front through the admin-only PUT /api/v1/settings/modules/{module} route via a new lib/factories.enableModule helper. This keeps the specs self-sufficient regardless of the staging tenant's current config. The routes themselves already ship in staging, so unlike PMS-149 there is no new-route deploy-gate deadlock to tolerate here. Coverage notes: billing invoices have no DELETE route, so creating one would leave permanent residue (the leak PMS-149/PMS-155 set out to avoid); the billing spec therefore smoke-reads the invoice list only and runs the full lifecycle on tax-rates and payments, which are deletable. Rate-card items are skipped because they require a work_type_id that would couple the contracts spec to the time_tracking module. Decimals are sent as JSON strings to match the house convention in tests/audit_hooks.rs. Each record carries a run suffix and is deleted inline in reverse-dependency order; global teardown gains best-effort backstop sweeps for the new top-level named resources (projects, contracts, work types, rounding rules, task statuses, rate cards, tax rates) and the api project's testMatch is widened to pick the new specs up. #PMS-155 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>Third batch of E2E coverage for the cross-cutting/platform modules. - notifications: template + channel create/list/delete. Not module-gated; writes are admin-only. Templates and channels expose no update or get-by-id route, so the lifecycle is create -> list -> delete. channel_type uses CHECK-constrained enums ('email' for the template, 'in_app' for the channel since it needs no external config). - settings: full tenant-setting upsert/read/update/delete keyed by (category, key). A throwaway 'e2e' category with a run-suffixed key is used so validate_setting_value accepts the value verbatim (unknown category/key pairs pass) and nothing real is overwritten; the row is deleted inline and its absence confirmed with a 404. - audit: read-only end-to-end check. Creates a company, then asserts GET /audit-log?entity_type=companies&action=create surfaces a matching entry by entity_id (the contacts service writes the audit row in the same transaction, so it is immediately queryable; default sort is newest-first). Company cleaned up inline. - reports: read-only smoke. Enables the gated 'reports' module, then asserts the dashboard/tickets/time/billing aggregations and a CSV export all return 200 (no mandatory params; date ranges default to 30 days; billing's manager gate is satisfied by the E2E admin). Nothing created, no residue. global.teardown.ts gains backstop sweeps for notification templates and channels; the api project testMatch is widened for the four new specs. #PMS-155 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>Fourth batch, closing out the remaining real modules. - rmm: connection -> alert rule + device mapping. The module is tenant-gated ('rmm_integration') and every route is admin-only. The connection is created with throwaway credentials: create_connection only stores the api_key encrypted at rest (no live provider call - that is the separate /test route) and the response never echoes the key, so no real RMM system is needed. provider uses the CHECK-constrained enum 'tactical_rmm'. The connection gets full create/read/update/list; alert rules and device mappings are create/list/delete only and reference the connection (FK), so they are deleted before it. - dispatch: read-only smoke of the aggregated technician board (RequireCalendar). It requires both from+to RFC 3339 query params (400s without), so the spec passes a one-day range and asserts 200. No residue. global.teardown.ts gains backstop sweeps for rmm alert rules, device mappings, and connections (children before the connection); device mappings carry a run-suffixed device_name so they are sweepable. The api project testMatch is widened for the two new specs. #PMS-155 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>