Skip to content

Add an integration test suite#412

Merged
csandman merged 9 commits into
mainfrom
test/integration-suite
May 16, 2026
Merged

Add an integration test suite#412
csandman merged 9 commits into
mainfrom
test/integration-suite

Conversation

@csandman

@csandman csandman commented May 16, 2026

Copy link
Copy Markdown
Owner

Summary

Adds the package's first real integration test suite, built on top of the upstream react-select tests with adaptations for the Chakra wrapper. Before this PR the only tests were in codemod/; the package itself had zero coverage.

What's in here

Ported from react-select@5.10.2 — the core component tests come straight from upstream, adapted only where chakra-react-select diverges. Each ported file carries a header comment with a permalink to its source at the pinned version:

Adaptations applied to every ported file (also documented in CONTRIBUTING.md for future dep bumps):

  • Imports point at ../index instead of ../Select/etc.
  • A Chakra-provider-wrapped render (see src/tests/render.tsx) replaces the bare @testing-library/react render.
  • userEvent.setup() + await user.X(...) instead of synchronous userEvent.X(...) (the upstream tests predate userEvent v14's async API).
  • vi.fn/vi.mock instead of jest.fn/jest.mock.
  • A small src/tests/cases.ts shim provides the jest-in-case cases() function (with per-case skip/only flag support) so the upstream parameterised tests run unchanged.
  • Snapshot tests dropped — Chakra renders a different DOM than upstream's emotion-styled components, so the snapshots would lock us to whatever the test happened to render first.
  • A handful of tests are test.skiped with oxlint-disable-next-line comments: either upstream's own QUESTION-marked tests (e.g. "we currently do not do this, do we want to?") or intentional Chakra divergences (the theme prop is intentionally ignored in favor of Chakra's design tokens).

Chakra-specific testssrc/tests/chakra-specific.test.tsx covers the props this package adds on top of react-select: size, variant, invalid, disabled, readOnly, chakraStyles, tagColorPalette, tagVariant, selectedOptionStyle, selectedOptionColorPalette, focusRingColor, plus the useChakraSelectProps hook. Uses a "probe pattern" — pass a chakraStyles callback that captures state.selectProps.<prop> — to verify wiring without depending on jsdom's CSS engine (which can't reliably parse Chakra's @layer-based CSS).

One incidental fix — in src/use-chakra-select-props.ts, passing invalid directly to <Select> now propagates to aria-invalid on the input. Previously only <Field.Root invalid> did. Surfaced while writing the chakra-specific tests.

Infrastructure

  • Test runner: Vitest + jsdom + @testing-library/react + @testing-library/user-event + @testing-library/jest-dom (matches the codemod's already-vitest setup).
  • src/tests/setup.ts wires up cleanup, a matchMedia polyfill (Chakra's useMediaQuery calls it on mount), and a jsdom virtualConsole filter that suppresses the "Could not parse CSS stylesheet" noise Chakra triggers per <style> insert.
  • .github/workflows/test.yml runs the suite on Node 20 and 24, on push to main and on PR.
  • pnpm test, pnpm test:watch added; prepublishOnly now runs the suite too.

Linting

After the initial port, src/tests/ was added to oxlint's ignorePatterns because applying the project's full strict ruleset to upstream-style test code produced ~270 errors. The final commit on this branch reverses that — tests now get linted alongside source, with a scoped override in .oxlintrc.json for the small set of rules that legitimately don't apply to spy/mock-style test code. The vitest plugin is added project-wide (with stylistic preferences disabled). init-declarations ends up off project-wide because it directly conflicts with unicorn/no-useless-undefined and we prefer the latter's style (let captured: T | undefined; over let captured: T | undefined = undefined;).

Test plan

  • pnpm lint — passes (4 no-warning-comments warnings for pre-existing project TODOs + upstream-ported // TODO: Cover more scenarios notes; intentional)
  • pnpm lint:types — clean
  • pnpm test271 passed / 4 skipped on both Node 20 and Node 24
  • CI workflow ran on push and PR

Out of scope

  • Cypress E2E tests (deferred — upstream has 2 specs but they need a running demo page)
  • Filling out an even broader chakra-specific suite — current file covers the major user-facing props, but slot-by-slot chakraStyles coverage is incomplete

🤖 Generated with Claude Code

csandman and others added 9 commits May 14, 2026 14:36
Adds vitest + jsdom + @testing-library/{react,user-event,jest-dom} as
devDependencies and configures a Chakra-provider-wrapped render helper.
Ports the upstream react-select tests (Select, Async, Creatable,
AsyncCreatable, StateManaged + the constants fixture) from
react-select@5.10.2 with the adaptations the wrapper needs: imports
from the package source, userEvent v14 async migration, and a small
jest-in-case shim that honors per-case skip/only flags.

Adds dedicated coverage for the props this package layers on top of
react-select (size, variant, invalid, disabled, readOnly, chakraStyles,
tagColorPalette, tagVariant, selectedOptionStyle,
selectedOptionColorPalette, focusRingColor, useChakraSelectProps),
using a probe pattern that captures chakraStyles slot state to bypass
jsdom CSS-engine flakiness.

Also fixes a small accessibility gap surfaced while writing tests:
passing \`invalid\` directly to Select now propagates to aria-invalid on
the rendered input, matching how Field.Root invalid inheritance already
worked.

A CI workflow runs the suite on push to main/v5 and on PR. Final tally:
271 passing, 4 skipped (upstream's own QUESTION-marked tests and
intentional Chakra divergences). The .oxlintrc.json ignores src/tests/
since upstream's style differs from our strict project rules.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Each branch's workflow only knows about its code, so listing both
[main, v5] in a single workflow file is a footgun — only the branch
whose name matches will actually run, and pushing to the other
branch silently fires nothing useful from this file. Matches the
existing convention used by lint.yml, pkg-pr.yml, and zizmor.yml.

A parallel copy in the v5 branch should reference [v5] only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Moves the lint-staged config from package.json into .lintstagedrc.cjs
so we can use a function to filter file lists before invoking oxlint.
oxlint exits non-zero with "No files found to lint" when every staged
path matches its ignorePatterns (e.g. a commit touching only files
under src/tests/), which broke the pre-commit hook for test-only
changes. The filter drops src/tests/ paths before invoking oxlint;
oxfmt still formats them via the catch-all glob.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Each ported test file now carries a header comment with a permalink to
the exact upstream source at react-select@5.10.2 plus a brief re-port
checklist for future dep bumps. constants.ts gets a verbatim note
since its data fixtures should stay bit-identical with upstream.

No behavior change — comments only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a Node version matrix to the test workflow so we catch regressions
that depend on the runtime — particularly relevant given the test suite
relies on jsdom whose CSS serialization differs across versions (we
already hit a jsdom 22 -> 25 change in caret-color handling). 20 is the
current LTS, 24 is the latest stable. fail-fast: false so a failure on
one runner doesn't cancel the other and obscure which is broken.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a `pnpm test` bullet to the pre-PR checklist and a new Tests
section explaining the suite layout, the file naming convention, and
the manual re-port checklist for `react-select` dep bumps. The intent
is to make the porting boundary explicit so future contributors don't
fold chakra-specific assertions back into the ported files or skip
the upstream-source comments.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`.cjs` was unnecessary in a `type: commonjs` project — a plain `.js`
file already would have been CommonJS — and ESM is the better default
for new config files. Behavior unchanged from the previous .cjs
version. Uses `import.meta.dirname` (Node 20.11+); our CI matrix
requires Node 20+.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two layers:

* In source: name the default export (satisfies
  import/no-anonymous-default-export) and add braces to the bare
  if/return (satisfies eslint/curly). Both fixes are easy improvements
  that match project style.
* In config: add a *.mjs override that disables rules which
  fundamentally don't apply to root tooling configs —
  import/no-nodejs-modules (Node tooling legitimately imports
  node:built-ins) and the three typescript/no-unsafe-* rules (a .mjs
  file has no TS declarations, so type-aware oxlint sees everything as
  `any`).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes `src/tests/` from `.oxlintrc.json` `ignorePatterns` so the
tests now get linted alongside source. A scoped override exempts the
small set of rules that legitimately don't apply to spy/mock-style
test code: TS unsafe checks, the `cases()` non-null assertions,
react-perf inline-prop rules, jsx-a11y rules for synthetic fixtures,
and a handful of unicorn opinions that don't fit our jsdom env.

Also adds the `vitest` plugin and enables most of its rules
project-wide; the disables for vitest stylistic preferences
(`prefer-to-be*`, `prefer-lowercase-title`, etc.) live at the top
level since those rules are no-ops outside test files anyway.

Source side: a sweep that converts the upstream-ported style to
project conventions — `let` → `const` where appropriate, type-only
import splits, `toHaveLength`/`toStrictEqual` matcher upgrades,
function declarations to expressions, a few prefer-destructuring
rewrites, regex `u` flags, etc. Two intentional patterns get
per-line `oxlint-disable-next-line` comments (definite-assignment
`let event!:`, the 4th-element index in state-managed-select).

`init-declarations` ends up off project-wide. It conflicts with
`unicorn/no-useless-undefined` (one wants `= undefined`, the other
forbids it); we pick the no-useless-undefined style so
`let captured: T | undefined;` stays uninitialised. The change goes
at the top level rather than in the test override because the
preference is consistent for source code too.

Test counts: 271 passing, 4 skipped, 0 lint errors. Remaining lint
output is 4 `no-warning-comments` warnings (2 pre-existing project
TODOs in src/chakra-components, 2 upstream-ported `TODO: Cover more
scenarios` in select.test.tsx) — kept as warnings intentionally to
keep TODOs visible.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bolt-new-by-stackblitz

Copy link
Copy Markdown

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@pkg-pr-new

pkg-pr-new Bot commented May 16, 2026

Copy link
Copy Markdown

commit: 76d55aa

@github-actions

Copy link
Copy Markdown

📊 Package size report   0.2%↑

File Before After
dist/index.js 30.9 kB 0.5%↑31.1 kB
dist/index.mjs 29.4 kB 0.5%↑29.5 kB
package.json 2.8 kB 3%↑2.8 kB
Total (Includes all files) 152.5 kB 0.2%↑152.8 kB
Tarball size 29.9 kB 0.4%↑30.1 kB
Unchanged files
File Size
dist/index.d.mts 20.1 kB
dist/index.d.ts 20.1 kB
LICENSE.md 1.1 kB
README.md 48.1 kB

🤖 This report was automatically generated by pkg-size-action

@csandman csandman changed the title Enable oxlint on the test suite Add an integration test suite May 16, 2026
@csandman csandman merged commit cf64198 into main May 16, 2026
9 checks passed
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.

1 participant