Happy path (desired)
Staff pairs printer.
Settings → Printer. App scans Bluetooth devices for supported printers (Brother QL-820NWB, Zebra ZQ620, etc.). Tap to pair, OS-level pairing flow, app remembers across launches.
Organizer designs badge template.
Admin → Event Settings → Badge Template. Drag-drop placement of: guest name, company, access type pill (color from registry), optional QR (for re-scan), event branding. Preview at actual size. Save.
Auto-print on check-in confirm.
When check-in confirms (EF-061), the device's paired printer automatically prints the badge. Confirmation screen shows "✓ Checked in. Printing badge..." then "✓ Badge printed" once the printer confirms.
Manual reprint.
From a previously-checked-in guest's row, tap "Reprint badge." Same flow without the check-in step. Audit log row recorded.
Failure modes (desired contract)
Parity gap — feature absent
Trigger: matrix=Absent.
Visible "EF-067 wireless badge printing not yet implemented" panel on Settings → Printer. Without the feature, no Print tab is rendered (per native-app-shell trunk). Until shipped, the gap-panel asserts the absence.
Printer not paired
Trigger: staff attempts to print but no printer is paired.
Confirmation screen shows "Badge ready — pair printer in Settings to print." Check-in still succeeds (printing is best-effort). Harness: check-in without paired printer, message visible, audit log shows badge_pending.
Printer connection lost mid-print
Trigger: BT signal drops between confirm and printer-confirm.
Print job queued locally, retries on next reconnect. Confirmation says "Badge queued — will print on reconnect." Check-in not blocked. Harness: stub BT loss, queue persists, retry on reconnect.
Out of paper / ribbon
Trigger: printer reports paper-out / ribbon-empty.
UI shows "Printer is out of paper. Replace and tap Retry." Specific error from printer surface. Audit log row: badge_print_failed with reason. Harness: stub paper-out, banner visible, reload + retry succeeds.
Two-staff race on same guest's badge
Trigger: 2 staff devices both check-in same guest concurrently; both auto-print to their respective paired printers.
Idempotency: check-in is single (per EF-061). Printing is local to each device — both badges print on respective printers. The guest gets 2 badges. Acceptable behavior for the safety of physical-pickup at the door. Harness: 2-device test, both badges print, server has 1 check-in row.
Reprint requires permission
Trigger: read-only role tries to reprint.
Reprint requires checkins:reprint ability. Hidden for read-only roles. Harness: stub read-only, button hidden, server POST 403.
Reprint creates audit row
Trigger: staff reprints a guest's badge.
Audit log row: badge_reprinted with operator + guest + timestamp. Tracks how many times a guest has reprinted (potential lost-badge pattern). Harness: reprint, audit row exists.
Badge template change preserves prior prints
Trigger: organizer changes badge template mid-event.
Already-printed badges stay valid. New check-ins use the new template. Reprints use the CURRENT template (so a reprint after a template change reflects the new design). Harness: stub template-change, prior prints unaffected, reprint uses new template.
Badge content for missing fields
Trigger: badge template includes "Company" but a walk-in guest didn't provide one.
Field renders blank (not "{company}" literal, not "(undefined)"). Layout reflows gracefully. Harness: walk-in without company, badge renders without literal token, layout intact.
Cross-tenant printer pairing
Trigger: same physical printer used at two tenants' events.
Pairing is OS-level (the printer itself isn't tenant-aware). App-level pairing is tenant-scoped — if signed into tenant A, only A's print jobs go to that printer. Switching tenants re-prompts pair confirmation. Harness: switch tenants, re-prompt visible.
Stable test attributes
badge-printing-gap-panel | Settings → Printer | Visible until feature ships |
printer-pair-button | Settings → Printer | Triggers BT scan |
printer-status-pill | Settings + tab | paired / disconnected / unsupported |
badge-template-editor | Admin → Badge Template | Drag-drop preview |
print-progress | Confirmation | "Printing badge..." → "Badge printed" |
print-pending-banner | If queued | "Will print on reconnect" |
print-error-banner | If printer error | Specific reason + Retry |
reprint-button | Per guest row | Visible for permitted roles |
Agent test plan
Probe list
- gap-panel-visible: matrix=Absent, panel visible
- (when shipped + manual) printer-pairs-survives-relaunch: pair, force-quit, relaunch, still paired
- printer-not-paired-graceful: check-in succeeds, badge-pending message visible
- (when shipped + manual) printer-bt-loss-queues: stub BT loss, queue persists
- (when shipped + manual) printer-out-of-paper: stub error, specific banner + Retry
- two-staff-race-both-print: 2 devices, both badges print, server 1 check-in
- reprint-permission-gated: read-only, button hidden + 403
- reprint-audit-row: reprint, audit row exists
- template-change-preserves-prior: new template doesn't affect already-printed
- (when shipped) missing-field-renders-blank: walk-in without company, no literal token
- cross-tenant-pairing-reprompts: switch tenants, re-prompt
- (when shipped + manual) physical-printer-evidence: signed-build + printer + actual print physical photo