Skip to content

test(shipping): give the suite teeth — role gates, audit assertions, RPC integration (SR-4) - #62

Merged
LongXL6 merged 1 commit into
mainfrom
test/shipping-sr4-test-backbone
Jul 2, 2026
Merged

test(shipping): give the suite teeth — role gates, audit assertions, RPC integration (SR-4)#62
LongXL6 merged 1 commit into
mainfrom
test/shipping-sr4-test-backbone

Conversation

@LongXL6

@LongXL6 LongXL6 commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

Final PR of the 2026-07-03 shipping refinement — the P1 test-blindness cluster. Before this, three guardrail regressions passed the whole suite silently: deleting every writeAudit call, downgrading withRole("editor") to viewer, or regressing any RPC body (all route tests mock rpc()).

New coverage

  • role-gates.test.ts — one table pins the min-role of all 29 shipping withRole call sites (the withRole mock returns 204 before the handler body runs, so no supabase mocks needed). A count assertion flags unregistered new routes.
  • writeAudit assertions in the 9 mutation suites that mocked-but-never-asserted it, plus not-called-on-4xx checks — the "audit is mandatory" guardrail is finally executable.
  • Export suite: BOM bytes, ¥ conversion, shipment.export audit, and formula-injection neutralization including the leading-whitespace bypass.
  • Sanitize-through-route: proves GET /parcels actually feeds sanitizeSearchTerm output into .or() — the unit test alone couldn't catch the route dropping the call.
  • rpc.integration.test.ts (RUN_DB_TESTS-gated, dev branch only, marked fixtures + cleanup): executable pins for the most-patched SQL surface — advance skip-matrix (never touches picked_up), attach in-txn re-check, detach roundtrip, pack-request partial/re-run approval, one-open-request 23505, confirm-token idempotency, revert reason on the timeline, bulk-receive id sets, reassign, token-uniqueness trigger.

Bug found by writing the tests → migration 20260703000006

20260703000001 approved a pack request only when newly-moved count == total — so the sanctioned re-run flow (partial attach → stragglers received → attach again) could never reach approved: the re-run only moves the stragglers. Approval now checks "every linked parcel sits on this batch after the attach"; attached still reports newly-moved for the officer's toast; the route prefers the RPC's flag with a pre-apply count fallback.

Verification

299 passed / 25 skipped (DB-gated), tsc clean, lint clean (repo files), production build green.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added CSV export for shipments with safer output handling.
    • Improved batch pack-request attachment behavior so approval reflects all linked parcels on the shipment.
  • Bug Fixes

    • Added audit logging across shipment, parcel, request, and pack-request actions.
    • Sanitized shipping search filtering to remove unsafe characters.
    • Prevented audit entries from being written on failed or invalid updates.

…RPC integration (SR-4)

The suite was structurally blind to the three things CLAUDE.md declares
sacred: you could delete every writeAudit call, downgrade every editor
gate to viewer, or regress any RPC body, and 200+ tests stayed green.

- NEW role-gates.test.ts: one table pins the min-role all 29 shipping
  withRole call sites request (the per-route mocks discard it); a count
  assertion catches unregistered new routes
- writeAudit assertions added to the 9 mutation suites that mocked it
  without ever asserting (parcels create/update, shipments create/update,
  attach, advance, pack-request update/attach, request update) + not-
  called-on-4xx checks on the parcels paths
- NEW export suite: BOM bytes, ¥ formatting, audit row, and formula-
  injection neutralization incl. the leading-whitespace bypass
- parcels suite: proves the route actually passes SANITIZED search terms
  into .or() (the pure-function test alone couldn't)
- NEW lib/shipping/__tests__/rpc.integration.test.ts (RUN_DB_TESTS-gated,
  dev-branch only): pins the SQL invariants nothing executable covered —
  advance skip-matrix (never touches picked_up), attach in-txn re-check,
  detach roundtrip, partial-pack-attach non-approval + re-run approval,
  one-open-request 23505, confirm-by-token idempotency, revert reason on
  the timeline, bulk-receive id sets, reassign, token-uniqueness trigger

Migration 20260703000006: writing the integration suite exposed that
20260703000001's approval predicate (newly-moved == total) could NEVER
approve on the sanctioned re-run flow (the re-run only moves stragglers).
Approval now checks "every linked parcel sits on this batch"; the route
prefers the RPC's authoritative flag with a pre-apply count fallback.

299 tests green (25 skipped: DB-gated suites); tsc clean; build green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
bia-admin-bia-admin Ready Ready Preview, Comment Jul 2, 2026 10:11pm

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR fixes the admin_attach_pack_request approval logic to base approval on whether all linked parcels are on the target shipment (rather than counting only newly attached parcels), updates the attach route to consume the RPC's approved flag, and adds extensive audit-log assertions, a role-gating test suite, an export-route test suite, and a live Supabase RPC integration test suite.

Changes

Pack request approval fix and shipping test coverage

Layer / File(s) Summary
Approval logic fix in migration and attach route
supabase/migrations/20260703000006_pack_request_approve_on_batch.sql, bia-admin/app/api/admin/shipping/pack-requests/[id]/attach/route.ts, .../attach/__tests__/route.test.ts
Migration changes approval to check all linked parcels are on the target shipment; route consumes RPC's approved flag with count-based fallback; test asserts audit call includes approved: true.
Role-gating test suite
bia-admin/app/api/admin/shipping/__tests__/role-gates.test.ts
New test mocks withRole, iterates a CASES table across all shipping routes, and asserts each handler enforces its expected minimum role.
Audit-log assertions across shipping route tests
bia-admin/app/api/admin/shipping/{pack-requests,parcels,requests,shipments}/**/__tests__/route.test.ts
Existing tests import writeAudit and add assertions verifying audit entries are (or are not) recorded for PATCH/POST/attach/advance operations; parcels test also adds search-term sanitization checks for GET filtering.
Shipment CSV export test suite
bia-admin/app/api/admin/shipping/shipments/[id]/export/__tests__/route.test.ts
New test suite validates UTF-8 BOM CSV streaming with audit logging, formula-injection neutralization, and 404 handling for unknown shipments.
Live RPC integration test suite
bia-admin/lib/shipping/__tests__/rpc.integration.test.ts
New Supabase-backed integration tests exercise parcel/shipment/pack-request RPCs, pickup lifecycle, bulk receive, reassignment, and uniqueness triggers, gated by RUN_DB_TESTS.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant AttachRoute as attach/route.ts
  participant RPC as admin_attach_pack_request
  participant DB as Parcels/Shipment tables

  Client->>AttachRoute: PATCH attach pack request
  AttachRoute->>RPC: call admin_attach_pack_request(shipment_id)
  RPC->>DB: lock request, aggregate linked parcel IDs
  RPC->>DB: count parcels on target shipment vs total
  DB-->>RPC: v_on_batch, v_total
  RPC->>RPC: approved = (v_on_batch == v_total)
  RPC-->>AttachRoute: { approved, total, attached }
  AttachRoute->>AttachRoute: prefer r.approved, else fallback count check
  AttachRoute-->>Client: response with approval status
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is clearly related to the PR and names the main shipping test coverage additions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/shipping-sr4-test-backbone

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
bia-admin/app/api/admin/shipping/pack-requests/[id]/attach/route.ts (1)

127-140: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Stale comment contradicts the new approval logic.

Lines 129-130 still state Compute approved from the counts (not the RPC's key), but the code right below (Lines 137-140) now does the opposite: it prefers r.approved when the RPC provides it, falling back to the count comparison only otherwise. This will mislead future readers about the actual precedence.

✏️ Proposed fix
     // attached < total means some parcels were ineligible (not received_cn) and
     // the RPC skipped them — the request then stays attachable for a re-run.
-    // Compute `approved` from the counts (not the RPC's key) so this route
-    // stays correct against the pre-20260703000001 RPC, which always approved.
     const attachedCount = r.attached ?? 0;
     const total = r.total ?? 0;
     const skipped = total - attachedCount;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@bia-admin/app/api/admin/shipping/pack-requests/`[id]/attach/route.ts around
lines 127 - 140, The comment above the approval calculation in the attach route
is stale and contradicts the current logic. Update the nearby explanatory
comment in the route handler so it matches the behavior in `approved`:
`r.approved` is authoritative when present, and the count comparison is only the
fallback. Keep the wording aligned with the `attachedCount`, `total`, and
`approved` symbols so future readers understand the actual precedence.
🧹 Nitpick comments (3)
bia-admin/app/api/admin/shipping/shipments/[id]/export/__tests__/route.test.ts (2)

97-103: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider asserting entity_type too.

The audit assertion checks action, entity_id, and payload but not entity_type: "shipment". Minor completeness gap for pinning the full audit contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@bia-admin/app/api/admin/shipping/shipments/`[id]/export/__tests__/route.test.ts
around lines 97 - 103, The audit test for the shipment export route only
verifies action, entity_id, and payload, so it does not fully pin the audit
contract. Update the assertion in the export route test to also check
entity_type: "shipment" in the writeAuditMock call, using the existing shipment
export test case as the place to tighten the expectation.

119-124: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Fragile cell-splitting via split('","').

Splitting rows on the literal '","' delimiter assumes no cell content ever contains that exact sequence. It works for current fixtures but is brittle if test data changes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@bia-admin/app/api/admin/shipping/shipments/`[id]/export/__tests__/route.test.ts
around lines 119 - 124, The test in route.test.ts is using a brittle CSV cell
parser by splitting each row with split('","'), which will break if any exported
field contains that exact sequence. Update the assertion logic in the shipment
export test to parse cells in a way that respects CSV quoting, or otherwise
inspect the exported rows without relying on a literal delimiter. Keep the
existing safety check in the test, but apply it through a more robust row/cell
iteration approach around the text processing block.
bia-admin/lib/shipping/__tests__/rpc.integration.test.ts (1)

116-135: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Inconsistent error assertions before accessing .data risk unhelpful failures.

Several RPC calls destructure only data and immediately dereference it (e.g. Line 118 const { data } = await admin.rpc(...) then Line 123 data.received_at; similarly Lines 262-272, 280-289, 328-333, 352-357) without first asserting error is null. Other tests in the same file (e.g. Lines 211-224, 381-388, 401-406) do check error explicitly. On an unexpected RPC error, the un-checked variants will throw a generic Cannot read properties of null instead of a clear assertion message, making live-DB failures harder to diagnose.

♻️ Example fix pattern
-    const { data } = await admin.rpc("admin_patch_parcel", {
+    const { data, error } = await admin.rpc("admin_patch_parcel", {
       p_id: p.id,
       p_actor_user_id: ACTOR,
       p_patch: { status: "received_cn" },
     });
+    expect(error).toBeNull();
     expect(data.received_at).toBeTruthy();

Also applies to: 262-291, 328-333, 352-357

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@bia-admin/lib/shipping/__tests__/rpc.integration.test.ts` around lines 116 -
135, Several rpc integration tests in admin_patch_parcel and related cases
destructure only data and use it before confirming the RPC error state, which
can hide the real failure; update these calls to assert error is null (or
otherwise check the RPC result) immediately after each admin.rpc invocation
before dereferencing data, matching the safer pattern already used elsewhere in
this test file, so failures in admin_patch_parcel and similar helpers surface a
clear assertion instead of a null property access.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@bia-admin/app/api/admin/shipping/pack-requests/`[id]/attach/route.ts:
- Around line 127-140: The comment above the approval calculation in the attach
route is stale and contradicts the current logic. Update the nearby explanatory
comment in the route handler so it matches the behavior in `approved`:
`r.approved` is authoritative when present, and the count comparison is only the
fallback. Keep the wording aligned with the `attachedCount`, `total`, and
`approved` symbols so future readers understand the actual precedence.

---

Nitpick comments:
In
`@bia-admin/app/api/admin/shipping/shipments/`[id]/export/__tests__/route.test.ts:
- Around line 97-103: The audit test for the shipment export route only verifies
action, entity_id, and payload, so it does not fully pin the audit contract.
Update the assertion in the export route test to also check entity_type:
"shipment" in the writeAuditMock call, using the existing shipment export test
case as the place to tighten the expectation.
- Around line 119-124: The test in route.test.ts is using a brittle CSV cell
parser by splitting each row with split('","'), which will break if any exported
field contains that exact sequence. Update the assertion logic in the shipment
export test to parse cells in a way that respects CSV quoting, or otherwise
inspect the exported rows without relying on a literal delimiter. Keep the
existing safety check in the test, but apply it through a more robust row/cell
iteration approach around the text processing block.

In `@bia-admin/lib/shipping/__tests__/rpc.integration.test.ts`:
- Around line 116-135: Several rpc integration tests in admin_patch_parcel and
related cases destructure only data and use it before confirming the RPC error
state, which can hide the real failure; update these calls to assert error is
null (or otherwise check the RPC result) immediately after each admin.rpc
invocation before dereferencing data, matching the safer pattern already used
elsewhere in this test file, so failures in admin_patch_parcel and similar
helpers surface a clear assertion instead of a null property access.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8bf40fe4-a5c1-4c04-b890-477cd6833aaa

📥 Commits

Reviewing files that changed from the base of the PR and between c6ebbb8 and 6aa2fa1.

📒 Files selected for processing (14)
  • bia-admin/app/api/admin/shipping/__tests__/role-gates.test.ts
  • bia-admin/app/api/admin/shipping/pack-requests/[id]/__tests__/route.test.ts
  • bia-admin/app/api/admin/shipping/pack-requests/[id]/attach/__tests__/route.test.ts
  • bia-admin/app/api/admin/shipping/pack-requests/[id]/attach/route.ts
  • bia-admin/app/api/admin/shipping/parcels/[id]/__tests__/route.test.ts
  • bia-admin/app/api/admin/shipping/parcels/__tests__/route.test.ts
  • bia-admin/app/api/admin/shipping/requests/[id]/__tests__/route.test.ts
  • bia-admin/app/api/admin/shipping/shipments/[id]/__tests__/route.test.ts
  • bia-admin/app/api/admin/shipping/shipments/[id]/advance-parcels/__tests__/route.test.ts
  • bia-admin/app/api/admin/shipping/shipments/[id]/attach/__tests__/route.test.ts
  • bia-admin/app/api/admin/shipping/shipments/[id]/export/__tests__/route.test.ts
  • bia-admin/app/api/admin/shipping/shipments/__tests__/route.test.ts
  • bia-admin/lib/shipping/__tests__/rpc.integration.test.ts
  • supabase/migrations/20260703000006_pack_request_approve_on_batch.sql

@LongXL6
LongXL6 merged commit fa86d22 into main Jul 2, 2026
5 checks passed
@LongXL6
LongXL6 deleted the test/shipping-sr4-test-backbone branch July 2, 2026 22:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant