test(pms-17): integration tests pinning F4 fix + site/contact CRUD + portal flag + F9 filter #71
No reviewers
Labels
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
psa-systems/mokosh-server!71
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/pms-17-tests"
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?
PMS-17 ('Story: Contacts, companies, and sites') had four code ACs all
implemented on main (PMS-18 update_site, PMS-19 create_portal_access,
PMS-20 dead /companies alias removed, the CompanyFilter/ContactFilter
length-validation) but the fifth AC - integration tests covering
'company/contact/site CRUD including the previously-broken site
update' - shipped as just one company-CRUD test in tests/contacts.rs.
The next refactor that silently broke update_site again (the original
F4 defect: validate + get_site + return unchanged) would land
unnoticed.
Add five tests, all using the existing common::seed_admin /
common::boot / common::login harness so the boilerplate is small.
A.1 site_update_persists_changes (F4 regression pin / PMS-18)
PUT a renamed name + new is_primary + new phone, assert the PUT
response shows them, then INDEPENDENTLY GET the site and assert
the same values again. The second assertion is the actual F4
pin: a no-op implementation that just echoes the request body
passes the first assertion and fails the second.
A.2 site_crud_happy_path
Direct analogue of company_crud_happy_path for sites. Creates
two sites, lists them via /companies/{id}/sites, flips A to
primary and verifies B was auto-demoted (the side-effect at
service.rs::update_site's pre-UPDATE), deletes A, re-lists.
A.3 contact_crud_happy_path
Same shape for contacts. CRUD + a re-GET after PUT to verify
the title/department update actually persisted. Final DELETE
followed by an asserted 404 on GET.
A.4 create_contact_with_portal_access_flips_flag (PMS-19 pin)
Creates one contact with create_portal_access:true, one without,
and re-fetches both to confirm is_portal_user is exactly the
flag value. Negative control catches a future impl that
silently returns is_portal_user:true unconditionally.
A.5 company_filter_rejects_oversize_q (F9 pin)
GET /contacts/companies?q=<1000 chars> -> expect 400 or 422
(the route handler calls filter.validate()? against
CompanyFilter where q has length(max=200)). Single test
suffices; ContactFilter shares the same code path.
Two small DRY helpers at the top of the file (create_company,
create_site) consolidate the bearer + POST + extract-id pattern
every PMS-17 test needs. Each is #[allow(dead_code)] because
clippy's per-binary dead-code pass fires on the company test if
it doesn't happen to call them.
cargo check --tests and cargo clippy --tests pass clean. Actual
test execution against a live postgres deferred to CI (local disk
ran out of room building the test binary).
Closes the AC5 gap on PMS-17.
PMS-17 ('Story: Contacts, companies, and sites') had four code ACs all implemented on main (PMS-18 update_site, PMS-19 create_portal_access, PMS-20 dead /companies alias removed, the CompanyFilter/ContactFilter length-validation) but the fifth AC - integration tests covering 'company/contact/site CRUD including the previously-broken site update' - shipped as just one company-CRUD test in tests/contacts.rs. The next refactor that silently broke update_site again (the original F4 defect: validate + get_site + return unchanged) would land unnoticed. Add five tests, all using the existing common::seed_admin / common::boot / common::login harness so the boilerplate is small. A.1 site_update_persists_changes (F4 regression pin / PMS-18) PUT a renamed name + new is_primary + new phone, assert the PUT response shows them, then INDEPENDENTLY GET the site and assert the same values again. The second assertion is the actual F4 pin: a no-op implementation that just echoes the request body passes the first assertion and fails the second. A.2 site_crud_happy_path Direct analogue of company_crud_happy_path for sites. Creates two sites, lists them via /companies/{id}/sites, flips A to primary and verifies B was auto-demoted (the side-effect at service.rs::update_site's pre-UPDATE), deletes A, re-lists. A.3 contact_crud_happy_path Same shape for contacts. CRUD + a re-GET after PUT to verify the title/department update actually persisted. Final DELETE followed by an asserted 404 on GET. A.4 create_contact_with_portal_access_flips_flag (PMS-19 pin) Creates one contact with create_portal_access:true, one without, and re-fetches both to confirm is_portal_user is exactly the flag value. Negative control catches a future impl that silently returns is_portal_user:true unconditionally. A.5 company_filter_rejects_oversize_q (F9 pin) GET /contacts/companies?q=<1000 chars> -> expect 400 or 422 (the route handler calls filter.validate()? against CompanyFilter where q has length(max=200)). Single test suffices; ContactFilter shares the same code path. Two small DRY helpers at the top of the file (create_company, create_site) consolidate the bearer + POST + extract-id pattern every PMS-17 test needs. Each is #[allow(dead_code)] because clippy's per-binary dead-code pass fires on the company test if it doesn't happen to call them. cargo check --tests and cargo clippy --tests pass clean. Actual test execution against a live postgres deferred to CI (local disk ran out of room building the test binary). Closes the AC5 gap on PMS-17.