fix(e2e): let expect(await response.json()) reach the value matchers

Merged
KR
7d ago
+32-9

expect(await response.json()).toMatchSchema(schema) failed to type-check on the web engine's WebResponse:

TS2339: Property 'toMatchSchema' does not exist on type 'AsyncExpectation'.
  • json<T = unknown>(): Promise<T> infers T from its contextual type. expect's first overload was (actual: Locator), so T became Locator and the call routed to the locator matchers. expect.soft did the same.
  • The locator and screen overloads are now generic (<L extends Locator>(actual: NotAny<L>)). TypeScript infers nothing from a bare type parameter, so json() keeps unknown and lands on the value overload. packages/e2e/src/types.ts:1011
  • NotAny keeps any off the locator overload. A generic L would otherwise match any, and the DOM fetch(...).json() from the API testing guide would have regressed.
  • json<T>() is unchanged, so const users: User[] = await response.json() still infers T.

Closes ENG-974.

Verified

Ran it locally: yes

  • Typechecked a scratch test in apps/testbed (DOM lib) against the built packages, on main and on this branch:
expect(...)mainthis branch
await response.json() (web engine) .toMatchSchemaTS2339ok
expect.soft(await response.json()) .toMatchSchemaTS2339ok
await (await fetch(url)).json() (DOM any) .toMatchSchemaokok
JSON.parse('[]') .toEqualokok
const users: User[] = await response.json()okok
locator, screen, browser, Locator | undefined routingunchangedunchanged
  • sdk-types.ts gains the engine-response and any cases for expect and expect.soft. Both fail against the old overloads.
  • All 9 nightly examples (vite, next, astro, expo, swiftui, compose, kotlin-multiplatform, flutter, maui) pass tsc --noEmit with this branch's packed e2e, @e2e-dev/web, and @e2e-dev/mobile swapped in.

Changes by Claude Opus 5.5 (claude-opus-5-5) in Claude Code, via T3 Code.