5.1 KiB
Smoke test: per-item ⓘ popover on /sprint
Manual checklist. Run once after merge; ~5 minutes per env-var mode.
Requires: live PocketBase reachable from your dev server, n8n's
ai_item_insightsworkflow having run on at least a few recentquote_itemsrows, and a populatedorders/order_items/suppliers/stock_purchase_itemsset (so the deterministic joins return data).
Pre-flight
cd /path/to/wfdash-webapp
git checkout feature/order-sprint-item-history
npm install # only if node_modules changed since the branch was built
npm run test:run # expect: all tests pass (24 of those are item-history)
The full suite has 8 pre-existing failures on main (collection-pool,
orders-service, quotes-service) that are unrelated to this branch. Don't
fix them as part of this work.
1. Default mode — both (the A/B render)
npm run dev
Open http://localhost:3000/sprint and sign in.
Pick three rows on the sprint list and click the small ⓘ next to each item line. For each, verify:
| # | Item profile | Expected render |
|---|---|---|
| A | Has a SKU that's been bought/sold before (e.g. a drill bit you stock regularly) | Two cards side by side. Left ("PB-derived", indigo) shows cheapest supplier line in green + the usual 3 supplier rows + 1+ other-quote row + stock count. Right ("AI snapshot", amber) shows the n8n summary line. Both freshness badges ("fresh" / "snapshot") visible. |
| B | Has a SKU but no PB history yet (very new item) | Left card: "No history for this item yet" empty state (or a card with no rows). Right card: if ai_item_insights is populated, the AI summary shows; if not, AI card hidden. |
| C | Has a stale ai_item_insights from >7 days ago |
Right card shows with an older freshness badge ("12d ago" or similar) so you can see it's stale. Left card unaffected. |
Notes:
- The trigger is grey by default and turns indigo when the item has data. If the icon never goes indigo for item A, the join is empty and something is wrong with the SKU filter.
- The
Item id: <id>footer in the popover lets you grab the PB id for a deeper look in the PB admin.
2. deterministic — PB joins only
# stop the dev server first (Ctrl-C)
ITEM_HISTORY_COMPARE_MODE=deterministic npm run dev
Reload /sprint and click ⓘ on the same item A as above.
Expect:
- The popover opens.
- Only the indigo "PB-derived" card is visible.
- The amber "AI snapshot" card is not present (the popover should show the single card full-width).
- A
Networktab request to/api/v1/quote_items/<id>/item-historyshould return JSON withai: nullanddeterministic: {...}.
3. ai — AI blob only
ITEM_HISTORY_COMPARE_MODE=ai npm run dev
Reload /sprint and click ⓘ on the same item A.
Expect:
- The popover opens.
- Only the amber "AI snapshot" card is visible.
- The indigo "PB-derived" card is not present.
- Network response has
deterministic: nullandai: {...}.
This mode is mostly for debugging the n8n blob independently of the service-layer joins. If the AI card shows here but not in mode 1 (both), the deterministic service is broken.
4. none — kill switch
ITEM_HISTORY_COMPARE_MODE=none npm run dev
Reload /sprint.
Expect:
- The ⓘ trigger is not visible on any item.
- No
/api/v1/quote_items/.../item-historyrequests are made (the trigger only fires on first open; with the trigger hidden, the endpoint is never called). - The rest of the sprint page is unchanged — quotes, statuses, etc. still work.
5. Reset to default
# stop the dev server
npm run dev
Reload /sprint. Confirm both cards render again (same as step 1).
6. Build check
npm run build
Expect: a clean production build. The route.ts under
/api/v1/quote_items/[id]/item-history/ should appear in the route
manifest.
7. Type check
npx tsc --noEmit
Expect: the one pre-existing error in
src/app/(app)/collection-confirm/view-model.test.ts(278,63) and
nothing else. (The Pick<InvoiceDetails, "number" | "date"> type
doesn't include setBy — predates this branch.)
Pass criteria
- Mode
bothshows both cards with correct content on item A. - Mode
deterministicshows only the PB card. - Mode
aishows only the AI card. - Mode
nonehides the trigger entirely. - No console errors or unhandled rejections in the browser DevTools.
npm run test:runreportsTest Files 2 passed (2)for the item-history slice (24 tests total).npm run buildexits 0.
If any of these fail, capture the response body from
/api/v1/quote_items/<id>/item-history and the Network tab request
log — those are the two things that distinguish "service returned
empty" from "service threw" from "endpoint short-circuited on mode".
Bake-in
After the smoke test passes, leave the deploy in both mode and run
the 1-week A/B bake per the original plan. Track operator clicks: do
operators click the deterministic card and phone the supplier, or do
they still read the AI summary? The mode that loses gets cut.