fix(presets): complete config mapping contracts (#82) #98

Merged
gronod merged 1 commits from feat/82-preset-mapping-contracts into milestone/m8-consolidation 2026-09-11 10:58:56 +01:00
Owner

Refs #82

Mapping contract fixes

  • TargenConfig(preset:): explicit ofps_high_quality: false is now preserved in Core mapping (previously collapsed to nil), remaining distinguishable from a missing key; -G is still only emitted for true. UI snapshots continue to normalise disabled controls to nil.
  • FWA conversion is centralised in PresetMapping.swift: ColprofFwaSelection moved there with init(presetValue:) (nil/"none".none, "".empty, case-insensitive D50/D65, anything else → .custom) and presetValue(customPath:) for the reverse direction. The duplicate switches in ProfileWorkflowViewModel (fwaValue, applyPreset) are gone.
  • ProfileWorkflowViewModel.applyPreset now resets all Stage 4 state deterministically: a nil/non-custom preset FWA clears any previously selected custom .sp path, and preset apply_calibration/calibration_file are applied to the calibration controls.
  • TargetWorkflowViewModel.applyPreset applies profile + calibration state before constructing the Stage 2 PrinttargConfig, so the layout receives the preset's effective calibration path rather than stale live state.
  • Stage 1/2 form-field assignment stays encapsulated in applyTargenForm/applyPrinttargForm; no raw preset field lists leak back to the view model.

TestAppEnvironment

Tests/ICCeryCoreTests/TestAppEnvironment.swift — shared factory that builds an AppEnvironment backed by a unique NSTemporaryDirectory() root (settings.json, wizard_state.json, verification_history.json) plus a fresh ProcessManager, ArgyllRunner, and CupsService. It never touches the real Application Support directory and never mutates the global process environment.

Tests added

PresetTests.swift (PresetMappingTests):

  • Full ProfilingPresetTargenConfig/PrinttargConfig/ColprofConfig round-trip with every field asserted (back == preset).
  • Round-trip for all full-spread algorithms: ofps, t, r, R, q, Q, i, I.
  • Optional advanced targen fields stay nil (not numeric sentinels); explicit ofpsHighQuality=false vs nil distinction.
  • no_randomize/random_seed layout matrix (raster / deterministic / custom seed).
  • Custom page fallback matrix: valid WxH ≥ 50 mm, foo, undersized 30x40, truncated 210x → A4 fallback.
  • FWA conversion matrix in both directions (nil, none, ``, D50, D65, custom .sp path).

PresetViewModelMappingTests.swift (app-target, @MainActor, isolated via TestAppEnvironment):

  • Apply custom-FWA preset then nil-FWA preset → stale selection/path cleared.
  • Preset calibration_file/apply_calibration reaches Stage 2 instead of stale live state; disabled calibration clears Stage 2.
  • Stage 1/2 form fields apply end-to-end.

Test gate

xcodebuild test -scheme ICCery -only-testing:ICCeryCoreTests/{ProfilingPresetTests,PresetMappingTests,PresetStoreTests,PresetMigrationTests,PresetViewModelMappingTests} -only-testing:ICCeryUITests/Milestone2UITests/testPresetApplyAndBuiltInProtection24 swift-testing tests + 1 UI test passed, 0 failures (DerivedData-feat-82-preset-mapping-contracts, universal arm64+x86_64).

v1 snake_case schema and built-in preset IDs unchanged.

Refs #82 ## Mapping contract fixes - `TargenConfig(preset:)`: explicit `ofps_high_quality: false` is now preserved in Core mapping (previously collapsed to `nil`), remaining distinguishable from a missing key; `-G` is still only emitted for `true`. UI snapshots continue to normalise disabled controls to `nil`. - FWA conversion is centralised in `PresetMapping.swift`: `ColprofFwaSelection` moved there with `init(presetValue:)` (`nil`/`"none"` → `.none`, `""` → `.empty`, case-insensitive `D50`/`D65`, anything else → `.custom`) and `presetValue(customPath:)` for the reverse direction. The duplicate switches in `ProfileWorkflowViewModel` (`fwaValue`, `applyPreset`) are gone. - `ProfileWorkflowViewModel.applyPreset` now resets all Stage 4 state deterministically: a `nil`/non-custom preset FWA clears any previously selected custom `.sp` path, and preset `apply_calibration`/`calibration_file` are applied to the calibration controls. - `TargetWorkflowViewModel.applyPreset` applies profile + calibration state **before** constructing the Stage 2 `PrinttargConfig`, so the layout receives the preset's effective calibration path rather than stale live state. - Stage 1/2 form-field assignment stays encapsulated in `applyTargenForm`/`applyPrinttargForm`; no raw preset field lists leak back to the view model. ## TestAppEnvironment `Tests/ICCeryCoreTests/TestAppEnvironment.swift` — shared factory that builds an `AppEnvironment` backed by a unique `NSTemporaryDirectory()` root (settings.json, wizard_state.json, verification_history.json) plus a fresh `ProcessManager`, `ArgyllRunner`, and `CupsService`. It never touches the real Application Support directory and never mutates the global process environment. ## Tests added `PresetTests.swift` (`PresetMappingTests`): - Full `ProfilingPreset` ↔ `TargenConfig`/`PrinttargConfig`/`ColprofConfig` round-trip with every field asserted (`back == preset`). - Round-trip for all full-spread algorithms: `ofps`, `t`, `r`, `R`, `q`, `Q`, `i`, `I`. - Optional advanced targen fields stay `nil` (not numeric sentinels); explicit `ofpsHighQuality=false` vs `nil` distinction. - `no_randomize`/`random_seed` layout matrix (raster / deterministic / custom seed). - Custom page fallback matrix: valid `WxH` ≥ 50 mm, `foo`, undersized `30x40`, truncated `210x` → A4 fallback. - FWA conversion matrix in both directions (`nil`, `none`, ``, `D50`, `D65`, custom `.sp` path). `PresetViewModelMappingTests.swift` (app-target, `@MainActor`, isolated via `TestAppEnvironment`): - Apply custom-FWA preset then nil-FWA preset → stale selection/path cleared. - Preset `calibration_file`/`apply_calibration` reaches Stage 2 instead of stale live state; disabled calibration clears Stage 2. - Stage 1/2 form fields apply end-to-end. ## Test gate `xcodebuild test -scheme ICCery -only-testing:ICCeryCoreTests/{ProfilingPresetTests,PresetMappingTests,PresetStoreTests,PresetMigrationTests,PresetViewModelMappingTests} -only-testing:ICCeryUITests/Milestone2UITests/testPresetApplyAndBuiltInProtection` — **24 swift-testing tests + 1 UI test passed, 0 failures** (DerivedData-feat-82-preset-mapping-contracts, universal arm64+x86_64). v1 snake_case schema and built-in preset IDs unchanged.
gronod added the Kind/Enhancement
Priority
Medium
3
Project/ICCery-v2Feature/Backend
labels 2026-09-11 10:53:58 +01:00
gronod added 1 commit 2026-09-11 10:53:58 +01:00
Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
gronod added this to the M7 — Deduplicate & consolidate (develop) milestone 2026-09-11 10:54:04 +01:00
gronod self-assigned this 2026-09-11 10:54:11 +01:00
gronod merged commit 0ffcf5ea91 into milestone/m8-consolidation 2026-09-11 10:58:56 +01:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: gronod/iccery-v2-mac#98