feat(expect): add cross-engine toBeInViewport matcher

AN
9d ago
+234-3

Adds a portable locator assertion for viewport intersection.

  • ratio ranges from 0 to 1; 0 and the default require any positive intersection.
  • Missing geometry fails clearly even under .not, and stale observations retry within the assertion deadline.
  • The matcher uses the node box and viewport rectangle. The shared engine contract has no ancestor clip data, so overflow clipping is outside this assertion's check; the docs mark that migration difference as by design.
await expect(screen.getByRole('toolbar', 'Selection')).toBeInViewport({ ratio: 0.5 });

Verified

Ran it locally: yes

  • Built CLI on the testbed, tests/controls.e2e.ts --video: 16 tests passed, including the offscreen/after-scroll assertion.
  • pnpm test:web-benchmark: all 91 tests in 41 files passed.
  • expect-viewport.test.ts: 6 passed; pnpm typecheck, pnpm lint, pnpm plugins:check, and pnpm mcp-server:check passed.
  • Full pnpm test ran but failed on this Windows host (36 files, 154 cases), with failures including \\.\nul, symlink EPERM, POSIX path and permission expectations. The viewport tests passed.
  • pnpm check stops in check:dead-code on the existing unused scripts/check-dist.ts, scripts/stamp-dist.ts, and dependency-override findings. pnpm docs:check passed its static checks, then Mintlify validation failed to load the installed Win32 Sharp binary (ERR_DLOPEN_FAILED). The full testbed run also has Windows visual baseline failures; the controls file passed in the built CLI run above.
  • The video was recorded locally. Installed GitHub CLI is 2.97.0 and does not support --attach (available in 2.99+).

The migration guide shortening pass changed the Assertions mapping only: 455 to 456 lines and 4,581 to 4,603 prose words, adding the documented clipping distinction.