Skip to content

Deprecate the MSW v1 ctx compat layer in GraphQL mocks, and fix the misleading ctx comment in generated cell mocks #2135

Description

@Tobbe

Two related follow-ups deliberately left out of #2133 (MSW 2 upgrade), because both are docs/DX changes rather than dependency work. They share a root cause: the ctx object Cedar exposes in GraphQL mocks is an MSW v1 API that no longer exists upstream, and its name collides with several unrelated Cedar concepts.

Background

MSW v2 removed the (req, res, ctx) resolver signature. ctx was a bundle of response transformersctx.data() constructs a response body, it never reads request state. To avoid breaking every existing app, #2133 reimplements that shape as a Cedar compatibility layer on top of v2's HttpResponse (packages/testing/src/web/mockRequests.ts).

That was the right call for the upgrade, but it leaves Cedar carrying an API that no longer exists in the library it wraps, under a name that means four other things in this codebase. See the THE FIVE CONTEXTS section in docs/implementation-docs/2026-03-26-cedarjs-project-overview.md for the full disambiguation.


1. Deprecate the ctx compat layer in favour of returning HttpResponse

Why this is low-risk: across all fixtures, templates, and local-testing-project there are 23 cell mock files and zero use the function-plus-ctx form. There are also zero direct mockGraphQLQuery call sites outside of tests. The entire breaking surface is resolvers that call ctx.status/delay/errors, which in real code is currently nothing.

Suggested approach — additive, not a breaking change. Keep mockGraphQLQuery / mockGraphQLMutation as the registration mechanism; they own the handler queue and the reset-between-tests lifecycle, and they're what makes the auto-wrapped cell mocks work at all. Only the fake ctx goes away. Detecting whether a resolver returned an HttpResponse versus plain data is trivial, so both forms can coexist:

// still works — plain data, the 100% case today
mockGraphQLQuery('GetArticle', { article: { id: 1 } })

// new — return an HttpResponse for anything ctx used to do
mockGraphQLQuery('GetArticle', () =>
  HttpResponse.json({ errors: [{ message: 'Uh oh' }] }, { status: 404 }),
)

Then emit a deprecation warning when a resolver destructures/uses ctx, and remove it in a later major.

Explicitly not proposed: having users write graphql.query(...) and manage server.use() themselves. That would break the cell-mock auto-wrapping in cedarMockCellDataPlugin, which is genuinely load-bearing.

Docs to update (current docs only — docs/versioned_docs/** are frozen snapshots and should be left alone):

File ctx. mentions
docs/docs/graphql/mocking-graphql-requests.md 8
docs/docs/testing.md 2
docs/docs/tutorial/chapter6/comment-form.md 2
docs/docs/how-to/mocking-graphql-in-storybook.md 1

Naming caution for the write-up: describe this as "MSW's response transformers are replaced by returning an HttpResponse", never as "deprecating ctx". mockCurrentUser() exists on both the web and api sides, and api-side services read a global context — so "we're deprecating ctx" reads to a Cedar developer as "Cedar's context is changing", which is false and alarming.

2. Fix the misleading ctx comment in generated cell mocks

cedar generate cell emits a commented-out signature advertising an MSW-v1-ism:

// packages/cli/src/commands/generate/cell/templates/mock.ts.template
// packages/cli/src/commands/generate/cell/templates/mockList.ts.template
export const standard = (/* vars, { ctx, req } */) => ({
  // ...
})

This is the one place Cedar itself puts ctx in front of users, in a file where they'd reasonably assume it means Cedar's api-side context. It should be fixed regardless of whether item 1 happens, and it's a good first issue on its own.

Open question: vars (the query variables) is still legitimate and useful, so the options are roughly:

  • drop the comment entirely — export const standard = () => ({ ... })
  • keep only the useful half — export const standard = (/* vars */) => ({ ... })
  • update it to whatever signature item 1 settles on

Worth deciding item 1's direction first if both are done together, though item 2 can land independently.

Notes

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions