Skip to content

test(core): add config and watcher test services - #39157

Merged
kitlangton merged 1 commit into
v2from
test-fixtures
Jul 27, 2026
Merged

kitlangton merged 1 commit into
v2from
test-fixtures

Conversation

@kitlangton

Copy link
Copy Markdown
Contributor

What

First-class test services for Config and Watcher, replacing 25 ad-hoc Config.Service.of stubs and 3 hand-rolled Watcher PubSub stubs across core and simulation. Third slice of the config source reload series (#38983, #39131); the upcoming command/agent/plugin source-reload PRs consume these fixtures directly.

Every interface addition to Config (like changes() in #39131) previously broke every stub site — including ones outside core that local greps missed and CI caught late. Now there is exactly one implementation to update.

How

Follows the First-Class App Test Stubs pattern (TestInterface extends Interface, one object backing both the real and Test tags via Layer.effectContext, testLayer naming):

  • packages/core/src/config.ts — Config.Test adds setEntries(entries) and emitChange(update); Config.testLayer(initial?) provides both Config.Service and Config.Test from one Ref + PubSub instance.
  • packages/core/src/filesystem/watcher.ts — Watcher.Test adds emit(update) and read-only subscriptions() (the subscribe-call log tests already asserted by hand); Watcher.testLayer provides both tags.
  • Statics live in src so other packages share one canonical impl (packages/simulation stubs Config today).

Conversion notes:

  • test/config/config.test.ts — its testLayer helper now defaults to Watcher.testLayer (previously tests without an explicit watcher silently used the native watcher) and merges the watcher layer by reference so Watcher.Test resolves to the same memoized instance inside the AppNodeBuilder graph.
  • test/config/reload.test.ts and test/config/policy.test.ts — mutable let entries closures become Config.Test.setEntries, removing the shared-mutable-variable pattern.
  • test/tool-read.test.ts — same conversion; the module-level let configEntries + beforeEach reset is gone, each test gets a fresh Ref and sets entries explicitly. Layer memoization shares the one Config instance with the nested Image.node build.
  • test/config/provider.test.ts / policy.test.ts — addPlugin helpers now take Config.Entry[] instead of a hand-built service.

Scope

Npm, Credential, and WellKnown stubs (5 files, one-off shapes) are deliberately not converted; they migrate opportunistically when a PR touches them.

Testing

  • New fixture behavior tests: Config > backs Config.Service and Config.Test with one shared test implementation, Watcher.testLayer > records subscriptions and broadcasts emitted updates through the service.
  • 128 tests across all 18 touched files: 127 pass; the 1 failure (PluginSupervisor config > reloads an auto-discovered plugin when its file changes) is pre-existing on clean base.
  • bun typecheck clean in core and simulation; repo-wide pre-push typecheck passed.

@kitlangton
kitlangton merged commit 713658c into v2 Jul 27, 2026
7 of 9 checks passed
@kitlangton
kitlangton deleted the test-fixtures branch July 27, 2026 18:32
jinhuang712 pushed a commit to jinhuang712/opencode that referenced this pull request Sep 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant