From ec6c4dc9b0e75f5c2e24d0fc9e47ab91b38ff023 Mon Sep 17 00:00:00 2001 From: Brenley Dueck Date: Sun, 20 Sep 2026 08:10:04 -0500 Subject: [PATCH 1/2] fix(vitest): resolve each inline project's own config under Vitest 5 Vitest 5 defaults test.sharedViteServer to true, so inline projects reuse the root Vite server and never run the plugin's config hook. They lost the per-project posture, the jest-dom setup file and the server.deps handling. The plugin now sets sharedViteServer to false when the root config declares test.projects and the user has not set the option. Fixes #369 --- .changeset/vitest-5-shared-server-projects.md | 5 +++++ README.md | 2 ++ src/index.ts | 5 +++++ 3 files changed, 12 insertions(+) create mode 100644 .changeset/vitest-5-shared-server-projects.md diff --git a/.changeset/vitest-5-shared-server-projects.md b/.changeset/vitest-5-shared-server-projects.md new file mode 100644 index 00000000..62889bb6 --- /dev/null +++ b/.changeset/vitest-5-shared-server-projects.md @@ -0,0 +1,5 @@ +--- +'@solidjs/vite-plugin': patch +--- + +Vitest 5 inline projects get the plugin's test configuration again (#369). Vitest 5 defaults `test.sharedViteServer` to `true`, so an inline project that only changes `test` options reuses the root Vite server and resolves its options from the raw root `test` block, without running the plugin's `config` hook. Such projects lost everything the hook injects: a `test.environment: 'node'` project kept the root's `browser` condition (`isServer` was `false`), and jsdom projects lost the `@testing-library/jest-dom` setup file and the `solid-js` `server.deps` handling. When the root config declares `test.projects` and leaves `test.sharedViteServer` unset, the plugin now sets it to `false` so every project resolves its own Vite config, as it did under Vitest 4. An explicit `sharedViteServer` value is respected. diff --git a/README.md b/README.md index 68b757cc..41c50343 100644 --- a/README.md +++ b/README.md @@ -1045,6 +1045,8 @@ test: { }, ``` +The posture is chosen while each project resolves its own Vite config. Vitest 5 lets inline projects reuse the root Vite server instead (`test.sharedViteServer`, on by default), which skips that step, so the plugin sets `sharedViteServer: false` when the root config declares `test.projects`. Setting the option yourself overrides this; with `true`, every shared project runs with the root config's posture and without the injected `jest-dom` setup file. + # Credits - [solid-js](https://github.com/solidjs/solid) diff --git a/src/index.ts b/src/index.ts index f4d66873..f522ec2e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1192,6 +1192,11 @@ export default function solidPlugin(options: Partial = {}): Plugin[] { test.environment = 'jsdom'; } + // Vitest 5 inline projects reuse the root server and never run this hook (#369). + if (userTest.projects && userTest.sharedViteServer === undefined) { + test.sharedViteServer = false; + } + if (serverTestPosture) { // The worker pool is shared across the whole vitest workspace and // imports externalized deps natively with `--conditions` derived From 59519fb2693d80e04af650bd7dad413d40080831 Mon Sep 17 00:00:00 2001 From: Ryan Carniato Date: Wed, 30 Sep 2026 01:31:51 -0700 Subject: [PATCH 2/2] =?UTF-8?q?fix(vitest):=20address=20review=20=E2=80=94?= =?UTF-8?q?=20resolveConfig=20assertion,=20comment,=20docs=20(Refs=20#369)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- .changeset/vitest-5-shared-server-projects.md | 2 +- README.md | 2 +- examples/start-ssr/test/run.mjs | 47 +++++++++++++++++++ src/index.ts | 7 ++- 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/.changeset/vitest-5-shared-server-projects.md b/.changeset/vitest-5-shared-server-projects.md index 62889bb6..7781421a 100644 --- a/.changeset/vitest-5-shared-server-projects.md +++ b/.changeset/vitest-5-shared-server-projects.md @@ -2,4 +2,4 @@ '@solidjs/vite-plugin': patch --- -Vitest 5 inline projects get the plugin's test configuration again (#369). Vitest 5 defaults `test.sharedViteServer` to `true`, so an inline project that only changes `test` options reuses the root Vite server and resolves its options from the raw root `test` block, without running the plugin's `config` hook. Such projects lost everything the hook injects: a `test.environment: 'node'` project kept the root's `browser` condition (`isServer` was `false`), and jsdom projects lost the `@testing-library/jest-dom` setup file and the `solid-js` `server.deps` handling. When the root config declares `test.projects` and leaves `test.sharedViteServer` unset, the plugin now sets it to `false` so every project resolves its own Vite config, as it did under Vitest 4. An explicit `sharedViteServer` value is respected. +When the root config declares `test.projects` and leaves `test.sharedViteServer` unset, the plugin now sets it to `false` so every inline project resolves its own Vite config, as under Vitest 4; an explicit value is respected. Vitest 5 defaults the option to `true`, and a shared inline project takes its `test` options from the raw root block captured before any `config` hook runs, so it lost everything the plugin injects (posture, the `@testing-library/jest-dom` setup file, `server.deps`). Refs #369. diff --git a/README.md b/README.md index 41c50343..052b23f3 100644 --- a/README.md +++ b/README.md @@ -1045,7 +1045,7 @@ test: { }, ``` -The posture is chosen while each project resolves its own Vite config. Vitest 5 lets inline projects reuse the root Vite server instead (`test.sharedViteServer`, on by default), which skips that step, so the plugin sets `sharedViteServer: false` when the root config declares `test.projects`. Setting the option yourself overrides this; with `true`, every shared project runs with the root config's posture and without the injected `jest-dom` setup file. +The posture is chosen while each project resolves its own Vite config. Vitest 5 lets inline projects reuse the root Vite server instead (`test.sharedViteServer`, on by default), which skips that step, so the plugin sets `sharedViteServer: false` when the root config declares `test.projects` — trading Vitest 5's shared-server optimization for the per-project resolution Vitest 4 always did. Setting the option yourself overrides this; with `true`, every shared project runs with the root config's posture, without the injected `jest-dom` setup file, and without the plugin's `server.deps` handling (the framework inlined for the server posture, externalized for the client one). # Credits diff --git a/examples/start-ssr/test/run.mjs b/examples/start-ssr/test/run.mjs index b898951a..b490f634 100644 --- a/examples/start-ssr/test/run.mjs +++ b/examples/start-ssr/test/run.mjs @@ -5231,6 +5231,53 @@ async function runVitestMode() { projectsEnvPass ? undefined : projectsEnvError || `environment: ${projectsEnv}`, ); + // Vitest 5 defaults `test.sharedViteServer` to true, and a shared inline + // project takes its `test` options from the raw root block captured before + // any `config` hook runs — so it would never see the posture, jest-dom + // setup file, or server.deps the plugin injects (#369). The plugin turns + // sharing off when the root declares `test.projects` and the user hasn't + // chosen. Asserted at the config-resolution level, which is + // version-independent: the examples pin vitest 4, where the option has no + // effect, but the resolved value is what Vitest 5's getOwnServerReason + // reads. + const resolveSharedViteServer = async (testBlock) => { + const resolved = await resolveConfig( + { root: exampleDir, mode: 'test', test: testBlock }, + 'serve', + ); + return resolved.test?.sharedViteServer; + }; + const projectsBlock = [{ extends: true, test: { name: 'node', environment: 'node' } }]; + let sharedWithProjects; + let sharedWithoutProjects; + let sharedExplicit; + let sharedError = ''; + try { + sharedWithProjects = await resolveSharedViteServer({ projects: projectsBlock }); + sharedWithoutProjects = await resolveSharedViteServer({}); + sharedExplicit = await resolveSharedViteServer({ + projects: projectsBlock, + sharedViteServer: true, + }); + } catch (e) { + sharedError = String(e); + } + const sharedPass = + !sharedError && + sharedWithProjects === false && + sharedWithoutProjects === undefined && + sharedExplicit === true; + record( + mode, + 'shared-vite-server', + 'root config with test.projects gets sharedViteServer: false (untouched without projects, explicit true preserved)', + sharedPass, + sharedPass + ? undefined + : sharedError || + `projects: ${sharedWithProjects}, none: ${sharedWithoutProjects}, explicit: ${sharedExplicit}`, + ); + // The jest-dom setup file is injected only when the PROJECT can resolve // `@testing-library/jest-dom` — by walking node_modules up from the Vite // root, the way vitest itself resolves bare `setupFiles`. Two ways the diff --git a/src/index.ts b/src/index.ts index f522ec2e..f370343a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1192,7 +1192,12 @@ export default function solidPlugin(options: Partial = {}): Plugin[] { test.environment = 'jsdom'; } - // Vitest 5 inline projects reuse the root server and never run this hook (#369). + // Vitest 5 defaults `test.sharedViteServer` to true: inline projects + // then reuse the root Vite server and take their `test` options from + // the raw root block captured BEFORE any `config` hook runs, so nothing + // injected here (posture, jest-dom, server.deps) reaches them. Vitest + // reads the option off the resolved root config (getOwnServerReason), so + // this restores per-project resolution as under Vitest 4 (#369). if (userTest.projects && userTest.sharedViteServer === undefined) { test.sharedViteServer = false; }