New gclo.Cli.Tests project (65 tests) covers the CLI to 100% line
coverage by driving injectable command cores over fake collaborators:
- Commands (sync/orgs/accounts) split into a thin composition-root
wrapper (excluded — it wires the real GitHub listers, LibGit2 client,
and Credential Manager) and an internal core taking IRepositoryLister/
IOrganizationLister/IGitClient/account-open-func/IActivityLog. Tests
capture the process Console (sequentially — the assembly disables test
parallelization since Console is global) and assert output, exit codes,
and error translation.
- Covered: argument parsing and every usage error, token resolution
(env/file/redirected-stdin/multi-source), account seeding + org
subfolder, unknown/missing-token accounts, sync success/partial-
failure/canceled, JSON and quiet output, path sanitization (recover/
fail/cancel), invalid-path listing + truncation, and the record-result
warning path.
- Excluded (auditable): Program (composition root), TokenOptions'
interactive no-echo read, and each command's real-collaborator wrapper.
CI now runs both test projects under coverage.runsettings and fails
unless gclo.Engine, gclo.ViewModels, and gclo (the CLI) each measure
100% line coverage. Verified locally: 100.00% / 100.00% / 100.00%.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Introduces coverage.runsettings (include the three library assemblies;
exclude source-generated JSON contexts and [ExcludeFromCodeCoverage]
adapters). Both core libraries now measure at 100.00% line coverage.
Testability seams (all offline, no network/native dependence):
- IGitHubGateway: the listers' Octokit calls move behind an internal
gateway interface; GitHubListerTests pin pagination, the org/user
fallback, ordering, dedupe, and every exception translation over a
fake. The production OctokitGateway is [ExcludeFromCodeCoverage].
- WorkspaceViewModel.SyncRunner: an internal seam so the view model's
own OperationCanceledException handling is exercisable (the engine
swallows cancellation into a summary).
- CredentialManagerVault: internal target-name/platform seams cover the
error arms; VaultEdgeTests drive them.
- LibGit2GitClient is [ExcludeFromCodeCoverage] as the native-libgit2
boundary (like OctokitGateway) — verified behaviorally by the
integration suites; its transport- and cancellation-timing branches
are not deterministically reproducible offline (see its remarks).
New/expanded tests: GitHubListerTests, VaultEdgeTests, AppSettingsTests,
CoverageResidueTests, plus WorkspaceViewModel and WindowsPathValidator
residue. 267 engine/viewmodel tests, all green.
gclo.Cli coverage (its own console-coupled head) is the remaining piece
and needs a testability refactor; tracked next.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The coordinator now announces each account's place in the pass (Queued
up front, Running when its turn starts, then Succeeded / Failed /
Skipped — canceled queues badge the unstarted remainder as Skipped
without changing the result's skip count). MainWindow maps the states
to pane badges: informational dot while queued, the existing attention
dot while running (now with a live "N of M repositories" tooltip),
a success check on clean completion, the failed-repo count on a red
badge otherwise, and a caution dot for skipped accounts. States are
run-scoped and cleared when the next pass starts. Five coordinator
transition tests added.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
An older settings file has no SplashMilliseconds field, which deserializes
to 0 and was clamped to the 500ms minimum — existing users would get a
blink instead of the intended 5s default. Zero now reads as "unset" and
migrates to the default (test added).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>