refactor: extract the Steam client orchestrator into WhiskyKit for testability - #241
Conversation
…stability Move SteamClientOrchestrator into the kit behind a SteamClientDriver protocol: the orchestrator keeps the sequencing (single-flight client startup, per-game phases, the shared process snapshot) and the driver owns the side effects, so swift test can drive the whole launch flow without Wine. WineSteamClientDriver is the production driver; the app subclasses it only to run download monitoring for the session. Part of #171; this is the last step.
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
The only logic in WineSteamClientDriver is turning a ps listing into .exe image names; pull it out as a nonisolated static so it is testable without spawning ps, and test the path, case and filtering rules.
|
Review notes, since this one cannot be self-approved. Pure refactor, no changelog entry per convention. The seam holds the split it promises: the orchestrator keeps every piece of sequencing that mattered (single-flight client startup, per-game phases, the shared snapshot with its lifetime and coalesced reads) and the driver is delegations plus one parser, which is now tested on its own. LibraryModel is a one-line change. The three error strings moved with the type and carry extractionState manual. Coverage: the orchestrator file measures 98.9% of lines locally under swift test; the remaining uncovered lines in the driver are the four calls that need a running Wine plus two empty hooks, which is the point of the seam. Full kit suite 1294 XCTest plus 251 Swift Testing green, app target builds, both lints clean, CI green on the final head including the UI tests. Merging; closes #171. |
Step 3 of #171, the last one: the Steam client orchestrator core moves into WhiskyKit, parameterized over a driver protocol so tests can drive it without Wine. No behavior change intended.
what moved
SteamClientOrchestratornow lives inWhiskyKit/Steam/. It keeps the three pieces that were the point of extracting it:Side effects go through
SteamClientDriver: host process names (ps), the bottle's process list (tasklist.exe), starting the client, applying launcher fixes,-applaunch, killing a process, and two lifecycle hooks (clientDidBecomeReady,shutdown).WineSteamClientDriveris the kit's production implementation and isopen; the app'sAppSteamClientDriver(30 lines) overrides only the two hooks to runSteamDownloadMonitorfor the session, which stays app-target since nothing else needs it.LibraryModelconstructs the kit type with that driver and is otherwise untouched.The launcher-fix gate (skip in manual mode, skip when the bottle is already configured for Steam) is a public static on the orchestrator so the rule is testable on its own. Waits and intervals are a
Timingvalue with production defaults, injectable for tests.The three error strings (
steam.client.timeout,steam.client.missing,steam.launch.timeout) are now referenced from the kit, so their catalog entries carryextractionState: manual.tests
17 new Swift Testing cases against a scripted fake driver and a fake Steam layout on disk:
verified
Closes #171.