Skip to content

feat: support rstest in testing library#2328

Merged
upupming merged 37 commits intomainfrom
feat/rstest-rltl
Apr 13, 2026
Merged

feat: support rstest in testing library#2328
upupming merged 37 commits intomainfrom
feat/rstest-rltl

Conversation

@upupming
Copy link
Copy Markdown
Collaborator

@upupming upupming commented Mar 10, 2026

Summary

close #1300

This PR introduces rstest support for ReactLynx Testing Library and aligns the public testing APIs around plugin/config composition.

What changed

  • Added a new rstest config entrypoint:
    • @lynx-js/react/testing-library/rstest-config
    • withLynxConfig(...) for app scenarios (reuse lynx.config.ts)
    • withDefaultConfig(...) for library scenarios (runner defaults only)
  • Replaced rstest-adapter naming with rstest-config naming for public exports.
    • The old adapter path is removed in this PR.
  • Promoted plugin-based Vitest integration:
    • vitestTestingLibraryPlugin() is now the recommended API.
    • createVitestConfig is deprecated but still supported for backward compatibility.
  • Updated examples so users can validate both runners:
    • packages/testing-library/examples/basic
    • packages/testing-library/examples/library
    • packages/testing-library/examples/react-compiler
  • Updated package exports/docs to reflect the new API surface.

Recommended usage

Vitest

import { defineConfig } from 'vitest/config';
import { vitestTestingLibraryPlugin } from '@lynx-js/react/testing-library/plugins';

export default defineConfig({
  plugins: [vitestTestingLibraryPlugin()],
});

Rstest (app)

import { defineConfig } from '@rstest/core';
import { withLynxConfig } from '@lynx-js/react/testing-library/rstest-config';

export default defineConfig({
  extends: withLynxConfig(),
});

Rstest (library)

import { defineConfig } from '@rstest/core';
import { withDefaultConfig } from '@lynx-js/react/testing-library/rstest-config';

export default defineConfig({
  extends: withDefaultConfig(),
});

Notes

  • Main CI jobs for this change set are green after reruns for flaky jobs.
  • Codecov patch threshold checks are currently not treated as blocking for this PR.

Checklist

  • Tests updated (or not required).
  • Documentation updated (or not required).

commit ff2cb92
Merge: b2d5322 f66e319
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Wed Aug 20 16:36:09 2025 +0800

    Merge remote-tracking branch 'gh/main' into feat/rltl-rstest

commit b2d5322
Merge: 44fbd57 f0d483c
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Wed Aug 20 16:24:41 2025 +0800

    Merge remote-tracking branch 'gh/main' into feat/rltl-rstest

commit 44fbd57
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Thu Aug 14 11:18:57 2025 +0800

    fix: rstest css module classname is diff from vitest

commit 2825c3c
Merge: 24cd0a2 fcec513
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Thu Aug 14 10:20:05 2025 +0800

    Merge remote-tracking branch 'gh/main' into feat/rltl-rstest

commit 24cd0a2
Merge: 41f71f1 cb6d23c
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Wed Aug 13 19:32:36 2025 +0800

    Merge remote-tracking branch 'gh/main' into feat/rltl-rstest

commit 41f71f1
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Mon Aug 11 14:47:06 2025 +0800

    fix: update testing cases

commit 1a18210
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Mon Aug 11 12:23:48 2025 +0800

    chore: remove process.env['DEBUG']

commit 0c38300
Merge: 1f51a70 05b0096
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Mon Aug 11 12:18:52 2025 +0800

    Merge remote-tracking branch 'gh/main' into feat/rltl-rstest

commit 1f51a70
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Wed Aug 6 21:03:31 2025 +0800

    fix: snapshot

commit 76872a4
Merge: 095bc28 0eeae9d
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Wed Aug 6 21:00:19 2025 +0800

    Merge remote-tracking branch 'gh/main' into feat/rltl-rstest

commit 095bc28
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Wed Aug 6 20:56:49 2025 +0800

    feat: remove enableDefine and use lynx.config to define __ALOG__

commit 9d8bd7c
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Wed Aug 6 20:53:33 2025 +0800

    feat: use getRspeedyAPI and remove applyStubRspeedyAPI

commit b898c19
Merge: e884c07 6baeb9f
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Wed Aug 6 15:47:53 2025 +0800

    Merge remote-tracking branch 'gh/main' into feat/rltl-rstest

commit e884c07
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Mon Aug 4 10:44:41 2025 +0800

    fix: remove test.only

commit b5567fa
Merge: 34bd921 8e6321a
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Mon Aug 4 10:45:30 2025 +0800

    Merge branch 'main' into feat/rltl-rstest

commit 34bd921
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Sat Aug 2 00:21:42 2025 +0800

    feat: add test cases for callerName: rstest

commit 37ccc68
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Fri Aug 1 23:51:31 2025 +0800

    feat: add applyStubRspeedyAPI

commit 37cd1c8
Merge: 8863f55 22ca433
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Fri Aug 1 22:45:43 2025 +0800

    Merge remote-tracking branch 'gh/main' into feat/rltl-rstest

commit 8863f55
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Fri Aug 1 22:08:53 2025 +0800

    fix: cr

commit cf78e1a
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Wed Jul 30 17:51:42 2025 +0800

    chore: changeset

commit 0d4e0c9
Merge: bfdebd0 a4ee4fd
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Wed Jul 30 16:49:08 2025 +0800

    Merge remote-tracking branch 'gh/main' into feat/rltl-rstest

commit bfdebd0
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Wed Jul 30 16:48:09 2025 +0800

    feat: remove layer from testing rules

commit 4591409
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Wed Jul 30 15:35:44 2025 +0800

    Update .changeset/red-lamps-arrive.md

    Co-authored-by: Zhiyuan Hong <28915578+hzy@users.noreply.github.com>
    Signed-off-by: Yiming Li <yimingli.cs@gmail.com>

commit fc20380
Merge: b9c1ca2 343cedb
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Fri Jul 25 15:29:13 2025 +0800

    Merge remote-tracking branch 'gh/main' into feat/rltl-rstest

commit b9c1ca2
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Fri Jul 25 15:18:16 2025 +0800

    fix: cr

commit 2300227
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Thu Jul 24 20:20:50 2025 +0800

    docs: update changeset

commit 6d0d454
Merge: fe86acd 3788b61
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Thu Jul 24 19:29:31 2025 +0800

    Merge branch 'main' into feat/rltl-rstest

commit fe86acd
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Thu Jul 24 17:30:30 2025 +0800

    fix: cr

commit a769bc5
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Thu Jul 24 17:29:10 2025 +0800

    chore: pnpm dedupe

commit 1163c32
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Thu Jul 24 17:24:09 2025 +0800

    feat: using callerName and reuse lynx.config for rstest

commit b391cb8
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Thu Jul 24 16:07:41 2025 +0800

    feat: keep the `createVitestConfig` API

commit 000961d
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Thu Jul 24 14:58:17 2025 +0800

    fix: use cjs for polyfill

commit df4d0a3
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Thu Jul 24 14:51:00 2025 +0800

    chore: use catalog for rstest version

commit fea9d67
Merge: 04cbe34 a6230e2
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Thu Jul 24 14:45:14 2025 +0800

    Merge remote-tracking branch 'gh/main' into feat/rltl-rstest

commit 04cbe34
Merge: dae4616 16a3ccb
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Fri Jul 18 23:48:43 2025 +0800

    Merge branch 'main' into feat/rltl-rstest

commit dae4616
Author: Yiming <yimingli.cs@gmail.com>
Date:   Fri Jul 18 23:47:07 2025 +0800

    chore: update changeset

commit 5b45cfb
Author: Yiming <yimingli.cs@gmail.com>
Date:   Fri Jul 18 17:27:52 2025 +0800

    feat: update snapshot

commit a0a21b6
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Fri Jul 18 17:05:11 2025 +0800

    fix coderabbitai cr

commit 9a44a9a
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Fri Jul 18 16:51:32 2025 +0800

    feat: add rstest template

commit c51a15a
Author: Yiming <yimingli.cs@gmail.com>
Date:   Fri Jul 18 16:43:18 2025 +0800

    chore: add testTimeout for rstest

commit d3dce4a
Author: Yiming <yimingli.cs@gmail.com>
Date:   Fri Jul 18 16:39:50 2025 +0800

    fix: rstest setup

commit d8a0221
Merge: dc74726 7eb5c36
Author: Yiming <yimingli.cs@gmail.com>
Date:   Fri Jul 18 15:05:25 2025 +0800

    Merge branch 'feat/rltl-rstest' of github.com:upupming/lynx-stack into feat/rltl-rstest

commit dc74726
Author: Yiming <yimingli.cs@gmail.com>
Date:   Fri Jul 18 15:05:07 2025 +0800

    fix: setup file order in vitest

commit fe0fd93
Author: Yiming <yimingli.cs@gmail.com>
Date:   Fri Jul 18 14:19:42 2025 +0800

    feat: pre-bundled @lynx-js/testing-environment should shared between vitest and rstest

commit 7eb5c36
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Fri Jul 18 14:02:03 2025 +0800

    fix: enableTestingLibrary passing to ReactWebpackPlugin

commit f4a9651
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Fri Jul 18 13:54:19 2025 +0800

    feat: add template to create-rspeedy

commit 410e1c9
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Fri Jul 18 11:34:59 2025 +0800

    fix: use `enableTestingLibrary` instead of process.env.NODE_ENV to avoid breaking current tests

commit a0f2275
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Thu Jul 17 22:17:00 2025 +0800

    fix: api

commit 2442e36
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Thu Jul 17 22:08:32 2025 +0800

    fix: unused Console type

commit 854e2f1
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Thu Jul 17 21:46:15 2025 +0800

    fix: global.console in rstest cannot be modify

commit 852025f
Merge: af8a651 6af75c1
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Thu Jul 17 21:45:02 2025 +0800

    Merge remote-tracking branch 'gh/main' into feat/rltl-rstest

commit af8a651
Author: Yiming Li <yimingli.cs@gmail.com>
Date:   Thu Jul 17 21:05:01 2025 +0800

    feat: support rstest in testing library
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 10, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds rstest support across the repo: new rstest configs/adapters, test loaders, environment refactor (LynxTestingEnv now accepts a {window} env), create-rspeedy rstest templates, many test snapshot updates, and CI to run rstest alongside Vitest.

Changes

Cohort / File(s) Summary
Changesets
\.changeset/easy-waves-pump.md, \.changeset/ninety-pants-tease.md, \.changeset/red-lamps-arrive.md, \.changeset/fair-plums-share.md
New changeset entries documenting rstest support, templates, adapter, and LynxTestingEnv API change.
CI / Workflows
.github/workflows/test.yml
Adds test-rstest job and regression run for rstest templates; done depends on test-rstest.
Workspace & dependencies
pnpm-workspace.yaml, package.json, packages/*/package.json
Adds @rstest/core catalog entry and devDeps/scripts across multiple packages; updates exports for rstest subpaths.
Testing environment core
packages/testing-library/testing-environment/src/index.ts, .../etc/testing-environment.api.md, .../src/env/vitest/index.ts, .../src/env/rstest/index.ts, .../src/setupFiles/rstest.js
Introduces LynxEnv interface, installLynxTestingEnv/uninstallLynxTestingEnv, switches runtime to use env.window, and adds rstest env wiring.
React testing-library: rstest integration
packages/react/testing-library/src/rstest-adapter.ts, packages/react/testing-library/rstest.config.ts, packages/react/testing-library/src/env/rstest.ts, packages/react/testing-library/src/env/index.ts
Adds withLynxConfig adapter to produce rstest config, new rstest config file and env bootstrap; re-exports env helpers.
Plugins & Vitest refactor
packages/react/testing-library/src/plugins/vitest.ts, packages/react/testing-library/src/plugins/index.ts, packages/react/testing-library/src/vitest.config.ts, packages/react/testing-library/types/vitest-config.d.ts
Reworks plugin API: introduces testingLibraryPlugin and TestingLibraryOptions, moves config into plugin hooks, adjusts types/exports.
Setup files & serializers
packages/react/testing-library/src/setupFiles/*, packages/react/testing-library/src/setupFiles/inner/*, packages/react/testing-library/src/setupFiles/rstest.js, packages/react/testing-library/src/setupFiles/vitest.js
Adds vitest/rstest setup entries, snapshot serializers, and injection hooks for main/background globals.
Testing loaders & webpack plugin
packages/webpack/react-webpack-plugin/src/loaders/testing.ts, packages/webpack/react-webpack-plugin/src/ReactWebpackPlugin.ts, packages/webpack/react-webpack-plugin/src/loaders/options.ts, packages/webpack/react-webpack-plugin/etc/react-webpack-plugin.api.md
Adds new TESTING loader, testingLoader implementation, exposes loader constants and extends static loaders map.
Rspeedy plugin changes
packages/rspeedy/plugin-react/src/loaders.ts, packages/rspeedy/plugin-react/src/pluginReactLynx.ts, packages/rspeedy/plugin-react/src/rspeedy-api.ts, packages/rspeedy/plugin-react/test/config.test.ts
Refactors loader options into helper, adds applyTestingLoaders and caller-aware branching (isRstest), conditional CSS application, and new rspeedy API helper + tests.
Create-rspeedy templates & generator
packages/rspeedy/create-rspeedy/src/index.ts, packages/rspeedy/create-rspeedy/template-react-rstest-rltl-*/**
Adds JS/TS rstest templates (configs, App, tests), and changes generator prompt to single-select testing framework.
Examples & polyfills
packages/testing-library/examples/*, packages/react/testing-library/vitest-polyfill.cjs, packages/testing-library/testing-environment/vitest-polyfill.cjs, packages/testing-library/examples/*/vitest-polyfill.cjs
Adds rstest configs/scripts to examples and vitest ↔ rstest polyfills mapping virs.
Tests & snapshots
packages/react/testing-library/src/__tests__/*
Widespread snapshot updates, added vitest imports (vi/beforeAll), conditional assertions for RSTEST, and minor test refactors.
Runtime adjustments
packages/react/testing-library/src/pure.jsx, packages/react/testing-library/rslib.config.ts, packages/react/testing-library/src/setupFiles/common/runtime-setup.js
Switches document access to lynxTestingEnv.env.window, updates rslib entries and d.ts emission, adjusts runtime injection behavior.
Testing-environment build/config
packages/testing-library/testing-environment/tsconfig.json, packages/testing-library/testing-environment/rstest.config.ts
Sets outDir/declarationDir, adds rstest config for testing-environment package.
Minor/auxiliary edits
assorted vitest.config.* changes, tsconfig libs, small package.json/script edits across examples and packages
Removes some await usages around createVitestConfig, adds DOM lib, updates scripts.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • Yradex
  • hzy
  • colinaaa
  • luhc228

Poem

🐰 I hopped in with a patch and a test,

rstest arrived, my nose at its best.
Loaders and envs stitched snug and neat,
Snapshots twitched their little feet.
Two runners now dance — what a treat! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: support rstest in testing library' directly describes the main change: adding rstest support to the testing library. It is clear, concise, and accurately reflects the primary objective of the PR.
Linked Issues check ✅ Passed The PR implements rstest support for ReactLynx Testing Library as specified in #1300, including the rstest-adapter with withLynxConfig(), configuration files, setup files, test environment integration, and comprehensive test updates across multiple packages.
Out of Scope Changes check ✅ Passed All changes are directly related to adding rstest support: new rstest configuration files, setup modules, test environment updates, plugin additions, and test adjustments. Additional changes to vitest configs and examples are supportive of the rstest implementation objective.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/rstest-rltl

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@upupming upupming marked this pull request as draft March 10, 2026 17:31
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
packages/rspeedy/create-rspeedy/src/index.ts (1)

113-127: ⚠️ Potential issue | 🟠 Major

mapESLintTemplate() always picks the TS template for react-*.

Line 114 matches on templateName.startsWith(template), but both Template entries use template: 'react', so find() always returns the first item (lang: 'ts'). That makes react-js, react-vitest-rltl-js, and react-rstest-rltl-js resolve to react-ts, which will scaffold the wrong ESLint template for JS projects.

Proposed fix
   mapESLintTemplate(templateName) {
-    const lang = TEMPLATES.find(({ template }) =>
-      templateName.startsWith(template)
-    )?.lang
+    const match = templateName.match(/-(js|ts)$/)
+    const lang = match?.[1] as LANG | undefined
 
     if (!lang) return null
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/rspeedy/create-rspeedy/src/index.ts` around lines 113 - 127,
mapESLintTemplate incorrectly uses TEMPLATES.find(({ template }) =>
templateName.startsWith(template)) which always returns the first 'react' entry
(ts); update mapESLintTemplate to match the full template identifier rather than
a prefix. Specifically, change the find predicate to compare equality
(templateName === template) or otherwise select the most specific template
(e.g., sort TEMPLATES by template.length desc before find) so entries like
'react-js' resolve to the 'js' lang; keep references to the existing
mapESLintTemplate function and the TEMPLATES array when making the change.
packages/react/testing-library/src/__tests__/lazy-bundle/index.test.jsx (1)

309-356: ⚠️ Potential issue | 🟡 Minor

Normalize the __RSTEST__ predicate.

Lines 25 and 58 treat a falsy __RSTEST__ as “not rstest”, but Lines 309 and 355 only special-case undefined. If the flag is ever injected as false, this test will take the non-rstest branch above and silently skip the teardown assertions here.

♻️ Suggested cleanup
 const require = createRequire(import.meta.url);
+const isRstest = typeof __RSTEST__ !== 'undefined' && __RSTEST__;

 function LazyComponentLoader({ url }) {
   const ExternalComponent = lazy(() => import(url));
   const InternalComponent = lazy(() => import('./LazyComponent'));
@@
-      {(typeof __RSTEST__ !== 'undefined' && __RSTEST__) ? null : <ExternalComponent />}
+      {isRstest ? null : <ExternalComponent />}
@@
-    if (typeof __RSTEST__ !== 'undefined' && __RSTEST__) {
+    if (isRstest) {
@@
-        if (typeof __RSTEST__ === 'undefined') {
+        if (!isRstest) {
@@
-        if (typeof __RSTEST__ === 'undefined') {
+        if (!isRstest) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react/testing-library/src/__tests__/lazy-bundle/index.test.jsx`
around lines 309 - 356, The test currently checks typeof __RSTEST__ ===
'undefined' in some branches but uses a different falsy check elsewhere; make
the predicate consistent by treating any falsy __RSTEST__ as "not rstest" (e.g.,
replace typeof __RSTEST__ === 'undefined' with if (!__RSTEST__) in the test
file) so both the branch guarding the tearDownInstances assertions and the other
branches use the same check; update occurrences referencing __RSTEST__ (and keep
assertions on tearDownInstances unchanged) to use the unified !__RSTEST__
predicate.
packages/react/testing-library/src/plugins/vitest.ts (2)

74-93: ⚠️ Potential issue | 🟠 Major

Honor runtimePkgName in the React aliases.

When runtimePkgName !== '@lynx-js/react', the transform already rewrites generated imports to the custom runtime, but react, react/jsx-runtime, and react/jsx-dev-runtime are still hard-coded to @lynx-js/react. That mixes two runtimes in one test build and makes runtimePkgName incomplete for projects importing from react.

♻️ Suggested fix
   const reactAlias = [
     {
       find: /^react$/,
-      replacement: require.resolve(runtimeOSSPkgName, {
+      replacement: require.resolve(runtimePkgName, {
         paths: [runtimeDir, __dirname],
       }),
     },
     {
       find: /^react\/jsx-runtime$/,
-      replacement: require.resolve(path.posix.join(runtimeOSSPkgName, 'jsx-runtime'), {
+      replacement: require.resolve(path.posix.join(runtimePkgName, 'jsx-runtime'), {
         paths: [runtimeDir, __dirname],
       }),
     },
     {
       find: /^react\/jsx-dev-runtime$/,
-      replacement: require.resolve(path.posix.join(runtimeOSSPkgName, 'jsx-dev-runtime'), {
+      replacement: require.resolve(path.posix.join(runtimePkgName, 'jsx-dev-runtime'), {
         paths: [runtimeDir, __dirname],
       }),
     },
   ];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react/testing-library/src/plugins/vitest.ts` around lines 74 - 93,
The reactAlias array currently resolves replacements using runtimeOSSPkgName,
which hard-codes `@lynx-js/react`; update the three alias entries in reactAlias to
use runtimePkgName instead of runtimeOSSPkgName (and use
path.posix.join(runtimePkgName, 'jsx-runtime') / 'jsx-dev-runtime' for those
two) so that imports for 'react', 'react/jsx-runtime', and
'react/jsx-dev-runtime' are redirected to the configured runtimePkgName (keep
existing require.resolve calls and paths array with runtimeDir and __dirname).

141-168: ⚠️ Potential issue | 🟠 Major

Move dependency resolution to configResolved hook and return a partial config instead of mutating input.

The config() hook receives raw, unresolved configuration. Vitest's test.alias can be either an object or an array; calling .push() on line 164 assumes it's an array and will fail if it's configured as an object. Additionally, config.root may not be set when config() runs. Use config() to return a partial test config with the alias, and move the dependency resolution (lines 142, 166–168) to the configResolved() hook for accessing the finalized config. The transformReactLynxPlugin in this file demonstrates the correct pattern (lines 293–308).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react/testing-library/src/plugins/vitest.ts` around lines 141 - 168,
The config() hook currently mutates the incoming config and assumes test.alias
is an array and config.root is set; instead return a partial test config that
includes the reactCompilerRuntimeAlias (do not call .push on config.test) and
move dependency resolution and require logic to configResolved(). Concretely: in
the config() implementation build reactCompilerRuntimeAlias (same regex and
replacement logic) but return { test: { alias: reactCompilerRuntimeAlias } }
rather than mutating config; then implement configResolved(resolvedConfig) to
set rootContext = resolvedConfig.root, call compilerDeps =
resolveCompilerDeps(rootContext), extract babelPath and require babel there
(using the same babelPath symbol), and avoid touching config.test there. Use the
transformReactLynxPlugin pattern for guidance.
🧹 Nitpick comments (6)
packages/testing-library/examples/basic/src/__tests__/index.test.tsx (1)

12-17: Consider adding type safety for the rstest global.

The rstest global isn't recognized by TypeScript. For consistency with the existing @ts-expect-error pattern on line 6 and strict TypeScript compliance, consider adding a type annotation or suppression comment.

♻️ Suggested improvement
-let fn;
-if (typeof rstest !== 'undefined') {
-  fn = rstest.fn;
-} else {
-  fn = vi.fn;
-}
+// `@ts-expect-error` rstest global is injected by rstest runner
+const fn = typeof rstest !== 'undefined' ? rstest.fn : vi.fn;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/testing-library/examples/basic/src/__tests__/index.test.tsx` around
lines 12 - 17, The test references the untyped global rstest when assigning fn
(using rstest.fn or vi.fn), causing TypeScript errors; fix by adding a local
type declaration or suppression for rstest before its use — for example add a
single-line declaration like "declare const rstest: any;" at the top of the test
file (or a narrower type such as "declare const rstest: { fn: typeof vi.fn } |
undefined;"), or place a targeted "// `@ts-expect-error`" immediately above the
rstest access to silence the error while keeping the existing fn assignment
logic (affecting the rstest, fn, and vi.fn usage).
packages/react/testing-library/src/__tests__/list.test.jsx (1)

483-569: Drop the second identical snapshot assertion.

There’s no state change between Line 395 and Line 483, so this block is a verbatim duplicate of the previous expect(list).toMatchInlineSnapshot(...). Keeping both just doubles snapshot churn when the list shape changes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react/testing-library/src/__tests__/list.test.jsx` around lines 483
- 569, Remove the duplicated inline snapshot assertion: there are two identical
expect(list).toMatchInlineSnapshot(...) calls; delete the second occurrence (the
block starting with expect(list).toMatchInlineSnapshot that reproduces the same
snapshot shown) so only the original snapshot assertion remains and snapshot
churn is avoided.
packages/rspeedy/plugin-react/test/config.test.ts (1)

2520-2531: Move async setup into beforeAll for cleaner test structure.

The current pattern initializes rsbuild and config at the describe block level using top-level await. While this works, using beforeAll is more conventional and makes the test setup explicit:

describe('callerName: rstest', () => {
  let config: Awaited<ReturnType<RsbuildInstance['initConfigs']>>[0];
  let rules: Rule[] | undefined;

  beforeAll(async () => {
    const { pluginReactLynx } = await import('../src/pluginReactLynx.js');
    const rsbuild = await createRspeedy({
      rspeedyConfig: { plugins: [pluginReactLynx()] },
      callerName: 'rstest',
    });
    [config] = await rsbuild.initConfigs();
    rules = config?.module?.rules as Rule[] | undefined;
  });
  // tests...
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/rspeedy/plugin-react/test/config.test.ts` around lines 2520 - 2531,
The test currently performs async initialization at the describe-top level; move
that setup into a beforeAll to make tests deterministic and cleaner: import
pluginReactLynx, create the rsbuild via createRspeedy, call
rsbuild.initConfigs() and assign the first item to config inside a beforeAll,
then extract rules from config.module.rules into a top-level let-bound variable
for the describe block; reference the pluginReactLynx import, createRspeedy
call, rsbuild.initConfigs invocation, the config variable and rules extraction
when making the change.
packages/rspeedy/plugin-react/src/pluginReactLynx.ts (1)

348-361: Consider consolidating the rstest conditional blocks.

The rstest-specific logic is split across multiple conditional blocks. While functionally correct, consolidating could improve readability:

if (isRstest) {
  applyRstest(api)
  applyTestingLoaders(api, resolvedOptions)
} else {
  applyCSS(api, resolvedOptions)
  applyLoaders(api, resolvedOptions)
}

This would make the rstest vs non-rstest code paths more explicit and easier to follow.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/rspeedy/plugin-react/src/pluginReactLynx.ts` around lines 348 - 361,
The code splits rstest behavior across multiple conditionals which reduces
readability; refactor the block around the isRstest flag in pluginReactLynx.ts
to use a single if/else: when isRstest is true call applyRstest(api) and
applyTestingLoaders(api, resolvedOptions); otherwise call applyCSS(api,
resolvedOptions) and applyLoaders(api, resolvedOptions); keep the other
unconditional calls (applyEntry, applyBackgroundOnly, applyGenerator) in place
and do not change their order.
packages/react/testing-library/src/env/rstest.ts (1)

3-8: Consider adding type declarations for global properties.

The @ts-ignore suppresses type errors for the custom global properties. While functional, adding type augmentation would improve type safety and IDE support.

♻️ Optional: Add type declarations

Create or extend a global type declaration:

declare global {
  var jsdom: { window: typeof window };
  var lynxTestingEnv: import('./index.js').LynxTestingEnv;
}

Then the @ts-ignore can be removed:

-// `@ts-ignore`
 global.jsdom = {
   window,
 };
 const lynxTestingEnv = new LynxTestingEnv();
 global.lynxTestingEnv = lynxTestingEnv;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react/testing-library/src/env/rstest.ts` around lines 3 - 8, Add
proper TypeScript global augmentations instead of using `@ts-ignore`: declare
global with var jsdom: { window: typeof window } and var lynxTestingEnv:
import('./index.js').LynxTestingEnv (or point to the LynxTestingEnv type), place
this in a .d.ts or at top of the module so the compiler knows the shapes, then
remove the // `@ts-ignore` and keep the assignments to global.jsdom and
global.lynxTestingEnv as-is; reference the LynxTestingEnv type from index.js to
ensure correct typing.
packages/react/testing-library/src/setupFiles/inner/rstest.js (1)

18-20: Unused callback parameter in requireModuleAsync stub.

The callback parameter is declared but never used since the function throws immediately. Consider removing it or, if the signature must match the real API for type compatibility, prefix with underscore to indicate intentional non-use.

♻️ Suggested fix
-  target.lynx.requireModuleAsync = async (url, callback) => {
+  target.lynx.requireModuleAsync = async (url, _callback) => {
     throw new Error('lynx.requireModuleAsync not implemented for rstest');
   };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react/testing-library/src/setupFiles/inner/rstest.js` around lines
18 - 20, The stub function target.lynx.requireModuleAsync declares an unused
parameter callback; either remove the parameter from the function signature or,
if you must preserve the API shape for compatibility, rename it to _callback (or
_callback) to indicate intentional non-use and silence linters — update the
function declaration for requireModuleAsync accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/test.yml:
- Around line 210-215: The scaffold command is being run from inside the
previously created create-rspeedy-regression-vitest-rltl directory, causing the
new create-rspeedy-regression-rstest-rltl project to be nested and possibly
inherit parent config; fix by creating and switching to a fresh temporary
directory (e.g., mktemp -d or similar) before running the npx
create-rspeedy-canary@latest ... --dir create-rspeedy-regression-rstest-rltl
sequence, run pnpm install/build/test there, and then optionally cd back to the
original directory so the test runs operate on an isolated fresh app rather than
a child of create-rspeedy-regression-vitest-rltl.

In `@packages/react/testing-library/.npmignore`:
- Around line 2-3: The .npmignore currently attempts to un-ignore contents with
patterns '!dist/**/*' and '!types/*' but leaves the parent directories ignored
by the top-level '*' rule; update the file to explicitly un-ignore the
directories themselves before their contents (e.g., add patterns to un-ignore
'dist' and 'types' such as '!dist/' and '!types/' and keep or add recursive
content patterns like '!dist/**/*' and '!types/**/*') so npm will include the
dist/ and types/ directories and their files when publishing.

In `@packages/react/testing-library/src/__tests__/css/index.test.jsx`:
- Around line 37-38: Update the inline comment above the assertion for
style3.baz to correct the typo "an string" to "a string" so it reads "to be a
string"; the test assertion itself (expect(style3.baz).toBeTypeOf('string'))
remains unchanged—just edit the comment near the expect call referencing
style3.baz.

In `@packages/react/testing-library/src/__tests__/lazy-bundle/index.test.jsx`:
- Line 25: The test was weakened for rstest by short-circuiting the external
lazy import via the conditional around ExternalComponent (the __RSTEST__ check),
changing assertions to accept the smaller tree, and removing delayed tearDown
checks; restore the original behavior by removing the conditional that bypasses
<ExternalComponent /> when __RSTEST__ is defined (so the external lazy(() =>
import(url)) case runs), revert the assertions in the block that was changed
(the assertion updates around the smaller tree) back to the original
expectations, and re-enable the delayed teardown/snapshot cleanup checks that
were removed; if running the external bundle is impossible in rstest, explicitly
mark the affected tests as skipped or TODO (using test.skip or a clear TODO
comment) so the limitation is visible instead of silently weakening the test.

In `@packages/react/testing-library/src/env/vitest.ts`:
- Around line 7-21: The setup currently creates fakeGlobal and calls
builtinEnvironments.jsdom.setup without capturing its return value, constructs
LynxTestingEnv without the jsdom instance, and doesn't expose Node; fix by
capturing the jsdom setup result (e.g., const jsdomTeardown = await
builtinEnvironments.jsdom.setup(fakeGlobal, {})), pass fakeGlobal.jsdom into the
LynxTestingEnv constructor when instantiating LynxTestingEnv, set global.Node =
fakeGlobal.jsdom.window.Node, and in the returned teardown call the captured
jsdomTeardown (if present) before deleting global.lynxTestingEnv and
global.jsdom so the builtin jsdom teardown is chained and cleanup is complete.

In `@packages/react/testing-library/src/setupFiles/common/runtime-setup.js`:
- Around line 156-159: The code temporarily replaces globalThis.lynxCoreInject
with target.lynxCoreInject and calls injectTt(), but if injectTt() throws the
original value isn't restored; wrap the assignment and call in a try...finally
so that oldLynxCoreInject is always restored in the finally block (use the
existing oldLynxCoreInject variable), ensuring globalThis.lynxCoreInject is
reset even on exceptions from injectTt().

In
`@packages/rspeedy/create-rspeedy/template-react-rstest-rltl-js/rstest.config.js`:
- Around line 7-8: The ESM config uses require.resolve() directly which is
undefined; import createRequire from 'module' using
createRequire(import.meta.url) and replace
require.resolve('@lynx-js/react/testing-library/setupFiles/rstest') with
requireInstance.resolve('@lynx-js/react/testing-library/setupFiles/rstest') so
the setupFiles entry resolves correctly in rstest.config.js (locate the
setupFiles array and the require.resolve call to update).

In
`@packages/rspeedy/create-rspeedy/template-react-rstest-rltl-js/src/__tests__/index.test.jsx`:
- Around line 74-79: The test snapshot in src/__tests__/index.test.jsx
incorrectly references "src/App.tsx" (TypeScript) for the JS scaffold; update
the snapshot string to "src/App.jsx" (or regenerate the snapshot) so the Edit
hint and expectations match the JS template, and verify the template files
(App.jsx) and the test's expected markup (the <text> element containing the file
path) are consistent.

In `@packages/rspeedy/create-rspeedy/template-react-rstest-rltl-js/src/App.jsx`:
- Around line 37-45: The scaffold hint currently points to the wrong file name;
update the string inside the nested <text> element (the one rendered under <text
className='Hint'> in App.jsx) from " src/App.tsx " to " src/App.jsx " so the UI
correctly directs users to the generated file (change the literal text content
inside that nested <text> element).

In `@packages/rspeedy/plugin-react/src/loaders.ts`:
- Around line 35-46: getLoaderOptions is not including the engineVersion from
its Required<PluginReactLynxOptions> param in the returned options object,
causing snapshots to miss engineVersion; update the function to destructure
engineVersion from the parameters and add engineVersion to the returned object
alongside compat, enableRemoveCSSScope, isDynamicComponent,
inlineSourcesContent, defineDCE and conditional shake so the returned shape
matches tests (refer to getLoaderOptions and the returned object currently
containing compat, enableRemoveCSSScope, isDynamicComponent,
inlineSourcesContent, defineDCE, and conditional shake).

In `@packages/rspeedy/plugin-react/src/rstest.ts`:
- Around line 7-13: The current api.modifyRsbuildConfig callback overwrites
config.output.externals and loses any existing externals; update the handler in
the modifyRsbuildConfig callback to read config.output?.externals, normalize it
to an array (wrap non-array values), append the /^node:/ regexp, and then call
mergeRsbuildConfig with the original config followed by the new output.externals
array so you preserve prior externals while adding the node: matcher.

---

Outside diff comments:
In `@packages/react/testing-library/src/__tests__/lazy-bundle/index.test.jsx`:
- Around line 309-356: The test currently checks typeof __RSTEST__ ===
'undefined' in some branches but uses a different falsy check elsewhere; make
the predicate consistent by treating any falsy __RSTEST__ as "not rstest" (e.g.,
replace typeof __RSTEST__ === 'undefined' with if (!__RSTEST__) in the test
file) so both the branch guarding the tearDownInstances assertions and the other
branches use the same check; update occurrences referencing __RSTEST__ (and keep
assertions on tearDownInstances unchanged) to use the unified !__RSTEST__
predicate.

In `@packages/react/testing-library/src/plugins/vitest.ts`:
- Around line 74-93: The reactAlias array currently resolves replacements using
runtimeOSSPkgName, which hard-codes `@lynx-js/react`; update the three alias
entries in reactAlias to use runtimePkgName instead of runtimeOSSPkgName (and
use path.posix.join(runtimePkgName, 'jsx-runtime') / 'jsx-dev-runtime' for those
two) so that imports for 'react', 'react/jsx-runtime', and
'react/jsx-dev-runtime' are redirected to the configured runtimePkgName (keep
existing require.resolve calls and paths array with runtimeDir and __dirname).
- Around line 141-168: The config() hook currently mutates the incoming config
and assumes test.alias is an array and config.root is set; instead return a
partial test config that includes the reactCompilerRuntimeAlias (do not call
.push on config.test) and move dependency resolution and require logic to
configResolved(). Concretely: in the config() implementation build
reactCompilerRuntimeAlias (same regex and replacement logic) but return { test:
{ alias: reactCompilerRuntimeAlias } } rather than mutating config; then
implement configResolved(resolvedConfig) to set rootContext =
resolvedConfig.root, call compilerDeps = resolveCompilerDeps(rootContext),
extract babelPath and require babel there (using the same babelPath symbol), and
avoid touching config.test there. Use the transformReactLynxPlugin pattern for
guidance.

In `@packages/rspeedy/create-rspeedy/src/index.ts`:
- Around line 113-127: mapESLintTemplate incorrectly uses TEMPLATES.find(({
template }) => templateName.startsWith(template)) which always returns the first
'react' entry (ts); update mapESLintTemplate to match the full template
identifier rather than a prefix. Specifically, change the find predicate to
compare equality (templateName === template) or otherwise select the most
specific template (e.g., sort TEMPLATES by template.length desc before find) so
entries like 'react-js' resolve to the 'js' lang; keep references to the
existing mapESLintTemplate function and the TEMPLATES array when making the
change.

---

Nitpick comments:
In `@packages/react/testing-library/src/__tests__/list.test.jsx`:
- Around line 483-569: Remove the duplicated inline snapshot assertion: there
are two identical expect(list).toMatchInlineSnapshot(...) calls; delete the
second occurrence (the block starting with expect(list).toMatchInlineSnapshot
that reproduces the same snapshot shown) so only the original snapshot assertion
remains and snapshot churn is avoided.

In `@packages/react/testing-library/src/env/rstest.ts`:
- Around line 3-8: Add proper TypeScript global augmentations instead of using
`@ts-ignore`: declare global with var jsdom: { window: typeof window } and var
lynxTestingEnv: import('./index.js').LynxTestingEnv (or point to the
LynxTestingEnv type), place this in a .d.ts or at top of the module so the
compiler knows the shapes, then remove the // `@ts-ignore` and keep the
assignments to global.jsdom and global.lynxTestingEnv as-is; reference the
LynxTestingEnv type from index.js to ensure correct typing.

In `@packages/react/testing-library/src/setupFiles/inner/rstest.js`:
- Around line 18-20: The stub function target.lynx.requireModuleAsync declares
an unused parameter callback; either remove the parameter from the function
signature or, if you must preserve the API shape for compatibility, rename it to
_callback (or _callback) to indicate intentional non-use and silence linters —
update the function declaration for requireModuleAsync accordingly.

In `@packages/rspeedy/plugin-react/src/pluginReactLynx.ts`:
- Around line 348-361: The code splits rstest behavior across multiple
conditionals which reduces readability; refactor the block around the isRstest
flag in pluginReactLynx.ts to use a single if/else: when isRstest is true call
applyRstest(api) and applyTestingLoaders(api, resolvedOptions); otherwise call
applyCSS(api, resolvedOptions) and applyLoaders(api, resolvedOptions); keep the
other unconditional calls (applyEntry, applyBackgroundOnly, applyGenerator) in
place and do not change their order.

In `@packages/rspeedy/plugin-react/test/config.test.ts`:
- Around line 2520-2531: The test currently performs async initialization at the
describe-top level; move that setup into a beforeAll to make tests deterministic
and cleaner: import pluginReactLynx, create the rsbuild via createRspeedy, call
rsbuild.initConfigs() and assign the first item to config inside a beforeAll,
then extract rules from config.module.rules into a top-level let-bound variable
for the describe block; reference the pluginReactLynx import, createRspeedy
call, rsbuild.initConfigs invocation, the config variable and rules extraction
when making the change.

In `@packages/testing-library/examples/basic/src/__tests__/index.test.tsx`:
- Around line 12-17: The test references the untyped global rstest when
assigning fn (using rstest.fn or vi.fn), causing TypeScript errors; fix by
adding a local type declaration or suppression for rstest before its use — for
example add a single-line declaration like "declare const rstest: any;" at the
top of the test file (or a narrower type such as "declare const rstest: { fn:
typeof vi.fn } | undefined;"), or place a targeted "// `@ts-expect-error`"
immediately above the rstest access to silence the error while keeping the
existing fn assignment logic (affecting the rstest, fn, and vi.fn usage).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: eba85ea0-3457-42c3-98d7-badfef5d8d30

📥 Commits

Reviewing files that changed from the base of the PR and between 27f1cff and 582ffe8.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (72)
  • .changeset/easy-waves-pump.md
  • .changeset/ninety-pants-tease.md
  • .changeset/red-lamps-arrive.md
  • .github/workflows/test.yml
  • package.json
  • packages/react/package.json
  • packages/react/testing-library/.npmignore
  • packages/react/testing-library/package.json
  • packages/react/testing-library/rslib.config.ts
  • packages/react/testing-library/rstest.config.ts
  • packages/react/testing-library/src/__tests__/act.test.jsx
  • packages/react/testing-library/src/__tests__/alog.test.jsx
  • packages/react/testing-library/src/__tests__/auto-cleanup-skip.test.jsx
  • packages/react/testing-library/src/__tests__/cleanup.test.jsx
  • packages/react/testing-library/src/__tests__/css/index.test.jsx
  • packages/react/testing-library/src/__tests__/end-to-end.test.jsx
  • packages/react/testing-library/src/__tests__/lazy-bundle/index.test.jsx
  • packages/react/testing-library/src/__tests__/list.test.jsx
  • packages/react/testing-library/src/__tests__/lynx.test.jsx
  • packages/react/testing-library/src/__tests__/rerender.test.jsx
  • packages/react/testing-library/src/__tests__/worklet.test.jsx
  • packages/react/testing-library/src/env/index.ts
  • packages/react/testing-library/src/env/rstest.ts
  • packages/react/testing-library/src/env/vitest.ts
  • packages/react/testing-library/src/plugins/index.ts
  • packages/react/testing-library/src/plugins/vitest.ts
  • packages/react/testing-library/src/setupFiles/common/bootstrap.js
  • packages/react/testing-library/src/setupFiles/common/runtime-setup.js
  • packages/react/testing-library/src/setupFiles/inner/rstest.js
  • packages/react/testing-library/src/setupFiles/inner/vitest.js
  • packages/react/testing-library/src/setupFiles/rstest.js
  • packages/react/testing-library/src/setupFiles/vitest.js
  • packages/react/testing-library/src/vitest.config.ts
  • packages/react/testing-library/types/vitest-config.d.ts
  • packages/react/testing-library/vitest-polyfill.cjs
  • packages/react/testing-library/vitest.config.ts
  • packages/rspeedy/create-rspeedy/package.json
  • packages/rspeedy/create-rspeedy/src/index.ts
  • packages/rspeedy/create-rspeedy/template-react-rstest-rltl-js/lynx.config.js
  • packages/rspeedy/create-rspeedy/template-react-rstest-rltl-js/package.json
  • packages/rspeedy/create-rspeedy/template-react-rstest-rltl-js/rstest.config.js
  • packages/rspeedy/create-rspeedy/template-react-rstest-rltl-js/src/App.jsx
  • packages/rspeedy/create-rspeedy/template-react-rstest-rltl-js/src/__tests__/index.test.jsx
  • packages/rspeedy/create-rspeedy/template-react-rstest-rltl-js/src/index.jsx
  • packages/rspeedy/create-rspeedy/template-react-rstest-rltl-ts/lynx.config.ts
  • packages/rspeedy/create-rspeedy/template-react-rstest-rltl-ts/package.json
  • packages/rspeedy/create-rspeedy/template-react-rstest-rltl-ts/rstest.config.ts
  • packages/rspeedy/create-rspeedy/template-react-rstest-rltl-ts/src/App.tsx
  • packages/rspeedy/create-rspeedy/template-react-rstest-rltl-ts/src/__tests__/index.test.tsx
  • packages/rspeedy/create-rspeedy/template-react-rstest-rltl-ts/src/index.tsx
  • packages/rspeedy/create-rspeedy/template-react-rstest-rltl-ts/src/rspeedy-env.d.ts
  • packages/rspeedy/create-rspeedy/template-react-rstest-rltl-ts/tsconfig.json
  • packages/rspeedy/create-rspeedy/template-react-vitest-rltl-js/vitest.config.js
  • packages/rspeedy/create-rspeedy/template-react-vitest-rltl-ts/vitest.config.ts
  • packages/rspeedy/plugin-react/package.json
  • packages/rspeedy/plugin-react/src/loaders.ts
  • packages/rspeedy/plugin-react/src/pluginReactLynx.ts
  • packages/rspeedy/plugin-react/src/rspeedy-api.ts
  • packages/rspeedy/plugin-react/src/rstest.ts
  • packages/rspeedy/plugin-react/test/config.test.ts
  • packages/testing-library/examples/basic/package.json
  • packages/testing-library/examples/basic/rstest.config.ts
  • packages/testing-library/examples/basic/src/__tests__/index.test.tsx
  • packages/testing-library/examples/basic/src/rspeedy-env.d.ts
  • packages/testing-library/examples/basic/vitest.config.ts
  • packages/testing-library/testing-environment/src/index.ts
  • packages/use-sync-external-store/vitest.config.ts
  • packages/webpack/react-webpack-plugin/etc/react-webpack-plugin.api.md
  • packages/webpack/react-webpack-plugin/src/ReactWebpackPlugin.ts
  • packages/webpack/react-webpack-plugin/src/loaders/options.ts
  • packages/webpack/react-webpack-plugin/src/loaders/testing.ts
  • pnpm-workspace.yaml
💤 Files with no reviewable changes (1)
  • packages/react/testing-library/types/vitest-config.d.ts

Comment thread .github/workflows/test.yml Outdated
Comment thread packages/react/testing-library/.npmignore
Comment thread packages/react/testing-library/src/__tests__/css/index.test.jsx Outdated
Comment thread packages/react/testing-library/src/__tests__/lazy-bundle/index.test.jsx Outdated
Comment thread packages/react/testing-library/src/env/vitest.ts
Comment thread packages/rspeedy/create-rspeedy/template-react-rstest-rltl-js/rstest.config.js Outdated
Comment thread packages/rspeedy/plugin-react/src/loaders.ts
Comment thread packages/rspeedy/plugin-react/src/rstest.ts Outdated
@relativeci
Copy link
Copy Markdown

relativeci Bot commented Mar 10, 2026

Web Explorer

#8803 Bundle Size — 748.66KiB (0%).

527ed7c(current) vs fd0cc6e main#8801(baseline)

Bundle metrics  Change 1 change
                 Current
#8803
     Baseline
#8801
No change  Initial JS 44.27KiB 44.27KiB
No change  Initial CSS 2.16KiB 2.16KiB
No change  Cache Invalidation 0% 0%
No change  Chunks 8 8
No change  Assets 10 10
Change  Modules 148(+1.37%) 146
No change  Duplicate Modules 11 11
No change  Duplicate Code 35.03% 35.03%
No change  Packages 3 3
No change  Duplicate Packages 0 0
Bundle size by type  no changes
                 Current
#8803
     Baseline
#8801
No change  Other 401.63KiB 401.63KiB
No change  JS 344.87KiB 344.87KiB
No change  CSS 2.16KiB 2.16KiB

Bundle analysis reportBranch feat/rstest-rltlProject dashboard


Generated by RelativeCIDocumentationReport issue

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Mar 10, 2026

Merging this PR will degrade performance by 26.68%

⚡ 2 improved benchmarks
❌ 2 regressed benchmarks
✅ 77 untouched benchmarks
⏩ 21 skipped benchmarks1

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
002-hello-reactLynx-destroyBackground 681.8 µs 929.9 µs -26.68%
transform 1000 view elements 54.5 ms 42.4 ms +28.79%
basic-performance-scroll-view-100 8.1 ms 8.7 ms -6.74%
basic-performance-div-1000 35.3 ms 26.3 ms +34.35%

Comparing feat/rstest-rltl (527ed7c) with main (edf9b3b)2

Open in CodSpeed

Footnotes

  1. 21 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on main (fd0cc6e) during the generation of this report, so edf9b3b was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Mar 11, 2026

🦋 Changeset detected

Latest commit: 527ed7c

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

This PR includes changesets to release 9 packages
Name Type
@lynx-js/react-webpack-plugin Patch
@lynx-js/react-rsbuild-plugin Patch
@lynx-js/testing-environment Minor
create-rspeedy Patch
@lynx-js/react Patch
@lynx-js/react-alias-rsbuild-plugin Patch
@lynx-js/react-umd Patch
upgrade-rspeedy Patch
@lynx-js/rspeedy Patch

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

upupming and others added 4 commits March 11, 2026 22:38
<!--
  Thank you for submitting a pull request!

We appreciate the time and effort you have invested in making these
changes. Please ensure that you provide enough information to allow
others to review your pull request.

Upon submission, your pull request will be automatically assigned with
reviewers.

If you want to learn more about contributing to this project, please
visit:
https://github.com/lynx-family/lynx-stack/blob/main/CONTRIBUTING.md.
-->

<!-- The AI summary below will be auto-generated - feel free to replace
it with your own. -->

@coderabbitai summary


`@lynx-js/react/testing-library/rstest-adapter` will automatically load
your `lynx.config.ts` and apply the same configuration to rstest, so you
can keep your test environment consistent with your development
environment.

```ts
// rstest.config.ts
import { defineConfig } from '@rstest/core';
import { withLynxConfig } from '@lynx-js/react/testing-library/rstest-adapter';

export default defineConfig({
  extends: withLynxConfig(),
});
```

## Checklist

<!--- Check and mark with an "x" -->

- [ ] Tests updated (or not required).
- [ ] Documentation updated (or not required).
- [ ] Changeset added, and when a BREAKING CHANGE occurs, it needs to be
clearly marked (or not required).
<!--
  Thank you for submitting a pull request!

We appreciate the time and effort you have invested in making these
changes. Please ensure that you provide enough information to allow
others to review your pull request.

Upon submission, your pull request will be automatically assigned with
reviewers.

If you want to learn more about contributing to this project, please
visit:
https://github.com/lynx-family/lynx-stack/blob/main/CONTRIBUTING.md.
-->

<!-- The AI summary below will be auto-generated - feel free to replace
it with your own. -->

@coderabbitai summary

fix rstest lock version.


https://github.com/lynx-family/lynx-stack/actions/runs/23236933928/job/67543097691?pr=2328
## Checklist

<!--- Check and mark with an "x" -->

- [ ] Tests updated (or not required).
- [ ] Documentation updated (or not required).
- [ ] Changeset added, and when a BREAKING CHANGE occurs, it needs to be
clearly marked (or not required).
@upupming
Copy link
Copy Markdown
Collaborator Author

@codex

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Yiming Li <yimingli.cs@gmail.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c493518d47

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/react/testing-library/src/rstest-adapter.ts Outdated
Comment thread packages/react/package.json
Comment thread packages/webpack/react-webpack-plugin/src/loaders/testing.ts Outdated
upupming and others added 4 commits March 19, 2026 11:15
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Yiming Li <yimingli.cs@gmail.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Yiming Li <yimingli.cs@gmail.com>
…etup.js

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Yiming Li <yimingli.cs@gmail.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b5e918019a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/testing-library/testing-environment/src/index.ts
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b30dd8817a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/react/testing-library/src/vitest.config.ts
HuJean
HuJean previously approved these changes Apr 3, 2026
# Conflicts:
#	packages/react/testing-library/src/__tests__/alog.test.jsx
#	packages/react/testing-library/src/__tests__/list.test.jsx
#	packages/react/testing-library/src/setupFiles/common/runtime-setup.js
#	pnpm-lock.yaml
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6521e71ad1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/react/testing-library/src/setupFiles/common/runtime-setup.js Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6521e71ad1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/react/testing-library/src/setupFiles/common/runtime-setup.js Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5722509c55

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/testing-library/testing-environment/src/index.ts
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

1 similar comment
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 530cdb6d03

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/rspeedy/create-rspeedy/src/index.ts
Comment thread packages/rspeedy/create-rspeedy/template-react-rstest-rltl-js/rstest.config.js Outdated
@upupming upupming enabled auto-merge (squash) April 13, 2026 08:07
@upupming upupming merged commit b1ad1b9 into main Apr 13, 2026
74 of 79 checks passed
@upupming upupming deleted the feat/rstest-rltl branch April 13, 2026 08:11
upupming added a commit that referenced this pull request Apr 14, 2026
<!--
  Thank you for submitting a pull request!

We appreciate the time and effort you have invested in making these
changes. Please ensure that you provide enough information to allow
others to review your pull request.

Upon submission, your pull request will be automatically assigned with
reviewers.

If you want to learn more about contributing to this project, please
visit:
https://github.com/lynx-family/lynx-stack/blob/main/CONTRIBUTING.md.
-->

<!-- The AI summary below will be auto-generated - feel free to replace
it with your own. -->

Small Fix for #2328

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Updated build task configuration to include an additional upstream
dependency, optimizing the build pipeline execution order.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

## Checklist

<!--- Check and mark with an "x" -->

- [ ] Tests updated (or not required).
- [ ] Documentation updated (or not required).
- [ ] Changeset added, and when a BREAKING CHANGE occurs, it needs to be
clearly marked (or not required).
colinaaa pushed a commit that referenced this pull request Apr 19, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @lynx-js/react@0.119.0

### Minor Changes

- Simplify hooks for main-thread runtime, which only can run during the
first screen.
([#2441](#2441))

### Patch Changes

- Remove stale gestures when gestures are removed
([#2297](#2297))

- Trace refactor
([#2466](#2466))

    -   Remove `ReactLynx::renderOpcodes` from the trace
- Use `ReactLynx::transferRoot` to measure the time spent transferring
the root to the background thread

- refactor: set state of suspense to render fallback
([#2450](#2450))

- Support rstest for testing library, you can use rstest with RLTL now:
([#2328](#2328))

    Create a config file `rstest.config.ts` with the following content:

    ```ts
    import { defineConfig } from "@rstest/core";
import { withLynxConfig } from
"@lynx-js/react/testing-library/rstest-config";

    export default defineConfig({
      extends: withLynxConfig(),
    });
    ```

`@lynx-js/react/testing-library/rstest-config` will automatically load
your `lynx.config.ts` and apply the same configuration to rstest, so you
can keep your test environment consistent with your development
environment.

    And then use rstest as usual:

    ```bash
    $ rstest
    ```

    For more usage detail, see <https://rstest.rs/>

- Update preact version
([#2456](#2456))

- Add `nodeIndex` to generated FiberElement creation calls and expose
React transform debug metadata as `uiSourceMapRecords`.
([#2402](#2402))

## @lynx-js/react-rsbuild-plugin@0.16.0

### Minor Changes

- Simplify hooks for main-thread runtime, which only can run during the
first screen.
([#2441](#2441))

### Patch Changes

- Support rstest for testing library using a dedicated testing loader.
([#2328](#2328))

- Fix `environments.lynx.performance.profile` so it overrides the
default profile behavior for the current environment.
([#2468](#2468))

- Add `enableUiSourceMap` option to enable UI source map generation and
debug-metadata asset emission.
([#2402](#2402))

- Updated dependencies
\[[`a9f8d05`](a9f8d05),
[`b1ad1b9`](b1ad1b9),
[`f6184f3`](f6184f3),
[`f6184f3`](f6184f3),
[`a9f8d05`](a9f8d05),
[`f542d9c`](f542d9c)]:
    -   @lynx-js/template-webpack-plugin@0.10.9
    -   @lynx-js/react-webpack-plugin@0.9.1
    -   @lynx-js/react-alias-rsbuild-plugin@0.16.0
    -   @lynx-js/css-extract-webpack-plugin@0.7.0
    -   @lynx-js/react-refresh-webpack-plugin@0.3.5
    -   @lynx-js/use-sync-external-store@1.5.0

## @lynx-js/react-alias-rsbuild-plugin@0.16.0

### Minor Changes

- Simplify hooks for main-thread runtime, which only can run during the
first screen.
([#2441](#2441))

### Patch Changes

- fix(rstest): add global fallback aliases for
`@lynx-js/react/jsx-runtime` and `@lynx-js/react/jsx-dev-runtime`
([#2464](#2464))

`pluginReactAlias` only aliased these entries inside layer-specific
rules (`issuerLayer: BACKGROUND/MAIN_THREAD`). In rstest mode there are
no layers, so JSX transformed by the testing loader—which emits `import
{ jsx } from '@lynx-js/react/jsx-runtime'`—could not be resolved,
causing a `Cannot find module '@lynx-js/react/jsx-runtime'` error. Added
global (non-layer-specific) fallback aliases pointing to the background
jsx-runtime.

## @lynx-js/testing-environment@0.2.0

### Minor Changes

- **BREAKING CHANGE**:
([#2328](#2328))

    Align the public test-environment API around `LynxEnv`.

`LynxTestingEnv` now expects a `{ window }`-shaped environment instead
of relying on a concrete `JSDOM` instance or `global.jsdom`. Callers
that construct `LynxTestingEnv` manually or initialize the environment
through globals should migrate to `new LynxTestingEnv({ window })` or
set `global.lynxEnv`.

This release also adds the `@lynx-js/testing-environment/env/rstest`
entry for running the shared testing-environment suite under rstest.

### Patch Changes

- Add `__RemoveGestureDetector` PAPI binding
([#2297](#2297))

## @lynx-js/rspeedy@0.14.2

### Patch Changes

-   Updated dependencies \[]:
    -   @lynx-js/web-rsbuild-server-middleware@0.20.2

## create-rspeedy@0.14.2

### Patch Changes

- Add Rstest ReactLynx Testing Library template.
([#2328](#2328))

## @lynx-js/external-bundle-rsbuild-plugin@0.1.1

### Patch Changes

- Updated dependencies
\[[`3262ca8`](3262ca8)]:
    -   @lynx-js/externals-loading-webpack-plugin@0.1.1

## @lynx-js/web-core@0.20.2

### Patch Changes

- fix: map clientX and clientY to x and y in touch event detail
([#2458](#2458))

- fix(web-platform): completely detach event listeners and forcefully
free `MainThreadWasmContext` pointer alongside strict FIFO async
component disposal to ensure total memory reclamation without
use-after-free risks
([#2457](#2457))

- refactor: with WeakRef in element APIs and WASM bindings to improve
memory management.
([#2439](#2439))

- fix: preserve CSS variable fallback values when encoding web-core
stylesheets so declarations like `var(--token, rgba(...))` are emitted
with their fallback intact.
([#2460](#2460))

- fix: avoid to do use-after-free for rust instance
([#2461](#2461))

- fix: Change uniqueId to uid in LynxCrossThreadEventTarget
([#2467](#2467))

-   Updated dependencies \[]:
    -   @lynx-js/web-worker-rpc@0.20.2

## @lynx-js/externals-loading-webpack-plugin@0.1.1

### Patch Changes

- fix: deduplicate `loadScript` calls for externals sharing the same
(bundle, section) pair
([#2465](#2465))

When multiple externals had different `libraryName` values but pointed
to the same
bundle URL and section path,
`createLoadExternalSync`/`createLoadExternalAsync` was
called once per external, causing `lynx.loadScript` to execute
redundantly for the
same section. Now only the first external in each `(url, sectionPath)`
group triggers
the load; subsequent externals in the group are assigned the
already-loaded result
    directly.

## @lynx-js/react-webpack-plugin@0.9.1

### Patch Changes

- Support rstest for testing library using a dedicated testing loader.
([#2328](#2328))

- fix(rstest): normalize partial `compat` options in the testing loader
([#2464](#2464))

The testing loader forwards `compat` directly to
`transformReactLynxSync` without normalization. When `compat` is
supplied as a partial object, the required `target` field is absent and
the WASM transform throws `Error: Missing field 'target'`. Added the
same normalization already present in `getCommonOptions` for the
background/main-thread loaders: fills in `target: 'MIXED'` and all other
required fields with sensible defaults.

- Add `enableUiSourceMap` option to enable UI source map generation and
debug-metadata asset emission.
([#2402](#2402))

## @lynx-js/template-webpack-plugin@0.10.9

### Patch Changes

- Introduce `LynxDebugMetadataPlugin` to emit debug-metadata assets.
([#2402](#2402))

- Updated dependencies
\[[`24c4c69`](24c4c69),
[`7332eb4`](7332eb4),
[`fd0cc6e`](fd0cc6e),
[`e5b0f66`](e5b0f66),
[`5aa97d8`](5aa97d8),
[`5c39654`](5c39654)]:
    -   @lynx-js/web-core@0.20.2

## @lynx-js/react-umd@0.119.0



## upgrade-rspeedy@0.14.2



## @lynx-js/web-rsbuild-server-middleware@0.20.2



## @lynx-js/web-worker-rpc@0.20.2

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Refactor] testing-library Powered by rstest

4 participants