Phase 5 of the M12 megaplan: AirPrint queue detection during enumeration plus a persistent Stage 2 warning badge (#202, docs/14 §10.2).
CupsParsers — new lpstatDeviceURIs(output:), lpoptionsMakeAndModel(output:), and detectAirPrint(deviceURI:makeAndModel:ppd:) implementing the six rules: apple-airprint:// URI; *APAirPrint: True; make-and-model with "Apple"+"AirPrint"; ipps:// + PPD "airprint" mention; local ipp:// resolved via the _universal._sub._ipp._tcp mDNS subtype; *cupsFilter2 destination image/urf.
CupsService.listPrinters — one extra lpstat -v spawn (cupsLpstat("v"), tolerateFailure: true, no fallback respawn); lpoptions -p now yields display name and make-and-model from a single spawn per queue; Printer.isAirPrint populated from URI + make-and-model + loaded PPD.
Printer.isAirPrint: Bool = false — tolerant decoder so pre-#202 payloads still decode; PrintOptions.cupsOptions doc updated to "Stage 2 mirror, not an lp payload".
Stage2View — live airPrintWarningBadge: "AirPrint queue — unmanaged colour cannot be guaranteed." shown only while the selected queue is AirPrint.
Fixtures — lpstat -v marks Mock_Canon_Pro via the _universal mDNS subtype; lpoptions emits printer-make-and-model='EPSON XP-55 Series'.
Tests
CupsParserTests: fixture-driven case per rule (6 true), USB Epson negative, plus testListPrintersToleratesLpstatVFailure asserting enumeration proceeds with isAirPrint == false and exactly one-v spawn.
Milestone12AirPrintUITests: badge appears for the AirPrint fixture queue and disappears for the USB queue, both directions.
Verification
xcodebuild test -scheme ICCery -destination 'platform=macOS' ARCHS=x86_64 — 515 unit + 69 UI tests; sole failure was the new test's label-vs-value assertion, fixed and re-run green (70 UI tests total).
## Summary
Phase 5 of the M12 megaplan: AirPrint queue detection during enumeration plus a persistent Stage 2 warning badge (#202, docs/14 §10.2).
- `CupsParsers` — new `lpstatDeviceURIs(output:)`, `lpoptionsMakeAndModel(output:)`, and `detectAirPrint(deviceURI:makeAndModel:ppd:)` implementing the six rules: `apple-airprint://` URI; `*APAirPrint: True`; make-and-model with "Apple"+"AirPrint"; `ipps://` + PPD "airprint" mention; local `ipp://` resolved via the `_universal._sub._ipp._tcp` mDNS subtype; `*cupsFilter2` destination `image/urf`.
- `CupsService.listPrinters` — one extra `lpstat -v` spawn (`cupsLpstat("v")`, `tolerateFailure: true`, **no fallback respawn**); `lpoptions -p` now yields display name and make-and-model from a single spawn per queue; `Printer.isAirPrint` populated from URI + make-and-model + loaded PPD.
- `Printer.isAirPrint: Bool = false` — tolerant decoder so pre-#202 payloads still decode; `PrintOptions.cupsOptions` doc updated to "Stage 2 mirror, not an `lp` payload".
- `Stage2View` — live `airPrintWarningBadge`: "AirPrint queue — unmanaged colour cannot be guaranteed." shown only while the selected queue is AirPrint.
- Fixtures — `lpstat -v` marks `Mock_Canon_Pro` via the `_universal` mDNS subtype; `lpoptions` emits `printer-make-and-model='EPSON XP-55 Series'`.
## Tests
- `CupsParserTests`: fixture-driven case per rule (6 true), USB Epson negative, plus `testListPrintersToleratesLpstatVFailure` asserting enumeration proceeds with `isAirPrint == false` and exactly **one** `-v` spawn.
- `Milestone12AirPrintUITests`: badge appears for the AirPrint fixture queue and disappears for the USB queue, both directions.
## Verification
`xcodebuild test -scheme ICCery -destination 'platform=macOS' ARCHS=x86_64` — 515 unit + 69 UI tests; sole failure was the new test's label-vs-value assertion, fixed and re-run green (70 UI tests total).
Part of #202.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Phase 5 of the M12 megaplan: AirPrint queue detection during enumeration plus a persistent Stage 2 warning badge (#202, docs/14 §10.2).
CupsParsers— newlpstatDeviceURIs(output:),lpoptionsMakeAndModel(output:), anddetectAirPrint(deviceURI:makeAndModel:ppd:)implementing the six rules:apple-airprint://URI;*APAirPrint: True; make-and-model with "Apple"+"AirPrint";ipps://+ PPD "airprint" mention; localipp://resolved via the_universal._sub._ipp._tcpmDNS subtype;*cupsFilter2destinationimage/urf.CupsService.listPrinters— one extralpstat -vspawn (cupsLpstat("v"),tolerateFailure: true, no fallback respawn);lpoptions -pnow yields display name and make-and-model from a single spawn per queue;Printer.isAirPrintpopulated from URI + make-and-model + loaded PPD.Printer.isAirPrint: Bool = false— tolerant decoder so pre-#202 payloads still decode;PrintOptions.cupsOptionsdoc updated to "Stage 2 mirror, not anlppayload".Stage2View— liveairPrintWarningBadge: "AirPrint queue — unmanaged colour cannot be guaranteed." shown only while the selected queue is AirPrint.lpstat -vmarksMock_Canon_Provia the_universalmDNS subtype;lpoptionsemitsprinter-make-and-model='EPSON XP-55 Series'.Tests
CupsParserTests: fixture-driven case per rule (6 true), USB Epson negative, plustestListPrintersToleratesLpstatVFailureasserting enumeration proceeds withisAirPrint == falseand exactly one-vspawn.Milestone12AirPrintUITests: badge appears for the AirPrint fixture queue and disappears for the USB queue, both directions.Verification
xcodebuild test -scheme ICCery -destination 'platform=macOS' ARCHS=x86_64— 515 unit + 69 UI tests; sole failure was the new test's label-vs-value assertion, fixed and re-run green (70 UI tests total).Part of #202.