Test utilities
These subpaths are repo-local source entrypoints for OpenClaw’s own bundled plugin tests. They are not publishedpackage.json exports for third-party
plugins, and they may import Vitest or other repo-only test dependencies.
openclaw/plugin-sdk/testing barrel was repo-local, excluded from shipped
packages, and has been removed. The former openclaw/plugin-sdk/test-utils
alias was removed with it. pnpm run lint:plugins:no-extension-test-core-imports
(scripts/check-no-extension-test-core-imports.ts) keeps extension tests on
the focused test subpaths above.
Bundled channel integration tests can use agent-runtime-test-contracts for
real session and subscriber fixtures, reply-payload-testing for payload
construction and delivery settlement, and plugin-test-runtime for hook
runners and registries. These helpers reuse their core owners; register the
session fixture lifecycle explicitly. Use published runtime subpaths when
they already expose the needed operation.
Available exports
Bundled-plugin contract suites also use these SDK testing subpaths for
test-only registry, manifest, public-artifact, and runtime fixture helpers.
Core-only suites that depend on bundled OpenClaw inventory stay under
src/plugins/contracts instead.
For channel account-policy tests, createAccountPolicyInheritanceCases() from
openclaw/plugin-sdk/channel-test-helpers returns four literal inheritance rows
with fresh objects and arrays on each call, preserving omitted policy fields.
Use it alongside validateTestChannelConfig(channelId, channelConfig), which
validates schema-parsed channel data through the host config boundary. Each
plugin test still owns its schema parsing, account resolver, and assertions,
including checks that omitted account policies remain absent.
For complete zero-usage inputs, createZeroUsageFixture() from
openclaw/plugin-sdk/test-fixtures returns fresh usage and nested cost objects
without optional telemetry fields. Keep expected usage values explicit.
Types
Focused testing subpaths also re-export types useful in test files:Testing target resolution
UseinstallCommonResolveTargetErrorCases to add standard error cases for
channel target resolution:
Testing patterns
Testing registration contracts
Unit tests that pass a hand-writtenapi mock to register(api) do not
exercise OpenClaw’s loader acceptance gates. Add at least one loader-backed
smoke test for each registration surface your plugin depends on, especially
hooks and exclusive capabilities such as memory.
The real loader fails plugin registration when required metadata is missing or
a plugin calls a capability API it does not own. For example,
api.registerHook(...) requires a hook name, and
api.registerMemoryCapability(...) requires the plugin manifest or exported
entry to declare kind: "memory".
Testing runtime config access
Prefer the shared plugin runtime mock fromopenclaw/plugin-sdk/plugin-test-runtime. Its runtime config helpers model the
current snapshot and mutation APIs.
Unit testing a channel plugin
Unit testing a provider plugin
For bundled catalog tests that resolve provider endpoint capabilities, calluseProviderCatalogMetadata(new URL(".", import.meta.url)) from
openclaw/plugin-sdk/plugin-test-runtime at file or suite scope. It prepares
the plugin’s manifest metadata once, installs and clears that snapshot around
each test, and rejects Jiti loading during assertions. This keeps cold runtime
discovery out of catalog test deadlines without changing provider behavior.
Mocking the plugin runtime
For code that usescreatePluginRuntimeStore, mock the runtime in tests:
Testing with per-instance stubs
Prefer per-instance stubs over prototype mutation:Contract tests (in-repo plugins)
Bundled plugins have contract tests that verify registration ownership:- Which plugins register which providers
- Which plugins register which speech providers
- Registration shape correctness
- Runtime contract compliance
Running scoped tests
For a specific plugin:Lint enforcement (in-repo plugins)
scripts/run-additional-boundary-checks.mts runs a set of lint:plugins:*
import-boundary checks in CI; each can also be run standalone locally:
External plugins are not subject to these lint rules, but following the same
patterns is recommended.
Test configuration
OpenClaw uses Vitest 5 with informational V8 coverage reporting. For plugin tests:Related
- SDK Overview — import conventions
- SDK Channel Plugins — channel plugin interface
- SDK Provider Plugins — provider plugin hooks
- Building Plugins — getting started guide