From 08894783e956112397f9f0b08835a1ff0e1a5549 Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Mon, 23 Mar 2026 00:35:12 +0900 Subject: [PATCH 1/2] fix(test): exclude @vitest/browser/context from vendor-aliases to fix missing server export --- .../test/__tests__/build-artifacts.spec.ts | 58 +++++++++++++++++++ packages/test/build.ts | 13 ++++- 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 packages/test/__tests__/build-artifacts.spec.ts diff --git a/packages/test/__tests__/build-artifacts.spec.ts b/packages/test/__tests__/build-artifacts.spec.ts new file mode 100644 index 0000000000..21d963dd17 --- /dev/null +++ b/packages/test/__tests__/build-artifacts.spec.ts @@ -0,0 +1,58 @@ +/** + * Verify that the @voidzero-dev/vite-plus-test build output (dist/) + * contains the expected files and that patches applied during the build + * (in build.ts) produce correct artifacts. + * + * This is important because vite-plus re-packages vitest with custom + * patches, and missing exports or incorrect patches can break + * third-party integrations (e.g., @storybook/addon-vitest, #1086). + */ +import fs from 'node:fs'; +import path from 'node:path'; +import url from 'node:url'; + +import { describe, expect, it } from 'vitest'; + +const testPkgDir = path.resolve(path.dirname(url.fileURLToPath(import.meta.url)), '..'); +const distDir = path.join(testPkgDir, 'dist'); + +describe('build artifacts', () => { + describe('@vitest/browser/context.js', () => { + const contextPath = path.join(distDir, '@vitest/browser/context.js'); + + it('should exist', () => { + expect(fs.existsSync(contextPath), `${contextPath} should exist`).toBe(true); + }); + + it('should export page, cdp, and utils', () => { + const content = fs.readFileSync(contextPath, 'utf-8'); + expect(content).toMatch(/export\s*\{[^}]*page[^}]*\}/); + expect(content).toMatch(/export\s*\{[^}]*cdp[^}]*\}/); + expect(content).toMatch(/export\s*\{[^}]*utils[^}]*\}/); + }); + }); + + /** + * The vitest:vendor-aliases plugin must NOT resolve @vitest/browser/context + * to the static file. If it does, the BrowserContext plugin's virtual module + * (which provides the `server` export) is bypassed. + * + * See: https://github.com/voidzero-dev/vite-plus/issues/1086 + */ + describe('vitest:vendor-aliases plugin (regression test for #1086)', () => { + const browserIndexPath = path.join(distDir, '@vitest/browser/index.js'); + + it('should not map @vitest/browser/context in vendorMap', () => { + const content = fs.readFileSync(browserIndexPath, 'utf-8'); + // The vendorMap inside vitest:vendor-aliases should NOT contain + // '@vitest/browser/context' — it must be left for BrowserContext + // plugin to resolve as a virtual module. + const vendorAliasesMatch = content.match( + /name:\s*['"]vitest:vendor-aliases['"][\s\S]*?const vendorMap\s*=\s*\{([\s\S]*?)\}/, + ); + expect(vendorAliasesMatch, 'vitest:vendor-aliases plugin should exist').toBeTruthy(); + const vendorMapContent = vendorAliasesMatch![1]; + expect(vendorMapContent).not.toContain("'@vitest/browser/context'"); + }); + }); +}); diff --git a/packages/test/build.ts b/packages/test/build.ts index a2c5df4249..fcec66b3c9 100644 --- a/packages/test/build.ts +++ b/packages/test/build.ts @@ -1458,8 +1458,19 @@ async function patchVitestBrowserPackage() { // 1. Inject vitest:vendor-aliases plugin into BrowserPlugin return array // This allows imports like @vitest/runner to be resolved to our copied @vitest files + // Exclude @vitest/browser/context from vendor-aliases so that BrowserContext + // plugin's resolveId can intercept the bare specifier and return the virtual + // module (which includes the dynamically generated `server` export). + // Without this, vendor-aliases resolves the bare specifier to the static + // context.js file (which has no `server`), bypassing BrowserContext entirely. + // See: https://github.com/voidzero-dev/vite-plus/issues/1086 + const VENDOR_ALIASES_EXCLUDE = new Set(['@vitest/browser/context']); + const mappingEntries = Object.entries(VITEST_PACKAGE_TO_PATH) - .filter(([pkg]) => pkg.startsWith('@vitest/')) + .filter( + ([pkg]) => + pkg.startsWith('@vitest/') && !VENDOR_ALIASES_EXCLUDE.has(pkg), + ) .map(([pkg, file]) => `'${pkg}': resolve(packageRoot, '${file}')`) .join(',\n '); From c382a2be58770aea588665927398ceffdbc8f091 Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Mon, 23 Mar 2026 12:28:18 +0900 Subject: [PATCH 2/2] fix: format --- packages/test/build.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/test/build.ts b/packages/test/build.ts index fcec66b3c9..f4276d0de5 100644 --- a/packages/test/build.ts +++ b/packages/test/build.ts @@ -1467,10 +1467,7 @@ async function patchVitestBrowserPackage() { const VENDOR_ALIASES_EXCLUDE = new Set(['@vitest/browser/context']); const mappingEntries = Object.entries(VITEST_PACKAGE_TO_PATH) - .filter( - ([pkg]) => - pkg.startsWith('@vitest/') && !VENDOR_ALIASES_EXCLUDE.has(pkg), - ) + .filter(([pkg]) => pkg.startsWith('@vitest/') && !VENDOR_ALIASES_EXCLUDE.has(pkg)) .map(([pkg, file]) => `'${pkg}': resolve(packageRoot, '${file}')`) .join(',\n ');