Canon and HP driver profiles for quick actions

Canon: CNColorMode color/mono, CNDuplex, PageSize=Letter. HP: HPColorAsGray or
HPColorMode; duplex and Letter from the generic profile. Profiles can mark an action
unavailable with a reason (Canon department IDs, HP accounting codes). Use Letter
Paper only says Fit to Nearest Size when the profile sets a fit option. Offline tests
sweep every Canon and HP PPD found in CUPSKIT_PPD_DIRS or /Library/Printers/PPDs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kfattic
2026-09-16 21:04:02 -05:00
parent 7a98cb3bd3
commit 795ab7a981
9 changed files with 219 additions and 17 deletions

View File

@@ -18,12 +18,13 @@ private func profileID(_ id: String, _ context: DriverContext) -> String? {
@Suite struct DriverProfileFile {
@Test func builtInProfilesAreWellFormed() {
let profiles = DriverProfiles.builtIn
#expect(profiles.map(\.id) == ["ricoh-m-c251fw", "ricoh", "generic"])
#expect(profiles.map(\.id) == ["ricoh-m-c251fw", "ricoh", "canon", "hp", "generic"])
#expect(profiles.last?.isGeneric == true)
#expect(profiles.dropLast().allSatisfy { !$0.isGeneric })
let known = Set(QuickAction.all.map(\.id)).union(["usercode-clear"])
for profile in profiles {
#expect(Set(profile.actions.keys).isSubset(of: known), "\(profile.id): \(profile.actions.keys.sorted())")
#expect(Set(profile.unavailable.keys).isSubset(of: known), "\(profile.id): \(profile.unavailable.keys.sorted())")
for alternatives in profile.actions.values {
#expect(alternatives.allSatisfy { !$0.isEmpty && $0.allSatisfy { QuickAction.parse($0) != nil } })
}
@@ -45,6 +46,7 @@ private func profileID(_ id: String, _ context: DriverContext) -> String? {
let letter = try QuickAction.named("letter")!.resolve(c).get().changes
#expect(letter == [OptionChange(key: "PageSize", value: "Letter", isSecret: false),
OptionChange(key: "RIPaperPolicy", value: "NearestSizeAdjust", isSecret: false)])
#expect(QuickAction.named("letter")!.title(in: c) == "Use Letter Paper, Fit to Nearest Size")
let code = try QuickAction.named("usercode")!.resolve(c, value: "4321").get().changes
#expect(code.map(\.value) == ["True", "Custom.4321"])
let clear = try QuickAction.named("usercode")!.resolve(c, clearing: true).get().changes
@@ -76,6 +78,7 @@ private func profileID(_ id: String, _ context: DriverContext) -> String? {
// No RIPaperPolicy on this driver: the Ricoh letter mapping doesn't fit, generic Letter does.
#expect(profileID("letter", c) == "generic")
#expect(try QuickAction.named("letter")!.resolve(c).get().changes == [OptionChange(key: "PageSize", value: "Letter", isSecret: false)])
#expect(QuickAction.named("letter")!.title(in: c) == "Use Letter Paper")
}
@Test(.enabled(if: hasVendorPPD("RICOH IM C4500")))