feat(vitest): expose mock controllers as using-friendly factories#1282
feat(vitest): expose mock controllers as using-friendly factories#1282toiroakr wants to merge 9 commits into
Conversation
Convert the tailor-runtime mock controllers (tailordbMock, workflowMock, secretmanagerMock, authconnectionMock, idpMock, fileMock, iconvMock) from singleton objects into factory functions that return a Disposable. Acquiring one with a using declaration resets its state automatically when the scope exits, removing the need for beforeEach(() => mock.reset()). Acquisition no longer resets state, so secrets seeded from tailor.config.ts survive until disposal. Update all runtime/vitest tests, example, scaffolding templates, and docs to the new pattern.
🦋 Changeset detectedLatest commit: 77e5ffe The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
…copes Address Copilot review: disposing a secretmanagerMock() acquired with using previously called reset(), wiping the secret store seeded once outside tests (e.g. from tailor.config.ts via setup.ts) for subsequent tests. The factory now snapshots the store on acquisition and restores it on dispose, clearing only the call records, so per-test setSecrets() overrides stay isolated while the global seed survives. asUsingMock gains optional onAcquire/onDispose hooks to support this snapshot/restore behavior.
Resolve conflicts from main's file-streaming API and workflow env additions against the vitest mock using-factory conversion: - mock.test.ts: drop beforeEach reset (using auto-resets), keep afterEach vi.unstubAllEnvs for the new env tests, convert the setEnv/WORKFLOW_TEST_ENV_KEY tests to using wf = workflowMock(), and switch the createWorkflowJob dynamic imports to a static top-level import. - file.test.ts: convert main's new downloadStream/uploadStream tests to using. - docs/testing.md: apply using to both the new downloadStream example and the deprecated openDownloadStream example. - workflow template order-fulfillment.test.ts: drop the now-unnecessary afterEach reset (no test configures the mock).
⚡ pkg.pr.new@tailor-platform/sdk@tailor-platform/create-sdk
|
This comment has been minimized.
This comment has been minimized.
… a shared state bag Rebuild the @tailor-platform/sdk/vitest mock controllers so each xMock() installs vi.fn-backed mocks for its namespace onto globalThis on acquisition and restores the previous value on dispose. The shared globalThis STATE_KEY state bag is gone — state now lives in the per-acquisition vi.fns/closures, so namespaces and nested using scopes are isolated. - Keep the friendly helper API (setJobHandler, enqueueResult, executedQueries, triggeredJobs, waitCalls, …) as thin wrappers over the vi.fns, and expose the raw vi.fns (db.queryObject, wf.triggerJobFunction, …) for native matchers. - Split the vi-free base surface (tailor/tailordb containers, context stub, error classes, runtime flag) into globals.ts so environment.ts no longer imports the vi-dependent mock module. - Move per-namespace mock installation to acquisition time (vi is available there); the environment installs only the base surface. Code under test must run inside a test that acquired the matching xMock(). - Drop the cross-method workflowMock.calls ordered array; assert via the per-fn vi.fn mock.calls or the reshaped waitCalls/resolveCalls helpers. - secretmanagerMock inherits the installed secret store on acquisition and restores it on dispose, so config-seeded secrets survive across scopes. Update SDK/runtime/integration tests and the testing/runtime docs accordingly.
This comment has been minimized.
This comment has been minimized.
Drop the internal-implementation details (vi.fn backing, install/restore, acquire-time requirement) from the runtime testing note; those belong in the testing guide. Keep only the user-facing essentials: factory + using + auto-reset on scope exit + requirements.
This comment has been minimized.
This comment has been minimized.
|
|
||
| ### TailorDB Mock | ||
|
|
||
| The environment auto-injects a mock `tailordb.Client`. Use `tailordbMock()` to configure responses and assert on executed queries: |
| ### Workflow Mock | ||
|
|
||
| The environment auto-injects `tailor.workflow.triggerJobFunction`. Use `workflowMock` to configure job responses: | ||
| The environment auto-injects `tailor.workflow.triggerJobFunction`. Use `workflowMock()` to configure job responses: |
| expect(iconvMock.calls[0]?.method).toBe("convert"); | ||
| }); | ||
| expect(iconvM.calls[0]?.method).toBe("convert"); | ||
| }); // iconvM.reset() runs here automatically |
Rename the mock controllers from noun-style (tailordbMock, workflowMock, secretmanagerMock, authconnectionMock, idpMock, fileMock, iconvMock) to verb-style factory functions (mockTailordb, mockWorkflow, mockSecretmanager, mockAuthconnection, mockIdp, mockFile, mockIconv) — mock as a verb (the act of mocking), not a noun. Update all SDK/runtime/integration tests, the example project, the create-sdk scaffolding templates, the testing/runtime docs, the changeset, and the comments/error messages that reference the old names. mock-types.test.ts no longer acquires a mock: it is a pure type test, so the call expressions are wrapped in never-invoked arrow functions and asserted via expectTypeOf(fn).returns, removing the runtime globals dependency entirely.
This comment has been minimized.
This comment has been minimized.
… testing guide The changeset and testing docs described how the mocks work under the hood (vi.fn backing, globalThis install/restore, the globals.ts split, the secret store snapshot/restore). Keep only the user-facing surface: the rename to mockX() factories, the using/auto-reset usage, the acquire-what-you-use and seeded-secrets behavior, and the migration + requirements.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
📖 Docs Consistency Check
|
| File | Issue | Suggested Fix |
|---|---|---|
packages/sdk/docs/testing.md:537 |
Uses old API name tailordbMock instead of new factory function name |
Update to mockTailordb() |
Details
packages/sdk/docs/testing.md:537
The line currently reads:
Reach for [`tailordbMock`](#mocking-the-tailordb-client) instead when you want to drive the raw query sequence at the `tailordb.Client` level rather than at the Kysely layer.This references the old singleton object name tailordbMock, but the PR renamed all mock controllers from noun-style singletons (tailordbMock, workflowMock, etc.) to verb-style factory functions (mockTailordb(), mockWorkflow(), etc.). The documentation consistently uses the new names everywhere else in this file and throughout the PR.
Suggested fix:
Reach for [`mockTailordb()`](#mocking-the-tailordb-client) instead when you want to drive the raw query sequence at the `tailordb.Client` level rather than at the Kysely layer.Checked Areas
✅ CLI documentation - N/A (no CLI changes in this PR)
✅ Public API documentation - All references updated correctly in:
packages/sdk/docs/testing.md(except line 537)packages/sdk/docs/runtime.mdpackages/sdk/src/vitest/index.tsJSDoc
✅ Configuration documentation - N/A (no config changes)
✅ Example code - All examples updated correctly:
example/tests/bundled_execution.test.tspackages/create-sdk/templates/**/*.test.ts
✅ CLAUDE.md - Updated correctly in the PR (note: there's an uncommitted local change that reverted it back, but the PR itself is correct)
Recommended Actions
- Update line 537 in
packages/sdk/docs/testing.mdto usemockTailordb()instead oftailordbMock
Re-run this check by adding the
docs-checklabel to the PR.
Resolve the CLAUDE.md conflict: main centralized the agent instructions into AGENTS.md and reduced CLAUDE.md to an `@AGENTS.md` include. Adopt that, and re-apply this PR's mock-API note in AGENTS.md (use `using wf = mockWorkflow()` + `wf.setWaitHandler`/`wf.setResolveHandler`). Also update the new Kysely section's TailorDB-mock link in testing.md to the renamed `mockTailordb`.
commit: |
Code Metrics Report (packages/sdk)
Details | | main (7e4200f) | #1282 (e2cf934) | +/- |
|--------------------|----------------|-----------------|-------|
+ | Coverage | 66.0% | 66.1% | +0.0% |
| Files | 394 | 395 | +1 |
| Lines | 13519 | 13542 | +23 |
+ | Covered | 8928 | 8954 | +26 |
+ | Code to Test Ratio | 1:0.4 | 1:0.4 | +0.0 |
| Code | 90419 | 90381 | -38 |
+ | Test | 39066 | 39127 | +61 |Code coverage of files in pull request scope (88.8% → 90.0%)
SDK Configure Bundle Size
Runtime Performance
Type Performance (instantiations)
Reported by octocov |
Summary
@tailor-platform/sdk/vitestmock controllers from noun-style singleton objects (tailordbMock,workflowMock, …) to verb-style factory functions (mockTailordb,mockWorkflow,mockSecretmanager,mockAuthconnection,mockIdp,mockFile,mockIconv) acquired with ausingdeclaration.vi.fn(): eachmockX()installs its namespace's vi.fns ontoglobalThison acquisition and restores the previous value on dispose. The sharedglobalThisSTATE_KEYstate bag is gone — state lives in the per-acquisition vi.fns/closures, so namespaces and nestedusingscopes are isolated.setJobHandler,enqueueResult,executedQueries,triggeredJobs,waitCalls, …) as thin wrappers over the vi.fns, and expose the raw vi.fns (db.queryObject,wf.triggerJobFunction, …) so native matchers likeexpect(wf.triggerJobFunction).toHaveBeenCalledWith(...)work.tailor/tailordbcontainers,contextstub, error classes, runtime flag) intoglobals.tsso the Vitest environment (which runs whereviis unavailable) no longer imports the vi-dependent mock module. Per-namespace mocks install at acquisition time; the environment installs only the base surface.mockSecretmanager()inherits the installed secret store on acquisition and restores it on dispose, so secrets seeded fromtailor.config.tssurvive acrossusingscopes while per-testsetSecrets()overrides stay isolated.exampleproject, thecreate-sdkscaffolding templates, and the testing/runtime docs.Breaking Changes (Beta)
This changes the Beta
@tailor-platform/sdk/vitestmock API. Migration:tailor.workflow,tailordb.Client) must run inside a test that acquired the matchingmockX(). The base surface (tailor.context, the error classes) is always present.workflowMock.callsordered array is dropped; assert via the per-fn vi.fnmock.callsor the reshapedwaitCalls/resolveCallshelpers.usingrequires TypeScript >= 5.2 and a runtime that providesSymbol.dispose(Node >= 20.4; the SDK targets Node >= 22, and Vitest's transformer downlevels the syntax).