Skip to content

feat(vitest): expose mock controllers as using-friendly factories#1282

Open
toiroakr wants to merge 9 commits into
mainfrom
feat/using-mock
Open

feat(vitest): expose mock controllers as using-friendly factories#1282
toiroakr wants to merge 9 commits into
mainfrom
feat/using-mock

Conversation

@toiroakr
Copy link
Copy Markdown
Contributor

@toiroakr toiroakr commented Jun 1, 2026

Summary

  • Rename and reshape the @tailor-platform/sdk/vitest mock controllers from noun-style singleton objects (tailordbMock, workflowMock, …) to verb-style factory functions (mockTailordb, mockWorkflow, mockSecretmanager, mockAuthconnection, mockIdp, mockFile, mockIconv) acquired with a using declaration.
  • Back the mocks with vi.fn(): each mockX() installs its namespace's vi.fns onto globalThis on acquisition and restores the previous value on dispose. The shared globalThis STATE_KEY state bag is gone — state 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, …) so native matchers like expect(wf.triggerJobFunction).toHaveBeenCalledWith(...) work.
  • Split the vi-free base surface (tailor/tailordb containers, context stub, error classes, runtime flag) into globals.ts so the Vitest environment (which runs where vi is 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 from tailor.config.ts survive across using scopes while per-test setSecrets() overrides stay isolated.
  • Update all runtime/vitest/integration tests, the example project, the create-sdk scaffolding templates, and the testing/runtime docs.

Breaking Changes (Beta)

This changes the Beta @tailor-platform/sdk/vitest mock API. Migration:

-import { tailordbMock } from "@tailor-platform/sdk/vitest";
-
-beforeEach(() => tailordbMock.reset());
-
 test("...", () => {
-  tailordbMock.enqueueResult({ age: 30 });
-  expect(tailordbMock.executedQueries).toHaveLength(1);
+  using db = mockTailordb();
+  db.enqueueResult({ age: 30 });
+  expect(db.executedQueries).toHaveLength(1);
 });
  • Acquire what you use: a namespace's mock is installed on acquisition, so code under test that calls a platform API (e.g. tailor.workflow, tailordb.Client) must run inside a test that acquired the matching mockX(). The base surface (tailor.context, the error classes) is always present.
  • The cross-method workflowMock.calls ordered array is dropped; assert via the per-fn vi.fn mock.calls or the reshaped waitCalls/resolveCalls helpers.

using requires TypeScript >= 5.2 and a runtime that provides Symbol.dispose (Node >= 20.4; the SDK targets Node >= 22, and Vitest's transformer downlevels the syntax).

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-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jun 1, 2026

🦋 Changeset detected

Latest commit: 77e5ffe

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@tailor-platform/sdk Minor
@tailor-platform/create-sdk Minor

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

This comment was marked as outdated.

…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.

This comment was marked as outdated.

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).
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

⚡ pkg.pr.new

@tailor-platform/sdk

pnpm add https://pkg.pr.new/@tailor-platform/sdk@097dfee
pnpm dlx https://pkg.pr.new/@tailor-platform/sdk@097dfee --help

@tailor-platform/create-sdk

pnpm add https://pkg.pr.new/@tailor-platform/create-sdk@097dfee
pnpm dlx https://pkg.pr.new/@tailor-platform/create-sdk@097dfee my-app

commit: 097dfee

This comment was marked as outdated.

@github-actions

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.
@github-actions

This comment has been minimized.

This comment was marked as outdated.

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.
@github-actions

This comment has been minimized.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 3 comments.

Comment thread packages/sdk/docs/testing.md Outdated

### TailorDB Mock

The environment auto-injects a mock `tailordb.Client`. Use `tailordbMock()` to configure responses and assert on executed queries:
Comment thread packages/sdk/docs/testing.md Outdated
### 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.
@github-actions

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.
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@toiroakr toiroakr marked this pull request as ready for review June 2, 2026 13:20
@toiroakr toiroakr requested a review from remiposo as a code owner June 2, 2026 13:20
@claude
Copy link
Copy Markdown

claude Bot commented Jun 2, 2026

📖 Docs Consistency Check

⚠️ Inconsistency Found

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.md
  • packages/sdk/src/vitest/index.ts JSDoc

Configuration documentation - N/A (no config changes)

Example code - All examples updated correctly:

  • example/tests/bundled_execution.test.ts
  • packages/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.md to use mockTailordb() instead of tailordbMock

Re-run this check by adding the docs-check label 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`.
@toiroakr toiroakr requested a review from dqn as a code owner June 5, 2026 06:50
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Jun 5, 2026

Open in StackBlitz

pnpm add https://pkg.pr.new/@tailor-platform/create-sdk@77e5ffe
pnpm add https://pkg.pr.new/@tailor-platform/sdk@77e5ffe

commit: 77e5ffe

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 5, 2026

Code Metrics Report (packages/sdk)

main (7e4200f) #1282 (e2cf934) +/-
Coverage 66.0% 66.1% +0.0%
Code to Test Ratio 1:0.4 1:0.4 +0.0
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%)

Files Coverage +/- Status
packages/sdk/src/configure/services/workflow/job.ts 100.0% 0.0% modified
packages/sdk/src/configure/services/workflow/test-env-key.ts 100.0% 0.0% modified
packages/sdk/src/configure/services/workflow/wait-point.ts 100.0% 0.0% modified
packages/sdk/src/runtime/authconnection.ts 100.0% 0.0% modified
packages/sdk/src/runtime/file.ts 100.0% 0.0% modified
packages/sdk/src/runtime/iconv.ts 100.0% 0.0% modified
packages/sdk/src/runtime/idp.ts 100.0% 0.0% modified
packages/sdk/src/runtime/secretmanager.ts 100.0% 0.0% modified
packages/sdk/src/runtime/workflow.ts 100.0% 0.0% modified
packages/sdk/src/utils/test/mock.ts 57.1% 0.0% modified
packages/sdk/src/vitest/globals.ts 90.9% +90.9% added
packages/sdk/src/vitest/index.ts 100.0% 0.0% modified
packages/sdk/src/vitest/mock.ts 93.0% +2.0% modified
packages/sdk/src/vitest/setup.ts 86.0% 0.0% modified

SDK Configure Bundle Size

main (7e4200f) #1282 (e2cf934) +/-
configure-index-size 19.69KB 19.69KB 0KB
dependency-chunks-size 34.65KB 34.65KB 0KB
total-bundle-size 54.34KB 54.34KB 0KB

Runtime Performance

main (7e4200f) #1282 (e2cf934) +/-
Generate Median 2,132ms 2,794ms 662ms
Generate Max 2,175ms 2,821ms 646ms
Apply Build Median 2,167ms 2,831ms 664ms
Apply Build Max 2,185ms 2,857ms 672ms

Type Performance (instantiations)

main (7e4200f) #1282 (e2cf934) +/-
tailordb-basic 33,959 33,959 0
tailordb-optional 3,841 3,841 0
tailordb-relation 5,921 5,921 0
tailordb-validate 2,566 2,566 0
tailordb-hooks 5,767 5,767 0
tailordb-object 12,136 12,136 0
tailordb-enum 2,462 2,462 0
resolver-basic 9,424 9,424 0
resolver-nested 26,111 26,111 0
resolver-array 18,187 18,187 0
executor-schedule 4,234 4,234 0
executor-webhook 873 873 0
executor-record 6,659 6,659 0
executor-resolver 4,369 4,369 0
executor-operation-function 868 868 0
executor-operation-gql 869 869 0
executor-operation-webhook 888 888 0
executor-operation-workflow 1,714 1,714 0

Reported by octocov

@toiroakr
Copy link
Copy Markdown
Contributor Author

toiroakr commented Jun 5, 2026

@remiposo
I intend to merge this together with #1308, but I thought it might be easier to review if I keep the PRs separate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants