macOS CI / build-and-test (push) Skipped
- Detect vendor tray keys in CupsParsers with InputSlot/MediaSource/EPIJ_FdSo/EPIJ_PSrc/CNIJMediaSupply roster; EPIJ_FdSo wins over EPIJ_PSrc. - PrinterTray now carries raw token + display name; PrinterCapabilities exposes trayKey, trayDefault and tray-specific quality maps. - CupsService enumerates trays from the detected key, enriches labels from PPD, seeds selection from CUPS default, and precomputes per-tray media→quality constraints. - MediaQualityConstraints resolves quality availability from both selected media and selected tray, falling back to the media-only map. - TicketWriteResolver emits the selected tray key=token in the locked write order between PageSize and media key. - PrintPanelService applies the Stage 2 tray token to PMPrintSettings on open and captures the tray back from the full roster plus AP_D_InputSlot. - PrintSessionViewModel keeps selectedTrayToken, applies capture-back, preserves unknown captured tokens as synthetic trays, and passes tray into spool overrides. - Stage2View replaces portrait/landscape buttons with an orientation dropdown (printerOrientationSelect) while preserving portrait/landscape semantics and orientation-requested=3|4. - Add/update core, UI and fixture tests for tray detection, enumeration, PPD labels, defaults, unknown-token synthesis, panel capture, ticket write order and tray-aware quality clamping. - Update docs/10-print-system.md, docs/11-print-macos.md, docs/21-ui-reference.md and docs/24-issues-invariants.md. Verified on the macOS 12.7.6 x86_64 CI runner: xcodebuild build-for-testing and ICCeryCoreTests pass (557 tests, 0 failures).
165 lines
6.2 KiB
Swift
165 lines
6.2 KiB
Swift
import Foundation
|
|
import XCTest
|
|
@testable import ICCeryCore
|
|
@testable import ICCery
|
|
|
|
/// Issue 13 — panel outcome mapping (cancel → nil, ok → result).
|
|
/// The real `NSPrintPanel` is never run in tests; these exercise the
|
|
/// `UITestHooks` seam the UI tests rely on.
|
|
final class PrintPanelStubTests: XCTestCase {
|
|
|
|
private func withEnv(
|
|
_ vars: [String: String?],
|
|
_ body: () throws -> Void
|
|
) rethrows {
|
|
var saved: [String: String?] = [:]
|
|
for key in vars.keys {
|
|
saved[key] = ProcessInfo.processInfo.environment[key]
|
|
}
|
|
for (key, value) in vars {
|
|
if let value { setenv(key, value, 1) } else { unsetenv(key) }
|
|
}
|
|
defer {
|
|
for (key, value) in saved {
|
|
if let value { setenv(key, value, 1) } else { unsetenv(key) }
|
|
}
|
|
}
|
|
try body()
|
|
}
|
|
|
|
func testCancelIsNil() throws {
|
|
try withEnv([
|
|
"ICCERY_UI_TESTING": "1",
|
|
"ICCERY_TEST_PRINT_PANEL": "cancel",
|
|
]) {
|
|
XCTAssertTrue(UITestHooks.printPanelStubbed)
|
|
XCTAssertNil(UITestHooks.printPanelResult(forQueue: "q"))
|
|
}
|
|
}
|
|
|
|
func testOkResult() throws {
|
|
try withEnv([
|
|
"ICCERY_UI_TESTING": "1",
|
|
"ICCERY_TEST_PRINT_PANEL": "ok",
|
|
"ICCERY_TEST_PANEL_OPTIONS": "MediaType=Photo InputSlot=Rear",
|
|
"ICCERY_TEST_PANEL_PRINTER": "Other_Queue",
|
|
]) {
|
|
let trays = [
|
|
PrinterTray(id: 1, token: "Auto", name: "Auto"),
|
|
PrinterTray(id: 2, token: "Rear", name: "Rear"),
|
|
]
|
|
let result = UITestHooks.printPanelResult(
|
|
forQueue: "q", trays: trays, preferredTrayKey: "InputSlot")
|
|
XCTAssertEqual(result?.selectedPrinter, "Other_Queue")
|
|
XCTAssertEqual(result?.options.cupsOptions, "MediaType=Photo InputSlot=Rear")
|
|
XCTAssertEqual(result?.options.mediaType, "Photo")
|
|
XCTAssertEqual(result?.options.paperSource, 2)
|
|
XCTAssertEqual(result?.options.ppdUncorrectedPassthrough, true)
|
|
}
|
|
}
|
|
|
|
/// #183 — the stub parses paper size / quality / orientation out of
|
|
/// `ICCERY_TEST_PANEL_OPTIONS` so UI tests can verify apply-back.
|
|
func testOkResultExtractsNewFields() throws {
|
|
try withEnv([
|
|
"ICCERY_UI_TESTING": "1",
|
|
"ICCERY_TEST_PRINT_PANEL": "ok",
|
|
"ICCERY_TEST_PANEL_OPTIONS":
|
|
"PageSize=Letter EPIJ_Qual=305 orientation-requested=4",
|
|
"ICCERY_TEST_PANEL_PRINTER": nil,
|
|
]) {
|
|
let result = UITestHooks.printPanelResult(forQueue: "q")
|
|
XCTAssertEqual(result?.options.paperSize, "Letter")
|
|
XCTAssertEqual(result?.options.quality, "305")
|
|
XCTAssertEqual(result?.options.orientation, "landscape")
|
|
}
|
|
}
|
|
|
|
/// #186 — a vendor media key in the captured string reaches
|
|
/// `options.mediaType` through the detection roster
|
|
/// (`CNIJMediaType`/`StpMediaType`, not only `MediaType`).
|
|
func testOkResultExtractsVendorMediaKey() throws {
|
|
try withEnv([
|
|
"ICCERY_UI_TESTING": "1",
|
|
"ICCERY_TEST_PRINT_PANEL": "ok",
|
|
"ICCERY_TEST_PANEL_OPTIONS":
|
|
"PageSize=A4 orientation-requested=4 CNIJMediaType=Photo",
|
|
"ICCERY_TEST_PANEL_PRINTER": nil,
|
|
]) {
|
|
let result = UITestHooks.printPanelResult(forQueue: "q")
|
|
XCTAssertEqual(result?.options.paperSize, "A4")
|
|
XCTAssertEqual(result?.options.orientation, "landscape")
|
|
XCTAssertEqual(result?.options.mediaType, "Photo")
|
|
}
|
|
}
|
|
|
|
func testOkDefaultsPrinter() throws {
|
|
try withEnv([
|
|
"ICCERY_UI_TESTING": "1",
|
|
"ICCERY_TEST_PRINT_PANEL": "ok",
|
|
"ICCERY_TEST_PANEL_OPTIONS": nil,
|
|
"ICCERY_TEST_PANEL_PRINTER": nil,
|
|
]) {
|
|
let result = UITestHooks.printPanelResult(forQueue: "My_Queue")
|
|
XCTAssertEqual(result?.selectedPrinter, "My_Queue")
|
|
XCTAssertNil(result?.options.cupsOptions)
|
|
}
|
|
}
|
|
|
|
/// #218 — vendor tray keys and the `AP_D_InputSlot` capture alias
|
|
/// map back through `paperSource` when the token matches the roster.
|
|
func testOkResultExtractsTrayToken() throws {
|
|
let trays = [
|
|
PrinterTray(id: 1, token: "Auto", name: "Auto"),
|
|
PrinterTray(id: 2, token: "Rear", name: "Rear Tray"),
|
|
PrinterTray(id: 3, token: "Manual", name: "Manual Feed"),
|
|
]
|
|
try withEnv([
|
|
"ICCERY_UI_TESTING": "1",
|
|
"ICCERY_TEST_PRINT_PANEL": "ok",
|
|
"ICCERY_TEST_PANEL_OPTIONS": "PageSize=A4 EPIJ_FdSo=Rear",
|
|
"ICCERY_TEST_PANEL_PRINTER": nil,
|
|
]) {
|
|
let result = UITestHooks.printPanelResult(
|
|
forQueue: "q", trays: trays,
|
|
preferredTrayKey: "EPIJ_FdSo")
|
|
XCTAssertEqual(result?.options.paperSource, 2)
|
|
XCTAssertEqual(result?.options.cupsOptions,
|
|
"PageSize=A4 EPIJ_FdSo=Rear")
|
|
}
|
|
}
|
|
|
|
func testOkResultExtractsAPDInputSlotAlias() throws {
|
|
let trays = [
|
|
PrinterTray(id: 1, token: "Auto", name: "Auto"),
|
|
PrinterTray(id: 2, token: "Manual", name: "Manual Feed"),
|
|
]
|
|
try withEnv([
|
|
"ICCERY_UI_TESTING": "1",
|
|
"ICCERY_TEST_PRINT_PANEL": "ok",
|
|
"ICCERY_TEST_PANEL_OPTIONS": "AP_D_InputSlot=Manual",
|
|
"ICCERY_TEST_PANEL_PRINTER": nil,
|
|
]) {
|
|
let result = UITestHooks.printPanelResult(
|
|
forQueue: "q", trays: trays)
|
|
XCTAssertEqual(result?.options.paperSource, 2)
|
|
}
|
|
}
|
|
|
|
func testOkResultUnknownTrayNoPaperSource() throws {
|
|
let trays = [
|
|
PrinterTray(id: 1, token: "Auto", name: "Auto"),
|
|
]
|
|
try withEnv([
|
|
"ICCERY_UI_TESTING": "1",
|
|
"ICCERY_TEST_PRINT_PANEL": "ok",
|
|
"ICCERY_TEST_PANEL_OPTIONS": "InputSlot=Unknown",
|
|
"ICCERY_TEST_PANEL_PRINTER": nil,
|
|
]) {
|
|
let result = UITestHooks.printPanelResult(
|
|
forQueue: "q", trays: trays)
|
|
XCTAssertNil(result?.options.paperSource)
|
|
}
|
|
}
|
|
}
|