From 4207c4024ab17253261d9af651ff84ca5fd9db39 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 2 Dec 2025 08:24:36 +0000
Subject: [PATCH 1/4] Initial plan
From aa82e65fd28626fe9ca2638d45519017e498fd40 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 2 Dec 2025 08:30:42 +0000
Subject: [PATCH 2/4] chore: setup oxfmt for formatting
Co-authored-by: hi-ogawa <4232207+hi-ogawa@users.noreply.github.com>
---
.oxfmtrc.json | 5 +
eslint.config.js | 12 +-
package.json | 7 +-
packages/common/refresh-runtime.js | 43 +-
packages/common/refresh-utils.ts | 7 +-
packages/common/warning.ts | 7 +-
packages/plugin-react-oxc/src/index.ts | 11 +-
.../__tests__/emotion-plugin.spec.ts | 12 +-
.../playground/emotion-plugin/src/App.jsx | 10 +-
.../emotion/__tests__/emotion.spec.ts | 12 +-
.../playground/emotion/src/App.tsx | 10 +-
.../playground/hmr/__tests__/hmr.spec.ts | 16 +-
.../playground/hmr/src/App.tsx | 4 +-
.../playground/mdx/__tests__/mdx.spec.ts | 6 +-
.../react-18/__tests__/react-18.spec.ts | 16 +-
.../playground/react-18/src/App.tsx | 4 +-
.../__tests__/styled-components.spec.ts | 10 +-
.../playground/styled-components/src/App.tsx | 4 +-
packages/plugin-react-swc/playground/utils.ts | 36 +-
.../worker/__tests__/worker.spec.ts | 6 +-
.../plugin-react-swc/playwright.config.ts | 6 +-
packages/plugin-react-swc/src/index.ts | 29 +-
packages/plugin-react-swc/tsdown.config.ts | 5 +-
packages/plugin-react/src/index.ts | 78 +--
packages/plugin-rsc/e2e/base.test.ts | 4 +-
packages/plugin-rsc/e2e/basic.test.ts | 652 +++++-------------
packages/plugin-rsc/e2e/browser-mode.test.ts | 48 +-
packages/plugin-rsc/e2e/error.test.ts | 4 +-
packages/plugin-rsc/e2e/fixture.ts | 25 +-
packages/plugin-rsc/e2e/helper.ts | 6 +-
packages/plugin-rsc/e2e/isolated.test.ts | 31 +-
packages/plugin-rsc/e2e/react-router.test.ts | 63 +-
.../plugin-rsc/e2e/render-built-url.test.ts | 4 +-
packages/plugin-rsc/e2e/ssr-thenable.test.ts | 5 +-
packages/plugin-rsc/e2e/starter.ts | 50 +-
packages/plugin-rsc/e2e/syntax-error.test.ts | 32 +-
.../plugin-rsc/e2e/validate-imports.test.ts | 8 +-
.../basic/src/framework/entry.rsc.tsx | 7 +-
.../basic/src/framework/entry.ssr.tsx | 10 +-
.../basic/src/framework/error-boundary.tsx | 10 +-
.../basic/src/framework/use-cache-runtime.tsx | 10 +-
.../basic/src/routes/action-bind/form.tsx | 4 +-
.../basic/src/routes/action-bind/server.tsx | 15 +-
.../src/routes/action-from-client/client.tsx | 4 +-
.../basic/src/routes/action-state/client.tsx | 5 +-
.../basic/src/routes/action/server.tsx | 6 +-
.../basic/src/routes/assets/client.tsx | 7 +-
.../basic/src/routes/assets/server.tsx | 7 +-
.../basic/src/routes/browser-only/client.tsx | 4 +-
.../basic/src/routes/chunk/server.tsx | 10 +-
.../examples/basic/src/routes/client.tsx | 6 +-
.../basic/src/routes/css-queries/server.tsx | 6 +-
.../src/routes/hmr-client-dep/client.tsx | 8 +-
.../src/routes/hmr-client-dep2/client.tsx | 8 +-
.../src/routes/hmr-client-dep3/client-a.tsx | 4 +-
.../src/routes/hmr-shared/atomic/client.tsx | 10 +-
.../basic/src/routes/hmr-shared/client.tsx | 3 +-
.../basic/src/routes/hmr-shared/server.tsx | 3 +-
.../src/routes/hydration-mismatch/server.tsx | 6 +-
.../basic/src/routes/payload/client.tsx | 7 +-
.../examples/basic/src/routes/root.tsx | 5 +-
.../basic/src/routes/serialization/server.tsx | 5 +-
.../src/routes/style-client-no-ssr/server.tsx | 4 +-
.../basic/src/routes/style-client/client.tsx | 6 +-
.../basic/src/routes/style-server/server.tsx | 6 +-
.../basic/src/routes/use-cache/server.tsx | 4 +-
.../test-dep/client-in-server2/client.js | 6 +-
.../test-dep/client-in-server2/server.js | 6 +-
.../basic/test-dep/css-in-server/server.js | 6 +-
.../plugin-rsc/examples/basic/vite.config.ts | 40 +-
.../browser-mode/src/action-bind/form.tsx | 4 +-
.../browser-mode/src/action-bind/server.tsx | 15 +-
.../examples/browser-mode/src/client.tsx | 6 +-
.../src/framework/load-client-dev.tsx | 9 +-
.../examples/browser-mode/src/root.tsx | 5 +-
.../examples/browser-mode/vite.config.ts | 24 +-
.../examples/browser/lib/dev-proxy.ts | 5 +-
.../plugin-rsc/examples/browser/lib/plugin.ts | 18 +-
.../examples/browser/src/client.tsx | 6 +-
.../browser/src/framework/entry.browser.tsx | 4 +-
.../plugin-rsc/examples/browser/src/root.tsx | 5 +-
.../examples/e2e/middleware-mode.ts | 4 +-
.../plugin-rsc/examples/no-ssr/src/client.tsx | 6 +-
.../no-ssr/src/framework/entry.browser.tsx | 8 +-
.../plugin-rsc/examples/no-ssr/src/root.tsx | 5 +-
.../plugin-rsc/examples/no-ssr/vite.config.ts | 5 +-
.../react-router/app/routes/client.tsx | 8 +-
.../examples/react-router/app/routes/home.tsx | 13 +-
.../app/routes/test-action-state/client.tsx | 5 +-
.../react-router-vite/entry.browser.tsx | 13 +-
.../react-router-vite/entry.rsc.single.tsx | 4 +-
.../react-router-vite/entry.ssr.tsx | 19 +-
.../plugin-rsc/examples/ssg/src/counter.tsx | 4 +-
.../ssg/src/framework/entry.browser.tsx | 5 +-
.../examples/ssg/src/framework/entry.rsc.tsx | 8 +-
.../examples/ssg/src/framework/entry.ssr.tsx | 6 +-
.../ssg/src/framework/error-boundary.tsx | 10 +-
packages/plugin-rsc/examples/ssg/src/root.tsx | 9 +-
.../plugin-rsc/examples/ssg/vite.config.ts | 5 +-
.../examples/starter-cf-single/src/client.tsx | 6 +-
.../src/framework/entry.rsc.tsx | 7 +-
.../src/framework/entry.ssr.tsx | 10 +-
.../src/framework/error-boundary.tsx | 10 +-
.../examples/starter-cf-single/src/root.tsx | 5 +-
.../examples/starter/src/client.tsx | 6 +-
.../starter/src/framework/entry.rsc.tsx | 7 +-
.../starter/src/framework/entry.ssr.tsx | 10 +-
.../starter/src/framework/error-boundary.tsx | 10 +-
.../plugin-rsc/examples/starter/src/root.tsx | 5 +-
packages/plugin-rsc/playwright.config.ts | 4 +-
packages/plugin-rsc/src/browser.ts | 4 +-
packages/plugin-rsc/src/core/browser.ts | 4 +-
packages/plugin-rsc/src/core/rsc.ts | 54 +-
packages/plugin-rsc/src/core/ssr.ts | 4 +-
packages/plugin-rsc/src/index.ts | 7 +-
packages/plugin-rsc/src/plugin.ts | 403 ++++-------
packages/plugin-rsc/src/plugins/cjs.ts | 8 +-
.../src/plugins/find-source-map-url.ts | 10 +-
packages/plugin-rsc/src/plugins/scan.ts | 6 +-
packages/plugin-rsc/src/plugins/utils.ts | 16 +-
.../plugin-rsc/src/plugins/validate-import.ts | 27 +-
packages/plugin-rsc/src/plugins/vite-utils.ts | 5 +-
packages/plugin-rsc/src/react/browser.ts | 17 +-
packages/plugin-rsc/src/react/rsc.ts | 38 +-
packages/plugin-rsc/src/rsc.tsx | 11 +-
packages/plugin-rsc/src/transforms/cjs.ts | 15 +-
.../plugin-rsc/src/transforms/hoist.test.ts | 13 +-
packages/plugin-rsc/src/transforms/hoist.ts | 33 +-
.../plugin-rsc/src/transforms/proxy-export.ts | 26 +-
packages/plugin-rsc/src/transforms/utils.ts | 10 +-
.../plugin-rsc/src/transforms/waku.test.ts | 15 +-
.../src/transforms/wrap-export.test.ts | 16 +-
.../plugin-rsc/src/transforms/wrap-export.ts | 42 +-
packages/plugin-rsc/src/types/virtual.d.ts | 4 +-
.../src/utils/encryption-runtime.ts | 14 +-
.../plugin-rsc/src/utils/encryption-utils.ts | 14 +-
packages/plugin-rsc/src/utils/rpc.ts | 12 +-
packages/plugin-rsc/tsdown.config.ts | 9 +-
.../__tests__/class-components.spec.ts | 18 +-
.../__tests__/compiler-react-18.spec.ts | 4 +-
playground/compiler-react-18/src/App.tsx | 8 +-
.../compiler/__tests__/compiler.spec.ts | 4 +-
playground/compiler/src/App.tsx | 8 +-
playground/hmr-false/src/App.tsx | 4 +-
.../__tests__/hook-with-jsx.spec.ts | 5 +-
.../hook-with-jsx/src/useButtonHook.tsx | 6 +-
playground/include-node-modules/App.jsx | 5 +-
playground/mdx/__tests__/mdx.spec.ts | 5 +-
playground/mdx/vite.config.ts | 5 +-
playground/react-classic/App.jsx | 4 +-
.../react-classic/__tests__/react.spec.ts | 27 +-
.../react-classic/components/WithQuery.jsx | 5 +-
.../react-emotion/__tests__/react.spec.ts | 12 +-
playground/react-sourcemap/main.jsx | 4 +-
playground/react/App.jsx | 5 +-
playground/react/__tests__/react.spec.ts | 73 +-
playground/react/components/Accordion.jsx | 5 +-
playground/react/components/WithQuery.jsx | 5 +-
.../ssr-react/__tests__/ssr-react.spec.ts | 8 +-
playground/ssr-react/src/entry-client.jsx | 5 +-
playground/ssr-react/src/entry-server.jsx | 4 +-
playground/ssr-react/vite.config.js | 18 +-
playground/test-utils.ts | 9 +-
playground/vitestGlobalSetup.ts | 8 +-
playground/vitestSetup.ts | 28 +-
pnpm-lock.yaml | 83 +++
scripts/release.ts | 12 +-
167 files changed, 834 insertions(+), 2244 deletions(-)
create mode 100644 .oxfmtrc.json
diff --git a/.oxfmtrc.json b/.oxfmtrc.json
new file mode 100644
index 000000000..4bddb6759
--- /dev/null
+++ b/.oxfmtrc.json
@@ -0,0 +1,5 @@
+{
+ "$schema": "./node_modules/oxfmt/configuration_schema.json",
+ "semi": false,
+ "singleQuote": true
+}
diff --git a/eslint.config.js b/eslint.config.js
index 1b2ff21dc..bbf423000 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -9,12 +9,7 @@ import globals from 'globals'
export default tseslint.config(
{
- ignores: [
- '**/dist/**',
- '**/playground-temp/**',
- '**/temp/**',
- 'packages/plugin-rsc/**',
- ],
+ ignores: ['**/dist/**', '**/playground-temp/**', '**/temp/**', 'packages/plugin-rsc/**'],
},
eslint.configs.recommended,
...tseslint.configs.recommended,
@@ -65,10 +60,7 @@ export default tseslint.config(
'error',
{ allowArgumentsExplicitlyTypedAsAny: true },
],
- '@typescript-eslint/no-empty-function': [
- 'error',
- { allow: ['arrowFunctions'] },
- ],
+ '@typescript-eslint/no-empty-function': ['error', { allow: ['arrowFunctions'] }],
'@typescript-eslint/no-empty-interface': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'no-extra-semi': 'off',
diff --git a/package.json b/package.json
index b9fdbce31..a5d64b51e 100644
--- a/package.json
+++ b/package.json
@@ -18,7 +18,7 @@
"scripts": {
"preinstall": "npx only-allow pnpm",
"postinstall": "simple-git-hooks",
- "format": "prettier --write --cache .",
+ "format": "oxfmt",
"lint": "eslint --cache .",
"typecheck": "tsc -p scripts && tsc -p playground && tsc -p packages/plugin-react",
"test": "pnpm run test-unit && pnpm run test-serve && pnpm run test-build && pnpm --filter ./packages/plugin-react-swc run test",
@@ -44,6 +44,7 @@
"fs-extra": "^11.3.2",
"globals": "^16.5.0",
"lint-staged": "^16.2.7",
+ "oxfmt": "^0.16.0",
"picocolors": "^1.1.1",
"playwright-chromium": "^1.57.0",
"prettier": "^3.6.2",
@@ -58,8 +59,8 @@
"pre-commit": "pnpm exec lint-staged --concurrent false"
},
"lint-staged": {
- "*": [
- "prettier --write --cache --ignore-unknown"
+ "*.{js,mjs,cjs,jsx,ts,mts,cts,tsx,vue,astro,svelte,json,jsonc}": [
+ "oxfmt"
],
"packages/*/{src,types}/**/*.ts": [
"eslint --cache --fix"
diff --git a/packages/common/refresh-runtime.js b/packages/common/refresh-runtime.js
index e798d000e..0ee199033 100644
--- a/packages/common/refresh-runtime.js
+++ b/packages/common/refresh-runtime.js
@@ -190,9 +190,7 @@ function performReactRefresh() {
failedRootsSnapshot.forEach((root) => {
const helpers = helpersByRootSnapshot.get(root)
if (helpers === undefined) {
- throw new Error(
- 'Could not find helpers for a root. This is a bug in React Refresh.',
- )
+ throw new Error('Could not find helpers for a root. This is a bug in React Refresh.')
}
if (!failedRoots.has(root)) {
// No longer failed.
@@ -217,9 +215,7 @@ function performReactRefresh() {
mountedRootsSnapshot.forEach((root) => {
const helpers = helpersByRootSnapshot.get(root)
if (helpers === undefined) {
- throw new Error(
- 'Could not find helpers for a root. This is a bug in React Refresh.',
- )
+ throw new Error('Could not find helpers for a root. This is a bug in React Refresh.')
}
if (!mountedRoots.has(root)) {
// No longer mounted.
@@ -405,8 +401,7 @@ export function injectIntoGlobalHook(globalObject) {
alternate.memoizedState.element != null &&
mountedRoots.has(root)
- const isMounted =
- current.memoizedState != null && current.memoizedState.element != null
+ const isMounted = current.memoizedState != null && current.memoizedState.element != null
if (!wasMounted && isMounted) {
// Mount a new root.
@@ -481,10 +476,7 @@ export function createSignatureFunctionForTransform() {
// Set the signature for all types (even wrappers!) in case
// they have no signatures of their own. This is to prevent
// problems like https://github.com/facebook/react/issues/20417.
- if (
- type != null &&
- (typeof type === 'function' || typeof type === 'object')
- ) {
+ if (type != null && (typeof type === 'function' || typeof type === 'object')) {
setSignature(type, key, forceReset, getCustomHooks)
}
return type
@@ -578,10 +570,7 @@ export function registerExportsForReactRefresh(filename, moduleExports) {
register(exportValue, filename + ' export ' + key)
} else if (isCompoundComponent(exportValue)) {
for (const subKey in exportValue) {
- register(
- exportValue[subKey],
- filename + ' export ' + key + '-' + subKey,
- )
+ register(exportValue[subKey], filename + ' export ' + key + '-' + subKey)
}
}
}
@@ -604,28 +593,12 @@ const enqueueUpdate = debounce(async () => {
performReactRefresh()
}, 16)
-export function validateRefreshBoundaryAndEnqueueUpdate(
- id,
- prevExports,
- nextExports,
-) {
+export function validateRefreshBoundaryAndEnqueueUpdate(id, prevExports, nextExports) {
const ignoredExports = window.__getReactRefreshIgnoredExports?.({ id }) ?? []
- if (
- predicateOnExport(
- ignoredExports,
- prevExports,
- (key) => key in nextExports,
- ) !== true
- ) {
+ if (predicateOnExport(ignoredExports, prevExports, (key) => key in nextExports) !== true) {
return 'Could not Fast Refresh (export removed)'
}
- if (
- predicateOnExport(
- ignoredExports,
- nextExports,
- (key) => key in prevExports,
- ) !== true
- ) {
+ if (predicateOnExport(ignoredExports, nextExports, (key) => key in prevExports) !== true) {
return 'Could not Fast Refresh (new export)'
}
diff --git a/packages/common/refresh-utils.ts b/packages/common/refresh-utils.ts
index ef9dc00f6..461f3e0d8 100644
--- a/packages/common/refresh-utils.ts
+++ b/packages/common/refresh-utils.ts
@@ -14,8 +14,7 @@ injectIntoGlobalHook(window);
window.$RefreshReg$ = () => {};
window.$RefreshSig$ = () => (type) => type;`
-export const getPreambleCode = (base: string): string =>
- preambleCode.replace('__BASE__', base)
+export const getPreambleCode = (base: string): string => preambleCode.replace('__BASE__', base)
export function addRefreshWrapper(
code: string,
@@ -41,9 +40,7 @@ if (import.meta.hot && !inWebWorker) {
}
RefreshRuntime.__hmr_import(import.meta.url).then((currentExports) => {
- RefreshRuntime.registerExportsForReactRefresh(${JSON.stringify(
- id,
- )}, currentExports);
+ RefreshRuntime.registerExportsForReactRefresh(${JSON.stringify(id)}, currentExports);
import.meta.hot.accept((nextExports) => {
if (!nextExports) return;
const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate(${JSON.stringify(
diff --git a/packages/common/warning.ts b/packages/common/warning.ts
index 85e0cf434..28b5fd4d4 100644
--- a/packages/common/warning.ts
+++ b/packages/common/warning.ts
@@ -1,14 +1,11 @@
import type { BuildOptions, UserConfig } from 'vite'
-export const silenceUseClientWarning = (
- userConfig: UserConfig,
-): BuildOptions => ({
+export const silenceUseClientWarning = (userConfig: UserConfig): BuildOptions => ({
rollupOptions: {
onwarn(warning, defaultHandler) {
if (
warning.code === 'MODULE_LEVEL_DIRECTIVE' &&
- (warning.message.includes('use client') ||
- warning.message.includes('use server'))
+ (warning.message.includes('use client') || warning.message.includes('use server'))
) {
return
}
diff --git a/packages/plugin-react-oxc/src/index.ts b/packages/plugin-react-oxc/src/index.ts
index 3be4046c9..1f959ad2f 100644
--- a/packages/plugin-react-oxc/src/index.ts
+++ b/packages/plugin-react-oxc/src/index.ts
@@ -51,12 +51,7 @@ export default function viteReact(opts: Options = {}): Plugin[] {
jsxRefreshExclude: exclude,
},
optimizeDeps: {
- include: [
- 'react',
- 'react-dom',
- jsxImportDevRuntime,
- jsxImportRuntime,
- ],
+ include: ['react', 'react-dom', jsxImportDevRuntime, jsxImportRuntime],
rolldownOptions: { transform: { jsx: { runtime: 'automatic' } } },
},
}
@@ -134,9 +129,7 @@ export default function viteReact(opts: Options = {}): Plugin[] {
const useFastRefresh =
!skipFastRefresh &&
!ssr &&
- (isJSX ||
- code.includes(jsxImportDevRuntime) ||
- code.includes(jsxImportRuntime))
+ (isJSX || code.includes(jsxImportDevRuntime) || code.includes(jsxImportRuntime))
if (!useFastRefresh) return
const newCode = addRefreshWrapper(code, '@vitejs/plugin-react-oxc', id)
diff --git a/packages/plugin-react-swc/playground/emotion-plugin/__tests__/emotion-plugin.spec.ts b/packages/plugin-react-swc/playground/emotion-plugin/__tests__/emotion-plugin.spec.ts
index 9fcdd8be8..d38de6d57 100644
--- a/packages/plugin-react-swc/playground/emotion-plugin/__tests__/emotion-plugin.spec.ts
+++ b/packages/plugin-react-swc/playground/emotion-plugin/__tests__/emotion-plugin.spec.ts
@@ -1,10 +1,5 @@
import { expect, test } from '@playwright/test'
-import {
- expectColor,
- setupBuildAndPreview,
- setupDevServer,
- setupWaitForLogs,
-} from '../../utils.ts'
+import { expectColor, setupBuildAndPreview, setupDevServer, setupWaitForLogs } from '../../utils.ts'
test('Emotion plugin build', async ({ page }) => {
const { testUrl, server } = await setupBuildAndPreview('emotion-plugin')
@@ -39,10 +34,7 @@ test('Emotion plugin HMR', async ({ page }) => {
const code = page.locator('code')
await expectColor(code, 'color', '#646cff')
- editFile('src/Button.jsx', [
- 'background-color: #d26ac2;',
- 'background-color: #646cff;',
- ])
+ editFile('src/Button.jsx', ['background-color: #d26ac2;', 'background-color: #646cff;'])
await waitForLogs('[vite] hot updated: /src/Button.jsx')
await expect(button).toHaveText('count is 1')
await expectColor(button, 'backgroundColor', '#646cff')
diff --git a/packages/plugin-react-swc/playground/emotion-plugin/src/App.jsx b/packages/plugin-react-swc/playground/emotion-plugin/src/App.jsx
index 44f5fd166..f1af53ac3 100644
--- a/packages/plugin-react-swc/playground/emotion-plugin/src/App.jsx
+++ b/packages/plugin-react-swc/playground/emotion-plugin/src/App.jsx
@@ -8,11 +8,7 @@ export const App = () => (
-
+
- Click on the Vite and Emotion logos to learn more -
+Click on the Vite and Emotion logos to learn more
) diff --git a/packages/plugin-react-swc/playground/emotion/__tests__/emotion.spec.ts b/packages/plugin-react-swc/playground/emotion/__tests__/emotion.spec.ts index 455fab7ba..c3b67dbb3 100644 --- a/packages/plugin-react-swc/playground/emotion/__tests__/emotion.spec.ts +++ b/packages/plugin-react-swc/playground/emotion/__tests__/emotion.spec.ts @@ -1,10 +1,5 @@ import { expect, test } from '@playwright/test' -import { - expectColor, - setupBuildAndPreview, - setupDevServer, - setupWaitForLogs, -} from '../../utils.ts' +import { expectColor, setupBuildAndPreview, setupDevServer, setupWaitForLogs } from '../../utils.ts' test('Emotion build', async ({ page }) => { const { testUrl, server } = await setupBuildAndPreview('emotion') @@ -39,10 +34,7 @@ test('Emotion HMR', async ({ page }) => { const code = page.locator('code') await expectColor(code, 'color', '#646cff') - editFile('src/Button.tsx', [ - 'background-color: #d26ac2;', - 'background-color: #646cff;', - ]) + editFile('src/Button.tsx', ['background-color: #d26ac2;', 'background-color: #646cff;']) await waitForLogs('[vite] hot updated: /src/Button.tsx') await expect(button).toHaveText('count is 1') await expectColor(button, 'backgroundColor', '#646cff') diff --git a/packages/plugin-react-swc/playground/emotion/src/App.tsx b/packages/plugin-react-swc/playground/emotion/src/App.tsx index 73f71fcb3..69e83f0de 100644 --- a/packages/plugin-react-swc/playground/emotion/src/App.tsx +++ b/packages/plugin-react-swc/playground/emotion/src/App.tsx @@ -8,11 +8,7 @@ export const App = () => (
+
- Click on the Vite and Emotion logos to learn more -
+Click on the Vite and Emotion logos to learn more
) diff --git a/packages/plugin-react-swc/playground/hmr/__tests__/hmr.spec.ts b/packages/plugin-react-swc/playground/hmr/__tests__/hmr.spec.ts index 714bf8a5d..6abf7f6da 100644 --- a/packages/plugin-react-swc/playground/hmr/__tests__/hmr.spec.ts +++ b/packages/plugin-react-swc/playground/hmr/__tests__/hmr.spec.ts @@ -1,9 +1,5 @@ import { expect, test } from '@playwright/test' -import { - setupBuildAndPreview, - setupDevServer, - setupWaitForLogs, -} from '../../utils.ts' +import { setupBuildAndPreview, setupDevServer, setupWaitForLogs } from '../../utils.ts' test('Default build', async ({ page }) => { const { testUrl, server } = await setupBuildAndPreview('hmr') @@ -41,10 +37,7 @@ test('HMR invalidate', async ({ page }) => { await expect(page.locator('h1')).toHaveText('Vite * React!') // Add non-component export - editFile('src/TitleWithExport.tsx', [ - "React!'", - "React!'\nexport const useless = 3", - ]) + editFile('src/TitleWithExport.tsx', ["React!'", "React!'\nexport const useless = 3"]) await waitForLogs( '[vite] invalidate /src/TitleWithExport.tsx: Could not Fast Refresh (new export)', '[vite] hot updated: /src/App.tsx', @@ -67,10 +60,7 @@ test('HMR invalidate', async ({ page }) => { await expect(page.locator('h2')).toHaveText('Title2') // Remove component export - editFile('src/TitleWithExport.tsx', [ - '\nexport const Title2 = () =>src/App.tsx and save to test HMR
- - Click on the Vite and {framework} logos to learn more -
+Click on the Vite and {framework} logos to learn more
) } diff --git a/packages/plugin-react-swc/playground/mdx/__tests__/mdx.spec.ts b/packages/plugin-react-swc/playground/mdx/__tests__/mdx.spec.ts index 41562b946..d42ebf710 100644 --- a/packages/plugin-react-swc/playground/mdx/__tests__/mdx.spec.ts +++ b/packages/plugin-react-swc/playground/mdx/__tests__/mdx.spec.ts @@ -1,9 +1,5 @@ import { expect, test } from '@playwright/test' -import { - setupBuildAndPreview, - setupDevServer, - setupWaitForLogs, -} from '../../utils.ts' +import { setupBuildAndPreview, setupDevServer, setupWaitForLogs } from '../../utils.ts' test('MDX build', async ({ page }) => { const { testUrl, server } = await setupBuildAndPreview('mdx') diff --git a/packages/plugin-react-swc/playground/react-18/__tests__/react-18.spec.ts b/packages/plugin-react-swc/playground/react-18/__tests__/react-18.spec.ts index 2902307fc..7642fc58e 100644 --- a/packages/plugin-react-swc/playground/react-18/__tests__/react-18.spec.ts +++ b/packages/plugin-react-swc/playground/react-18/__tests__/react-18.spec.ts @@ -1,9 +1,5 @@ import { expect, test } from '@playwright/test' -import { - setupBuildAndPreview, - setupDevServer, - setupWaitForLogs, -} from '../../utils.ts' +import { setupBuildAndPreview, setupDevServer, setupWaitForLogs } from '../../utils.ts' test('Default build', async ({ page }) => { const { testUrl, server } = await setupBuildAndPreview('react-18') @@ -41,10 +37,7 @@ test('HMR invalidate', async ({ page }) => { await expect(page.locator('h1')).toHaveText('Vite * React!') // Add non-component export - editFile('src/TitleWithExport.tsx', [ - "React!'", - "React!'\nexport const useless = 3", - ]) + editFile('src/TitleWithExport.tsx', ["React!'", "React!'\nexport const useless = 3"]) await waitForLogs( '[vite] invalidate /src/TitleWithExport.tsx: Could not Fast Refresh (new export)', '[vite] hot updated: /src/App.tsx', @@ -67,10 +60,7 @@ test('HMR invalidate', async ({ page }) => { await expect(page.locator('h2')).toHaveText('Title2') // Remove component export - editFile('src/TitleWithExport.tsx', [ - '\nexport const Title2 = () =>src/App.tsx and save to test HMR
- - Click on the Vite and {framework} logos to learn more -
+Click on the Vite and {framework} logos to learn more
) } diff --git a/packages/plugin-react-swc/playground/styled-components/__tests__/styled-components.spec.ts b/packages/plugin-react-swc/playground/styled-components/__tests__/styled-components.spec.ts index da8e44713..697af5184 100644 --- a/packages/plugin-react-swc/playground/styled-components/__tests__/styled-components.spec.ts +++ b/packages/plugin-react-swc/playground/styled-components/__tests__/styled-components.spec.ts @@ -1,10 +1,5 @@ import { expect, test } from '@playwright/test' -import { - expectColor, - setupBuildAndPreview, - setupDevServer, - setupWaitForLogs, -} from '../../utils.ts' +import { expectColor, setupBuildAndPreview, setupDevServer, setupWaitForLogs } from '../../utils.ts' test('styled-components build', async ({ page }) => { const { testUrl, server } = await setupBuildAndPreview('styled-components') @@ -23,8 +18,7 @@ test('styled-components build', async ({ page }) => { }) test('styled-components HMR', async ({ page }) => { - const { testUrl, server, editFile } = - await setupDevServer('styled-components') + const { testUrl, server, editFile } = await setupDevServer('styled-components') const waitForLogs = await setupWaitForLogs(page) await page.goto(testUrl) await waitForLogs('[vite] connected.') diff --git a/packages/plugin-react-swc/playground/styled-components/src/App.tsx b/packages/plugin-react-swc/playground/styled-components/src/App.tsx index f00df29ed..a63afea6a 100644 --- a/packages/plugin-react-swc/playground/styled-components/src/App.tsx +++ b/packages/plugin-react-swc/playground/styled-components/src/App.tsx @@ -21,8 +21,6 @@ export const App = () => ( Edit- Click on the Vite and Styled Components logos to learn more -
+Click on the Vite and Styled Components logos to learn more
) diff --git a/packages/plugin-react-swc/playground/utils.ts b/packages/plugin-react-swc/playground/utils.ts index 751b22f79..d059961e6 100644 --- a/packages/plugin-react-swc/playground/utils.ts +++ b/packages/plugin-react-swc/playground/utils.ts @@ -1,12 +1,6 @@ import { readFileSync, writeFileSync } from 'node:fs' import { type Locator, type Page, expect } from '@playwright/test' -import { - build, - createServer, - loadConfigFromFile, - mergeConfig, - preview, -} from 'vite' +import { build, createServer, loadConfigFromFile, mergeConfig, preview } from 'vite' export const setupWaitForLogs = async (page: Page) => { let logs: string[] = [] @@ -18,9 +12,7 @@ export const setupWaitForLogs = async (page: Page) => { .poll(() => { if ( messages.every((m) => - typeof m === 'string' - ? logs.includes(m) - : logs.some((l) => m.test(l)), + typeof m === 'string' ? logs.includes(m) : logs.some((l) => m.test(l)), ) ) { logs = [] @@ -35,11 +27,7 @@ let port = 5173 export const setupDevServer = async (name: string) => { process.env['NODE_ENV'] = 'development' const root = `playground-temp/${name}` - const res = await loadConfigFromFile( - { command: 'serve', mode: 'development' }, - undefined, - root, - ) + const res = await loadConfigFromFile({ command: 'serve', mode: 'development' }, undefined, root) const testConfig = mergeConfig(res!.config, { root, logLevel: 'silent', @@ -50,10 +38,7 @@ export const setupDevServer = async (name: string) => { return { testUrl: `http://localhost:${server.config.server.port}${server.config.base}`, server, - editFile: ( - name: string, - ...replacements: [searchValue: string, replaceValue: string][] - ) => { + editFile: (name: string, ...replacements: [searchValue: string, replaceValue: string][]) => { const path = `${root}/${name}` let content = readFileSync(path, 'utf-8') for (const [search, replace] of replacements) { @@ -70,11 +55,7 @@ export const setupDevServer = async (name: string) => { export const setupBuildAndPreview = async (name: string) => { process.env['NODE_ENV'] = 'production' const root = `playground-temp/${name}` - const res = await loadConfigFromFile( - { command: 'build', mode: 'production' }, - undefined, - root, - ) + const res = await loadConfigFromFile({ command: 'build', mode: 'production' }, undefined, root) const testConfig = mergeConfig( { root, logLevel: 'silent', configFile: false, preview: { port: port++ } }, res!.config, @@ -94,12 +75,7 @@ export const expectColor = async ( ) => { await expect .poll(async () => - rgbToHex( - await locator.evaluate( - (el, prop) => getComputedStyle(el)[prop], - property, - ), - ), + rgbToHex(await locator.evaluate((el, prop) => getComputedStyle(el)[prop], property)), ) .toBe(color) } diff --git a/packages/plugin-react-swc/playground/worker/__tests__/worker.spec.ts b/packages/plugin-react-swc/playground/worker/__tests__/worker.spec.ts index b0c7b2ce0..54b908df9 100644 --- a/packages/plugin-react-swc/playground/worker/__tests__/worker.spec.ts +++ b/packages/plugin-react-swc/playground/worker/__tests__/worker.spec.ts @@ -1,9 +1,5 @@ import { test } from '@playwright/test' -import { - setupBuildAndPreview, - setupDevServer, - setupWaitForLogs, -} from '../../utils.ts' +import { setupBuildAndPreview, setupDevServer, setupWaitForLogs } from '../../utils.ts' test('Worker build', async ({ page }) => { const { testUrl, server } = await setupBuildAndPreview('worker') diff --git a/packages/plugin-react-swc/playwright.config.ts b/packages/plugin-react-swc/playwright.config.ts index d7c8ae487..a3b666818 100644 --- a/packages/plugin-react-swc/playwright.config.ts +++ b/packages/plugin-react-swc/playwright.config.ts @@ -8,11 +8,7 @@ fs.emptyDirSync(tempDir) fs.copySync(fileURLToPath(new URL('playground', import.meta.url)), tempDir, { filter: (src) => { src = src.replaceAll('\\', '/') - return ( - !src.includes('/__tests__') && - !src.includes('/.vite') && - !src.includes('/dist') - ) + return !src.includes('/__tests__') && !src.includes('/.vite') && !src.includes('/dist') }, }) diff --git a/packages/plugin-react-swc/src/index.ts b/packages/plugin-react-swc/src/index.ts index ce875d6a5..94d6c35dd 100644 --- a/packages/plugin-react-swc/src/index.ts +++ b/packages/plugin-react-swc/src/index.ts @@ -86,8 +86,7 @@ const react = (_options?: Options): Plugin[] => { devTarget: _options?.devTarget ?? 'es2020', parserConfig: _options?.parserConfig, reactRefreshHost: _options?.reactRefreshHost, - useAtYourOwnRisk_mutateSwcOptions: - _options?.useAtYourOwnRisk_mutateSwcOptions, + useAtYourOwnRisk_mutateSwcOptions: _options?.useAtYourOwnRisk_mutateSwcOptions, disableOxcRecommendation: _options?.disableOxcRecommendation, } @@ -136,17 +135,12 @@ const react = (_options?: Options): Plugin[] => { configResolved(config) { viteCacheRoot = config.cacheDir hmrDisabled = config.server.hmr === false - const mdxIndex = config.plugins.findIndex( - (p) => p.name === '@mdx-js/rollup', - ) + const mdxIndex = config.plugins.findIndex((p) => p.name === '@mdx-js/rollup') if ( mdxIndex !== -1 && - mdxIndex > - config.plugins.findIndex((p) => p.name === 'vite:react-swc') + mdxIndex > config.plugins.findIndex((p) => p.name === 'vite:react-swc') ) { - throw new Error( - '[vite:react-swc] The MDX plugin should be placed before this plugin', - ) + throw new Error('[vite:react-swc] The MDX plugin should be placed before this plugin') } if ( @@ -212,17 +206,10 @@ const react = (_options?: Options): Plugin[] => { viteCacheRoot = config.cacheDir }, transform: (code, _id) => - transformWithOptions( - _id.split('?')[0], - code, - 'esnext', - options, - viteCacheRoot, - { - runtime: 'automatic', - importSource: options.jsxImportSource, - }, - ), + transformWithOptions(_id.split('?')[0], code, 'esnext', options, viteCacheRoot, { + runtime: 'automatic', + importSource: options.jsxImportSource, + }), } : { name: 'vite:react-swc', diff --git a/packages/plugin-react-swc/tsdown.config.ts b/packages/plugin-react-swc/tsdown.config.ts index fe0288561..693bed792 100644 --- a/packages/plugin-react-swc/tsdown.config.ts +++ b/packages/plugin-react-swc/tsdown.config.ts @@ -33,10 +33,7 @@ export default defineConfig({ { ...Object.fromEntries( Object.entries(packageJSON).filter( - ([key, _val]) => - key !== 'devDependencies' && - key !== 'scripts' && - key !== 'private', + ([key, _val]) => key !== 'devDependencies' && key !== 'scripts' && key !== 'private', ), ), exports: { diff --git a/packages/plugin-react/src/index.ts b/packages/plugin-react/src/index.ts index 9b4d66140..ab58880a1 100644 --- a/packages/plugin-react/src/index.ts +++ b/packages/plugin-react/src/index.ts @@ -14,10 +14,7 @@ import { silenceUseClientWarning, virtualPreamblePlugin, } from '@vitejs/react-common' -import { - exactRegex, - makeIdFiltersToMatchWithQuery, -} from '@rolldown/pluginutils' +import { exactRegex, makeIdFiltersToMatchWithQuery } from '@rolldown/pluginutils' const _dirname = dirname(fileURLToPath(import.meta.url)) const refreshRuntimePath = join(_dirname, 'refresh-runtime.js') @@ -48,9 +45,7 @@ export interface Options { /** * Babel configuration applied in both dev and prod. */ - babel?: - | BabelOptions - | ((id: string, options: { ssr?: boolean }) => BabelOptions) + babel?: BabelOptions | ((id: string, options: { ssr?: boolean }) => BabelOptions) /** * React Fast Refresh runtime URL prefix. * Useful in a module federation context to enable HMR by specifying @@ -63,12 +58,7 @@ export interface Options { export type BabelOptions = Omit< TransformOptions, - | 'ast' - | 'filename' - | 'root' - | 'sourceFileName' - | 'sourceMaps' - | 'inputSourceMap' + 'ast' | 'filename' | 'root' | 'sourceFileName' | 'sourceMaps' | 'inputSourceMap' > /** @@ -196,10 +186,7 @@ export default function viteReact(opts: Options = {}): Plugin[] { } projectRoot = config.root isProduction = config.isProduction - skipFastRefresh = - isProduction || - config.command === 'build' || - config.server.hmr === false + skipFastRefresh = isProduction || config.command === 'build' || config.server.hmr === false const hooks: ReactBabelHook[] = config.plugins .map((plugin) => plugin.api?.reactBabel) @@ -253,9 +240,7 @@ export default function viteReact(opts: Options = {}): Plugin[] { const babelOptions = (() => { if (staticBabelOptions) return staticBabelOptions const newBabelOptions = createBabelOptions( - typeof opts.babel === 'function' - ? opts.babel(id, { ssr }) - : opts.babel, + typeof opts.babel === 'function' ? opts.babel(id, { ssr }) : opts.babel, ) runPluginOverrides?.(newBabelOptions, { id, ssr }) return newBabelOptions @@ -287,13 +272,9 @@ export default function viteReact(opts: Options = {}): Plugin[] { (isJSX || (opts.jsxRuntime === 'classic' ? importReactRE.test(code) - : code.includes(jsxImportDevRuntime) || - code.includes(jsxImportRuntime))) + : code.includes(jsxImportDevRuntime) || code.includes(jsxImportRuntime))) if (useFastRefresh) { - plugins.push([ - await loadPlugin('react-refresh/babel'), - { skipEnvCheck: true }, - ]) + plugins.push([await loadPlugin('react-refresh/babel'), { skipEnvCheck: true }]) } if (opts.jsxRuntime === 'classic' && isJSX) { @@ -378,13 +359,9 @@ export default function viteReact(opts: Options = {}): Plugin[] { try { // NOTE: `+` is to bypass lint & typecheck. vite/internal exists for newer rolldown-vite const vite = 'vite' - nativePlugin = (await import(vite + '/internal')) - .reactRefreshWrapperPlugin + nativePlugin = (await import(vite + '/internal')).reactRefreshWrapperPlugin } catch {} - if ( - !nativePlugin || - ['7.1.10', '7.1.11', '7.1.12'].includes(vite.version) - ) { + if (!nativePlugin || ['7.1.10', '7.1.11', '7.1.12'].includes(vite.version)) { // the native plugin in 7.1.10 and 7.1.11 and 7.1.12 does not support dev properly return true } @@ -415,17 +392,10 @@ export default function viteReact(opts: Options = {}): Plugin[] { const useFastRefresh = !skipFastRefresh && !ssr && - (isJSX || - code.includes(jsxImportDevRuntime) || - code.includes(jsxImportRuntime)) + (isJSX || code.includes(jsxImportDevRuntime) || code.includes(jsxImportRuntime)) if (!useFastRefresh) return - const newCode = addRefreshWrapper( - code, - '@vitejs/plugin-react', - id, - opts.reactRefreshHost, - ) + const newCode = addRefreshWrapper(code, '@vitejs/plugin-react', id, opts.reactRefreshHost) return newCode ? { code: newCode, map: null } : undefined }, }, @@ -470,18 +440,11 @@ export default function viteReact(opts: Options = {}): Plugin[] { }, } - const dependencies = [ - 'react', - 'react-dom', - jsxImportDevRuntime, - jsxImportRuntime, - ] - const staticBabelPlugins = - typeof opts.babel === 'object' ? (opts.babel?.plugins ?? []) : [] + const dependencies = ['react', 'react-dom', jsxImportDevRuntime, jsxImportRuntime] + const staticBabelPlugins = typeof opts.babel === 'object' ? (opts.babel?.plugins ?? []) : [] const reactCompilerPlugin = getReactCompilerPlugin(staticBabelPlugins) if (reactCompilerPlugin != null) { - const reactCompilerRuntimeModule = - getReactCompilerRuntimeModule(reactCompilerPlugin) + const reactCompilerRuntimeModule = getReactCompilerRuntimeModule(reactCompilerPlugin) dependencies.push(reactCompilerRuntimeModule) } @@ -527,9 +490,7 @@ export default function viteReact(opts: Options = {}): Plugin[] { return [ viteBabel, - ...(isRolldownVite - ? [viteRefreshWrapper, viteConfigPost, viteReactRefreshFullBundleMode] - : []), + ...(isRolldownVite ? [viteRefreshWrapper, viteConfigPost, viteReactRefreshFullBundleMode] : []), viteReactRefresh, virtualPreamblePlugin({ name: '@vitejs/plugin-react/preamble', @@ -549,10 +510,7 @@ Object.assign(viteReactForCjs, { }) export { viteReactForCjs as 'module.exports' } -function canSkipBabel( - plugins: ReactBabelOptions['plugins'], - babelOptions: ReactBabelOptions, -) { +function canSkipBabel(plugins: ReactBabelOptions['plugins'], babelOptions: ReactBabelOptions) { return !( plugins.length || babelOptions.presets.length || @@ -606,9 +564,7 @@ function getReactCompilerPlugin(plugins: ReactBabelOptions['plugins']) { type ReactCompilerRuntimeModule = | 'react/compiler-runtime' // from react namespace | 'react-compiler-runtime' // npm package -function getReactCompilerRuntimeModule( - plugin: babelCore.PluginItem, -): ReactCompilerRuntimeModule { +function getReactCompilerRuntimeModule(plugin: babelCore.PluginItem): ReactCompilerRuntimeModule { let moduleName: ReactCompilerRuntimeModule = 'react/compiler-runtime' if (Array.isArray(plugin)) { if (plugin[1]?.target === '17' || plugin[1]?.target === '18') { diff --git a/packages/plugin-rsc/e2e/base.test.ts b/packages/plugin-rsc/e2e/base.test.ts index 1f651b9d0..b9e7d511e 100644 --- a/packages/plugin-rsc/e2e/base.test.ts +++ b/packages/plugin-rsc/e2e/base.test.ts @@ -49,9 +49,7 @@ test.describe(() => { test('request url', async ({ page }) => { await page.goto(f.url()) await page.waitForSelector('#root') - await expect(page.locator('.card').nth(2)).toHaveText( - `Request URL: ${f.url()}`, - ) + await expect(page.locator('.card').nth(2)).toHaveText(`Request URL: ${f.url()}`) }) } }) diff --git a/packages/plugin-rsc/e2e/basic.test.ts b/packages/plugin-rsc/e2e/basic.test.ts index c7ca7c50b..a8abec500 100644 --- a/packages/plugin-rsc/e2e/basic.test.ts +++ b/packages/plugin-rsc/e2e/basic.test.ts @@ -1,18 +1,8 @@ import { createHash } from 'node:crypto' import { readFileSync } from 'node:fs' -import { - type Page, - type Response as PlaywrightResponse, - expect, - test, -} from '@playwright/test' +import { type Page, type Response as PlaywrightResponse, expect, test } from '@playwright/test' import { type Fixture, useCreateEditor, useFixture } from './fixture' -import { - expectNoPageError, - expectNoReload, - testNoJs, - waitForHydration, -} from './helper' +import { expectNoPageError, expectNoReload, testNoJs, waitForHydration } from './helper' import { x } from 'tinyexec' import { normalizePath, type Rollup } from 'vite' import path from 'node:path' @@ -28,14 +18,8 @@ test.describe('dev-initial', () => { // verify css is collected properly on server startup (i.e. empty module graph) testNoJs('style', async ({ page }) => { await page.goto(f.url('./')) - await expect(page.locator('.test-style-client')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - ) - await expect(page.locator('.test-style-server')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - ) + await expect(page.locator('.test-style-client')).toHaveCSS('color', 'rgb(255, 165, 0)') + await expect(page.locator('.test-style-server')).toHaveCSS('color', 'rgb(255, 165, 0)') await expect(page.locator('.test-tw-client')).toHaveCSS( 'color', // blue-500 @@ -107,10 +91,7 @@ test.describe('dev-non-optimized-cjs', () => { // remove explicitly added optimizeDeps.include const editor = f.createEditor('vite.config.ts') editor.edit((s) => - s.replace( - `include: ['@vitejs/test-dep-transitive-cjs > @vitejs/test-dep-cjs'],`, - ``, - ), + s.replace(`include: ['@vitejs/test-dep-transitive-cjs > @vitejs/test-dep-cjs'],`, ``), ) }) @@ -136,9 +117,7 @@ test.describe('dev-inconsistent-client-optimization', () => { test.beforeAll(async () => { // remove explicitly added optimizeDeps.exclude const editor = f.createEditor('vite.config.ts') - editor.edit((s) => - s.replace(`'@vitejs/test-dep-client-in-server2/client',`, ``), - ) + editor.edit((s) => s.replace(`'@vitejs/test-dep-client-in-server2/client',`, ``)) }) const f = useFixture({ @@ -148,9 +127,7 @@ test.describe('dev-inconsistent-client-optimization', () => { test('show warning', async ({ page }) => { await page.goto(f.url()) - expect(f.proc().stderr()).toContain( - 'client component dependency is inconsistently optimized.', - ) + expect(f.proc().stderr()).toContain('client component dependency is inconsistently optimized.') }) }) @@ -234,13 +211,9 @@ function defineTest(f: Fixture) { async function testAction(page: Page) { await page.getByRole('button', { name: 'server-counter: 0' }).click() await page.getByRole('button', { name: 'server-counter: 1' }).click() - await expect( - page.getByRole('button', { name: 'server-counter: 2' }), - ).toBeVisible() + await expect(page.getByRole('button', { name: 'server-counter: 2' })).toBeVisible() await page.getByRole('button', { name: 'server-counter-reset' }).click() - await expect( - page.getByRole('button', { name: 'server-counter: 0' }), - ).toBeVisible() + await expect(page.getByRole('button', { name: 'server-counter: 0' })).toBeVisible() } test('useActionState @js', async ({ page }) => { @@ -274,13 +247,9 @@ function defineTest(f: Fixture) { // no js js = false await page.goto(f.url()) - await expect(page.getByTestId('use-action-state')).toContainText( - 'test-useActionState: 0', - ) + await expect(page.getByTestId('use-action-state')).toContainText('test-useActionState: 0') await page.getByTestId('use-action-state').click() - await expect(page.getByTestId('use-action-state')).toContainText( - 'test-useActionState: 1', - ) + await expect(page.getByTestId('use-action-state')).toContainText('test-useActionState: 1') // with js (hydration) js = true @@ -292,17 +261,11 @@ function defineTest(f: Fixture) { }) async function testUseActionState(page: Page) { - await expect(page.getByTestId('use-action-state')).toContainText( - 'test-useActionState: 0', - ) + await expect(page.getByTestId('use-action-state')).toContainText('test-useActionState: 0') await page.getByTestId('use-action-state').click() - await expect(page.getByTestId('use-action-state')).toContainText( - 'test-useActionState: 1', - ) + await expect(page.getByTestId('use-action-state')).toContainText('test-useActionState: 1') await page.getByTestId('use-action-state').click() - await expect(page.getByTestId('use-action-state')).toContainText( - 'test-useActionState: 2', - ) + await expect(page.getByTestId('use-action-state')).toContainText('test-useActionState: 2') } test('useActionState with jsx @js', async ({ page }) => { @@ -319,9 +282,7 @@ function defineTest(f: Fixture) { async function testUseActionStateJsx(page: Page, options?: { js?: boolean }) { await page.getByTestId('use-action-state-jsx').getByRole('button').click() - await expect(page.getByTestId('use-action-state-jsx')).toContainText( - /\(ok\)/, - ) + await expect(page.getByTestId('use-action-state-jsx')).toContainText(/\(ok\)/) // 1st call "works" but it shows an error during reponse and it breaks 2nd call. // Failed to serialize an action for progressive enhancement: @@ -330,9 +291,7 @@ function defineTest(f: Fixture) { if (!options?.js) return await page.getByTestId('use-action-state-jsx').getByRole('button').click() - await expect(page.getByTestId('use-action-state-jsx')).toContainText( - /\(ok\).*\(ok\)/, - ) + await expect(page.getByTestId('use-action-state-jsx')).toContainText(/\(ok\).*\(ok\)/) } test.describe(() => { @@ -342,19 +301,15 @@ function defineTest(f: Fixture) { await page.goto(f.url()) const srcs = await page .locator(`head >> link[rel="modulepreload"]`) - .evaluateAll((elements) => - elements.map((el) => el.getAttribute('href')), - ) + .evaluateAll((elements) => elements.map((el) => el.getAttribute('href'))) const manifest = JSON.parse( - readFileSync( - f.root + '/dist/ssr/__vite_rsc_assets_manifest.js', - 'utf-8', - ).slice('export default '.length), + readFileSync(f.root + '/dist/ssr/__vite_rsc_assets_manifest.js', 'utf-8').slice( + 'export default '.length, + ), ) const hashString = (v: string) => createHash('sha256').update(v).digest().toString('hex').slice(0, 12) - const deps = - manifest.clientReferenceDeps[hashString('src/routes/client.tsx')] + const deps = manifest.clientReferenceDeps[hashString('src/routes/client.tsx')] expect(srcs).toEqual(expect.arrayContaining(deps.js)) }) }) @@ -377,33 +332,27 @@ function defineTest(f: Fixture) { async function testServerActionUpdate(page: Page, options: { js: boolean }) { await page.getByRole('button', { name: 'server-counter: 0' }).click() - await expect( - page.getByRole('button', { name: 'server-counter: 1' }), - ).toBeVisible() + await expect(page.getByRole('button', { name: 'server-counter: 1' })).toBeVisible() // update server code const editor = f.createEditor('src/routes/action/action.tsx') - editor.edit((s) => - s.replace('const TEST_UPDATE = 1\n', 'const TEST_UPDATE = 10\n'), - ) + editor.edit((s) => s.replace('const TEST_UPDATE = 1\n', 'const TEST_UPDATE = 10\n')) await expect(async () => { if (!options.js) await page.goto(f.url()) - await expect( - page.getByRole('button', { name: 'server-counter: 0' }), - ).toBeVisible({ timeout: 10 }) + await expect(page.getByRole('button', { name: 'server-counter: 0' })).toBeVisible({ + timeout: 10, + }) }).toPass() await page.getByRole('button', { name: 'server-counter: 0' }).click() - await expect( - page.getByRole('button', { name: 'server-counter: 10' }), - ).toBeVisible() + await expect(page.getByRole('button', { name: 'server-counter: 10' })).toBeVisible() editor.reset() await expect(async () => { if (!options.js) await page.goto(f.url()) - await expect( - page.getByRole('button', { name: 'server-counter: 0' }), - ).toBeVisible({ timeout: 10 }) + await expect(page.getByRole('button', { name: 'server-counter: 0' })).toBeVisible({ + timeout: 10, + }) }).toPass() } @@ -414,15 +363,11 @@ function defineTest(f: Fixture) { await page.goto(f.url()) await waitForHydration(page) await page.getByRole('button', { name: 'client-counter: 0' }).click() - await expect( - page.getByRole('button', { name: 'client-counter: 1' }), - ).toBeVisible() + await expect(page.getByRole('button', { name: 'client-counter: 1' })).toBeVisible() const editor = f.createEditor('src/routes/client.tsx') editor.edit((s) => s.replace('client-counter', 'client-[edit]-counter')) - await expect( - page.getByRole('button', { name: 'client-[edit]-counter: 1' }), - ).toBeVisible() + await expect(page.getByRole('button', { name: 'client-[edit]-counter: 1' })).toBeVisible() // check next ssr is also updated const res = await page.goto(f.url()) @@ -447,9 +392,9 @@ function defineTest(f: Fixture) { // check next rsc payload includes current client reference and preserves state await page.locator("a[href='?test-hmr-client-dep-re-render']").click() - await expect( - page.locator("a[href='?test-hmr-client-dep-re-render']"), - ).toHaveText('re-render [ok]') + await expect(page.locator("a[href='?test-hmr-client-dep-re-render']")).toHaveText( + 're-render [ok]', + ) await expect(locator).toHaveText('test-hmr-client-dep: 1[ok-edit]') // check next ssr is also updated @@ -479,9 +424,9 @@ function defineTest(f: Fixture) { // check next rsc payload includes an updated client reference and preserves state await page.locator("a[href='?test-hmr-client-dep2-re-render']").click() - await expect( - page.locator("a[href='?test-hmr-client-dep2-re-render']"), - ).toHaveText('re-render [ok]') + await expect(page.locator("a[href='?test-hmr-client-dep2-re-render']")).toHaveText( + 're-render [ok]', + ) await expect(locator).toHaveText('test-hmr-client-dep2: 1[ok-edit]') // check next ssr is also updated @@ -502,13 +447,9 @@ function defineTest(f: Fixture) { await using _ = await expectNoReload(page) const editor = f.createEditor('src/routes/action/server.tsx') editor.edit((s) => s.replace('server-counter', 'server-[edit]-counter')) - await expect( - page.getByRole('button', { name: 'server-[edit]-counter: 0' }), - ).toBeVisible() + await expect(page.getByRole('button', { name: 'server-[edit]-counter: 0' })).toBeVisible() editor.reset() - await expect( - page.getByRole('button', { name: 'server-counter: 0' }), - ).toBeVisible() + await expect(page.getByRole('button', { name: 'server-counter: 0' })).toBeVisible() }) test('module invalidation', async ({ page }) => { @@ -538,12 +479,8 @@ function defineTest(f: Fixture) { await using _ = await expectNoReload(page) // Test initial state - await expect(page.getByTestId('test-hmr-shared-server')).toContainText( - '(shared1, shared2)', - ) - await expect(page.getByTestId('test-hmr-shared-client')).toContainText( - '(shared1, shared2)', - ) + await expect(page.getByTestId('test-hmr-shared-server')).toContainText('(shared1, shared2)') + await expect(page.getByTestId('test-hmr-shared-client')).toContainText('(shared1, shared2)') // Test 1: Component HMR (shared1.tsx) const editor1 = f.createEditor('src/routes/hmr-shared/shared1.tsx') @@ -558,12 +495,8 @@ function defineTest(f: Fixture) { ) editor1.reset() - await expect(page.getByTestId('test-hmr-shared-server')).toContainText( - '(shared1, shared2)', - ) - await expect(page.getByTestId('test-hmr-shared-client')).toContainText( - '(shared1, shared2)', - ) + await expect(page.getByTestId('test-hmr-shared-server')).toContainText('(shared1, shared2)') + await expect(page.getByTestId('test-hmr-shared-client')).toContainText('(shared1, shared2)') // Test 2: Non-component HMR (shared2.tsx) const editor2 = f.createEditor('src/routes/hmr-shared/shared2.tsx') @@ -578,12 +511,8 @@ function defineTest(f: Fixture) { ) editor2.reset() - await expect(page.getByTestId('test-hmr-shared-server')).toContainText( - '(shared1, shared2)', - ) - await expect(page.getByTestId('test-hmr-shared-client')).toContainText( - '(shared1, shared2)', - ) + await expect(page.getByTestId('test-hmr-shared-server')).toContainText('(shared1, shared2)') + await expect(page.getByTestId('test-hmr-shared-client')).toContainText('(shared1, shared2)') }) // for this use case to work, server refetch/render and client hmr needs to applied atomically @@ -592,25 +521,19 @@ function defineTest(f: Fixture) { test('shared hmr not atomic', async ({ page }) => { await page.goto(f.url()) await waitForHydration(page) - await expect(page.getByTestId('test-hmr-shared-atomic')).toContainText( - 'ok (test-shared)', - ) + await expect(page.getByTestId('test-hmr-shared-atomic')).toContainText('ok (test-shared)') // non-atomic update causes an error const editor = f.createEditor('src/routes/hmr-shared/atomic/shared.tsx') editor.edit((s) => s.replace('test-shared', 'test-shared-edit')) - await expect(page.getByTestId('test-hmr-shared-atomic')).toContainText( - 'ErrorBoundary', - ) + await expect(page.getByTestId('test-hmr-shared-atomic')).toContainText('ErrorBoundary') await page.reload() await expect(page.getByText('ok (test-shared-edit)')).toBeVisible() // non-atomic update causes an error editor.reset() - await expect(page.getByTestId('test-hmr-shared-atomic')).toContainText( - 'ErrorBoundary', - ) + await expect(page.getByTestId('test-hmr-shared-atomic')).toContainText('ErrorBoundary') await page.reload() await expect(page.getByText('ok (test-shared)')).toBeVisible() @@ -621,20 +544,14 @@ function defineTest(f: Fixture) { await waitForHydration(page) await using _ = await expectNoReload(page) - await expect(page.getByTestId('test-hmr-switch-server')).toContainText( - '(useState: false)', - ) + await expect(page.getByTestId('test-hmr-switch-server')).toContainText('(useState: false)') const editor = f.createEditor('src/routes/hmr-switch/server.tsx') editor.edit((s) => `"use client";\n` + s) - await expect(page.getByTestId('test-hmr-switch-server')).toContainText( - '(useState: true)', - ) + await expect(page.getByTestId('test-hmr-switch-server')).toContainText('(useState: true)') await page.waitForTimeout(100) editor.reset() - await expect(page.getByTestId('test-hmr-switch-server')).toContainText( - '(useState: false)', - ) + await expect(page.getByTestId('test-hmr-switch-server')).toContainText('(useState: false)') }) test('hmr switch client to server', async ({ page }) => { @@ -642,20 +559,14 @@ function defineTest(f: Fixture) { await waitForHydration(page) await using _ = await expectNoReload(page) - await expect(page.getByTestId('test-hmr-switch-client')).toContainText( - '(useState: true)', - ) + await expect(page.getByTestId('test-hmr-switch-client')).toContainText('(useState: true)') const editor = f.createEditor('src/routes/hmr-switch/client.tsx') editor.edit((s) => s.replace(`'use client'`, '')) - await expect(page.getByTestId('test-hmr-switch-client')).toContainText( - '(useState: false)', - ) + await expect(page.getByTestId('test-hmr-switch-client')).toContainText('(useState: false)') await page.waitForTimeout(100) editor.reset() - await expect(page.getByTestId('test-hmr-switch-client')).toContainText( - '(useState: true)', - ) + await expect(page.getByTestId('test-hmr-switch-client')).toContainText('(useState: true)') }) }) @@ -672,30 +583,12 @@ function defineTest(f: Fixture) { async function testCssBasic(page: Page) { await testCss(page) - await expect(page.locator('.test-dep-css-in-server')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - ) - await expect(page.locator('.test-style-server-manual')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - ) - await expect(page.getByTestId('css-module-client')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - ) - await expect(page.getByTestId('css-module-server')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - ) - await expect(page.locator('.test-style-url-client')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - ) - await expect(page.locator('.test-style-url-server')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - ) + await expect(page.locator('.test-dep-css-in-server')).toHaveCSS('color', 'rgb(255, 165, 0)') + await expect(page.locator('.test-style-server-manual')).toHaveCSS('color', 'rgb(255, 165, 0)') + await expect(page.getByTestId('css-module-client')).toHaveCSS('color', 'rgb(255, 165, 0)') + await expect(page.getByTestId('css-module-server')).toHaveCSS('color', 'rgb(255, 165, 0)') + await expect(page.locator('.test-style-url-client')).toHaveCSS('color', 'rgb(255, 165, 0)') + await expect(page.locator('.test-style-url-server')).toHaveCSS('color', 'rgb(255, 165, 0)') } async function testCss(page: Page, color = 'rgb(255, 165, 0)') { @@ -713,50 +606,28 @@ function defineTest(f: Fixture) { await using _ = await expectNoReload(page) const editor = f.createEditor('src/routes/style-client/client.css') editor.edit((s) => s.replaceAll('rgb(255, 165, 0)', 'rgb(0, 165, 255)')) - await expect(page.locator('.test-style-client')).toHaveCSS( - 'color', - 'rgb(0, 165, 255)', - ) - editor.edit((s) => - s.replaceAll( - `color: rgb(0, 165, 255);`, - `/* color: rgb(0, 165, 255); */`, - ), - ) - await expect(page.locator('.test-style-client')).toHaveCSS( - 'color', - 'rgb(0, 0, 0)', - ) + await expect(page.locator('.test-style-client')).toHaveCSS('color', 'rgb(0, 165, 255)') + editor.edit((s) => s.replaceAll(`color: rgb(0, 165, 255);`, `/* color: rgb(0, 165, 255); */`)) + await expect(page.locator('.test-style-client')).toHaveCSS('color', 'rgb(0, 0, 0)') // wait longer for multiple edits await page.waitForTimeout(100) editor.reset() - await expect(page.locator('.test-style-client')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - ) + await expect(page.locator('.test-style-client')).toHaveCSS('color', 'rgb(255, 165, 0)') await expectNoDuplicateServerCss(page) }) async function expectNoDuplicateServerCss(page: Page) { // verify duplicate client-reference style link are removed await expect( - page.locator( - 'link[rel="stylesheet"][data-precedence="vite-rsc/client-reference"]', - ), + page.locator('link[rel="stylesheet"][data-precedence="vite-rsc/client-reference"]'), ).toHaveCount(0) await expect( page - .locator( - 'link[rel="stylesheet"][data-precedence="vite-rsc/importer-resources"]', - ) + .locator('link[rel="stylesheet"][data-precedence="vite-rsc/importer-resources"]') .nth(0), ).toBeAttached() await expect( - page - .locator( - 'link[rel="stylesheet"][data-precedence="test-style-manual-link"]', - ) - .nth(0), + page.locator('link[rel="stylesheet"][data-precedence="test-style-manual-link"]').nth(0), ).toBeAttached() } @@ -778,31 +649,20 @@ function defineTest(f: Fixture) { await testAddRemoveCssClient(page, { js: false }) }) - async function testAddRemoveCssClient( - page: Page, - options: { js: boolean }, - ) { - await expect(page.locator('.test-style-client-dep')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - ) + async function testAddRemoveCssClient(page: Page, options: { js: boolean }) { + await expect(page.locator('.test-style-client-dep')).toHaveCSS('color', 'rgb(255, 165, 0)') // remove css import const editor = f.createEditor('src/routes/style-client/client-dep.tsx') editor.edit((s) => - s.replaceAll( - `import './client-dep.css'`, - `/* import './client-dep.css' */`, - ), + s.replaceAll(`import './client-dep.css'`, `/* import './client-dep.css' */`), ) await page.waitForTimeout(100) await expect(async () => { if (!options.js) await page.reload() - await expect(page.locator('.test-style-client-dep')).toHaveCSS( - 'color', - 'rgb(0, 0, 0)', - { timeout: 10 }, - ) + await expect(page.locator('.test-style-client-dep')).toHaveCSS('color', 'rgb(0, 0, 0)', { + timeout: 10, + }) }).toPass() // add back css import @@ -825,29 +685,12 @@ function defineTest(f: Fixture) { await using _ = await expectNoReload(page) const editor = f.createEditor('src/routes/style-server/server.css') editor.edit((s) => s.replaceAll('rgb(255, 165, 0)', 'rgb(0, 165, 255)')) - await expect(page.locator('.test-style-server')).toHaveCSS( - 'color', - 'rgb(0, 165, 255)', - ) - editor.edit((s) => - s.replaceAll( - `color: rgb(0, 165, 255);`, - `/* color: rgb(0, 165, 255); */`, - ), - ) - await expect(page.locator('.test-style-server')).toHaveCSS( - 'color', - 'rgb(0, 0, 0)', - ) + await expect(page.locator('.test-style-server')).toHaveCSS('color', 'rgb(0, 165, 255)') + editor.edit((s) => s.replaceAll(`color: rgb(0, 165, 255);`, `/* color: rgb(0, 165, 255); */`)) + await expect(page.locator('.test-style-server')).toHaveCSS('color', 'rgb(0, 0, 0)') editor.reset() - await expect(page.locator('.test-style-server')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - ) - await expect(page.locator('.test-style-server-manual')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - ) + await expect(page.locator('.test-style-server')).toHaveCSS('color', 'rgb(255, 165, 0)') + await expect(page.locator('.test-style-server-manual')).toHaveCSS('color', 'rgb(255, 165, 0)') await expectNoDuplicateServerCss(page) }) @@ -855,10 +698,7 @@ function defineTest(f: Fixture) { test('adding/removing css server @js', async ({ page }) => { await page.goto(f.url()) await waitForHydration(page) - await expect(page.locator('.test-style-server')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - ) + await expect(page.locator('.test-style-server')).toHaveCSS('color', 'rgb(255, 165, 0)') const editor = f.createEditor('src/routes/style-server/server.tsx') @@ -867,22 +707,12 @@ function defineTest(f: Fixture) { await using _ = await expectNoReload(page) // remove css import - editor.edit((s) => - s.replaceAll(`import './server.css'`, `/* import './server.css' */`), - ) - await expect(page.locator('.test-style-server')).toHaveCSS( - 'color', - 'rgb(0, 0, 0)', - ) + editor.edit((s) => s.replaceAll(`import './server.css'`, `/* import './server.css' */`)) + await expect(page.locator('.test-style-server')).toHaveCSS('color', 'rgb(0, 0, 0)') // add new css - editor.edit((s) => - s.replaceAll(`/* import './server.css' */`, `import './server2.css'`), - ) - await expect(page.locator('.test-style-server')).toHaveCSS( - 'color', - 'rgb(0, 255, 165)', - ) + editor.edit((s) => s.replaceAll(`/* import './server.css' */`, `import './server2.css'`)) + await expect(page.locator('.test-style-server')).toHaveCSS('color', 'rgb(0, 255, 165)') } // TODO: React doesn't re-inert same css link. so manual reload is required. @@ -890,11 +720,9 @@ function defineTest(f: Fixture) { await page.waitForTimeout(100) await expect(async () => { await page.reload() - await expect(page.locator('.test-style-server')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - { timeout: 10 }, - ) + await expect(page.locator('.test-style-server')).toHaveCSS('color', 'rgb(255, 165, 0)', { + timeout: 10, + }) }).toPass() }) @@ -903,28 +731,18 @@ function defineTest(f: Fixture) { await testAddRemoveCssServer(page, { js: false }) }) - async function testAddRemoveCssServer( - page: Page, - options: { js: boolean }, - ) { - await expect(page.locator('.test-style-server')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - ) + async function testAddRemoveCssServer(page: Page, options: { js: boolean }) { + await expect(page.locator('.test-style-server')).toHaveCSS('color', 'rgb(255, 165, 0)') // remove css import const editor = f.createEditor('src/routes/style-server/server.tsx') - editor.edit((s) => - s.replaceAll(`import './server.css'`, `/* import './server.css' */`), - ) + editor.edit((s) => s.replaceAll(`import './server.css'`, `/* import './server.css' */`)) await page.waitForTimeout(100) await expect(async () => { if (!options.js) await page.reload() - await expect(page.locator('.test-style-server')).toHaveCSS( - 'color', - 'rgb(0, 0, 0)', - { timeout: 10 }, - ) + await expect(page.locator('.test-style-server')).toHaveCSS('color', 'rgb(0, 0, 0)', { + timeout: 10, + }) }).toPass() // add back css import @@ -932,11 +750,9 @@ function defineTest(f: Fixture) { await page.waitForTimeout(100) await expect(async () => { if (!options.js) await page.reload() - await expect(page.locator('.test-style-server')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - { timeout: 10 }, - ) + await expect(page.locator('.test-style-server')).toHaveCSS('color', 'rgb(255, 165, 0)', { + timeout: 10, + }) }).toPass() } @@ -946,15 +762,9 @@ function defineTest(f: Fixture) { await using _ = await expectNoReload(page) const editor = f.createEditor('src/routes/style-client/client.module.css') editor.edit((s) => s.replaceAll('rgb(255, 165, 0)', 'rgb(0, 165, 255)')) - await expect(page.getByTestId('css-module-client')).toHaveCSS( - 'color', - 'rgb(0, 165, 255)', - ) + await expect(page.getByTestId('css-module-client')).toHaveCSS('color', 'rgb(0, 165, 255)') editor.reset() - await expect(page.getByTestId('css-module-client')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - ) + await expect(page.getByTestId('css-module-client')).toHaveCSS('color', 'rgb(255, 165, 0)') }) test('css module server hmr', async ({ page }) => { @@ -963,15 +773,9 @@ function defineTest(f: Fixture) { await using _ = await expectNoReload(page) const editor = f.createEditor('src/routes/style-server/server.module.css') editor.edit((s) => s.replaceAll('rgb(255, 165, 0)', 'rgb(0, 165, 255)')) - await expect(page.getByTestId('css-module-server')).toHaveCSS( - 'color', - 'rgb(0, 165, 255)', - ) + await expect(page.getByTestId('css-module-server')).toHaveCSS('color', 'rgb(0, 165, 255)') editor.reset() - await expect(page.getByTestId('css-module-server')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - ) + await expect(page.getByTestId('css-module-server')).toHaveCSS('color', 'rgb(255, 165, 0)') }) test('css url client hmr', async ({ page }) => { @@ -980,15 +784,9 @@ function defineTest(f: Fixture) { await using _ = await expectNoReload(page) const editor = f.createEditor('src/routes/style-client/client-url.css') editor.edit((s) => s.replaceAll('rgb(255, 165, 0)', 'rgb(0, 165, 255)')) - await expect(page.locator('.test-style-url-client')).toHaveCSS( - 'color', - 'rgb(0, 165, 255)', - ) + await expect(page.locator('.test-style-url-client')).toHaveCSS('color', 'rgb(0, 165, 255)') editor.reset() - await expect(page.locator('.test-style-url-client')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - ) + await expect(page.locator('.test-style-url-client')).toHaveCSS('color', 'rgb(255, 165, 0)') }) test('css url server hmr', async ({ page }) => { @@ -997,15 +795,9 @@ function defineTest(f: Fixture) { await using _ = await expectNoReload(page) const editor = f.createEditor('src/routes/style-server/server-url.css') editor.edit((s) => s.replaceAll('rgb(255, 165, 0)', 'rgb(0, 165, 255)')) - await expect(page.locator('.test-style-url-server')).toHaveCSS( - 'color', - 'rgb(0, 165, 255)', - ) + await expect(page.locator('.test-style-url-server')).toHaveCSS('color', 'rgb(0, 165, 255)') editor.reset() - await expect(page.locator('.test-style-url-server')).toHaveCSS( - 'color', - 'rgb(255, 165, 0)', - ) + await expect(page.locator('.test-style-url-server')).toHaveCSS('color', 'rgb(255, 165, 0)') }) }) @@ -1014,10 +806,7 @@ function defineTest(f: Fixture) { await waitForHydration(page) await using _ = await expectNoReload(page) await page.locator("a[href='?test-client-style-no-ssr']").click() - await expect(page.locator('.test-style-client-no-ssr')).toHaveCSS( - 'color', - 'rgb(0, 200, 100)', - ) + await expect(page.locator('.test-style-client-no-ssr')).toHaveCSS('color', 'rgb(0, 200, 100)') }) test('tailwind @js', async ({ page }) => { @@ -1056,27 +845,15 @@ function defineTest(f: Fixture) { const clientFile = f.createEditor('src/routes/tailwind/client.tsx') clientFile.edit((s) => s.replaceAll('text-[#00f]', 'text-[#88f]')) - await expect(page.locator('.test-tw-client')).toHaveCSS( - 'color', - 'rgb(136, 136, 255)', - ) + await expect(page.locator('.test-tw-client')).toHaveCSS('color', 'rgb(136, 136, 255)') clientFile.reset() - await expect(page.locator('.test-tw-client')).toHaveCSS( - 'color', - 'rgb(0, 0, 255)', - ) + await expect(page.locator('.test-tw-client')).toHaveCSS('color', 'rgb(0, 0, 255)') const serverFile = f.createEditor('src/routes/tailwind/server.tsx') serverFile.edit((s) => s.replaceAll('text-[#f00]', 'text-[#f88]')) - await expect(page.locator('.test-tw-server')).toHaveCSS( - 'color', - 'rgb(255, 136, 136)', - ) + await expect(page.locator('.test-tw-server')).toHaveCSS('color', 'rgb(255, 136, 136)') serverFile.reset() - await expect(page.locator('.test-tw-server')).toHaveCSS( - 'color', - 'rgb(255, 0, 0)', - ) + await expect(page.locator('.test-tw-server')).toHaveCSS('color', 'rgb(255, 0, 0)') }) test('tailwind no redundant server hmr', async ({ page }) => { @@ -1092,9 +869,7 @@ function defineTest(f: Fixture) { await page.waitForTimeout(200) f.createEditor('src/routes/tailwind/server.tsx').resave() await page.waitForTimeout(200) - expect(logs).toEqual([ - expect.stringMatching(/\[vite-rsc:update\].*\/tailwind\/server.tsx/), - ]) + expect(logs).toEqual([expect.stringMatching(/\[vite-rsc:update\].*\/tailwind\/server.tsx/)]) }) }) @@ -1102,9 +877,7 @@ function defineTest(f: Fixture) { await page.goto(f.url()) await waitForHydration(page) await page.getByRole('button', { name: 'test-temporary-reference' }).click() - await expect(page.getByTestId('temporary-reference')).toContainText( - 'result: [server [client]]', - ) + await expect(page.getByTestId('temporary-reference')).toContainText('result: [server [client]]') }) test('server action error @js', async ({ page }) => { @@ -1120,23 +893,17 @@ function defineTest(f: Fixture) { }) }) await page.getByRole('button', { name: 'test-server-action-error' }).click() - await expect(page.getByTestId('action-error-boundary')).toContainText( - 'ErrorBoundary triggered', - ) + await expect(page.getByTestId('action-error-boundary')).toContainText('ErrorBoundary triggered') await expect(errorResponse).resolves.toEqual(500) if (f.mode === 'dev') { - await expect(page.getByTestId('action-error-boundary')).toContainText( - '(Error: boom!)', - ) + await expect(page.getByTestId('action-error-boundary')).toContainText('(Error: boom!)') } else { await expect(page.getByTestId('action-error-boundary')).toContainText( '(Error: An error occurred in the Server Components render.', ) } await page.getByRole('button', { name: 'reset-error' }).click() - await expect( - page.getByRole('button', { name: 'test-server-action-error' }), - ).toBeVisible() + await expect(page.getByRole('button', { name: 'test-server-action-error' })).toBeVisible() }) test.describe(() => { @@ -1151,14 +918,10 @@ function defineTest(f: Fixture) { } }) }) - await page - .getByRole('button', { name: 'test-server-action-error' }) - .click() + await page.getByRole('button', { name: 'test-server-action-error' }).click() const response = await responsePromise expect(response.status()).toBe(500) - await expect(response.text()).resolves.toBe( - 'Internal Server Error: server action failed', - ) + await expect(response.text()).resolves.toBe('Internal Server Error: server action failed') }) }) @@ -1172,9 +935,7 @@ function defineTest(f: Fixture) { await locator.click() await expect(page.getByText('Caught an unexpected error')).toBeVisible() if (f.mode === 'dev') { - await expect( - page.getByText('Error: Client error triggered'), - ).toBeVisible() + await expect(page.getByText('Error: Client error triggered')).toBeVisible() } else { await expect(page.getByText('Error: (Unknown)')).toBeVisible() } @@ -1186,8 +947,7 @@ function defineTest(f: Fixture) { await page.goto(f.url()) await waitForHydration(page) - const expectedText = - f.mode === 'dev' ? 'Error: test-server-error!' : 'Error: (Unknown)' + const expectedText = f.mode === 'dev' ? 'Error: test-server-error!' : 'Error: (Unknown)' // trigger client navigation error await page.getByRole('link', { name: 'test-server-error' }).click() @@ -1203,12 +963,8 @@ function defineTest(f: Fixture) { // client is interactive before suspense is resolved await page.goto(f.url('./?test-suspense=1000'), { waitUntil: 'commit' }) await waitForHydration(page) - await expect(page.getByTestId('suspense')).toContainText( - 'suspense-fallback', - ) - await expect(page.getByTestId('suspense')).toContainText( - 'suspense-resolved', - ) + await expect(page.getByTestId('suspense')).toContainText('suspense-fallback') + await expect(page.getByTestId('suspense')).toContainText('suspense-resolved') }) test('ssr rsc payload encoding', async ({ page }) => { @@ -1238,18 +994,10 @@ function defineTest(f: Fixture) { }) async function testActionBindSimple(page: Page) { - await expect(page.getByTestId('test-server-action-bind-simple')).toHaveText( - '[?]', - ) - await page - .getByRole('button', { name: 'test-server-action-bind-simple' }) - .click() - await expect(page.getByTestId('test-server-action-bind-simple')).toHaveText( - 'true', - ) - await page - .getByRole('button', { name: 'test-server-action-bind-reset' }) - .click() + await expect(page.getByTestId('test-server-action-bind-simple')).toHaveText('[?]') + await page.getByRole('button', { name: 'test-server-action-bind-simple' }).click() + await expect(page.getByTestId('test-server-action-bind-simple')).toHaveText('true') + await page.getByRole('button', { name: 'test-server-action-bind-reset' }).click() } test('action bind client @js', async ({ page }) => { @@ -1266,18 +1014,10 @@ function defineTest(f: Fixture) { }) async function testActionBindClient(page: Page) { - await expect(page.getByTestId('test-server-action-bind-client')).toHaveText( - '[?]', - ) - await page - .getByRole('button', { name: 'test-server-action-bind-client' }) - .click() - await expect(page.getByTestId('test-server-action-bind-client')).toHaveText( - 'true', - ) - await page - .getByRole('button', { name: 'test-server-action-bind-reset' }) - .click() + await expect(page.getByTestId('test-server-action-bind-client')).toHaveText('[?]') + await page.getByRole('button', { name: 'test-server-action-bind-client' }).click() + await expect(page.getByTestId('test-server-action-bind-client')).toHaveText('true') + await page.getByRole('button', { name: 'test-server-action-bind-reset' }).click() } test('action bind action @js', async ({ page }) => { @@ -1293,18 +1033,10 @@ function defineTest(f: Fixture) { }) async function testActionBindAction(page: Page) { - await expect(page.getByTestId('test-server-action-bind-action')).toHaveText( - '[?]', - ) - await page - .getByRole('button', { name: 'test-server-action-bind-action' }) - .click() - await expect(page.getByTestId('test-server-action-bind-action')).toHaveText( - '[true,true]', - ) - await page - .getByRole('button', { name: 'test-server-action-bind-reset' }) - .click() + await expect(page.getByTestId('test-server-action-bind-action')).toHaveText('[?]') + await page.getByRole('button', { name: 'test-server-action-bind-action' }).click() + await expect(page.getByTestId('test-server-action-bind-action')).toHaveText('[true,true]') + await page.getByRole('button', { name: 'test-server-action-bind-reset' }).click() } test('test serialization @js', async ({ page }) => { @@ -1328,105 +1060,69 @@ function defineTest(f: Fixture) { test('server-in-server package', async ({ page }) => { await page.goto(f.url()) await waitForHydration(page) - await expect(page.getByTestId('server-in-server')).toHaveText( - 'server-in-server: 0', - ) + await expect(page.getByTestId('server-in-server')).toHaveText('server-in-server: 0') await page.getByTestId('server-in-server').click() - await expect(page.getByTestId('server-in-server')).toHaveText( - 'server-in-server: 1', - ) + await expect(page.getByTestId('server-in-server')).toHaveText('server-in-server: 1') await page.reload() - await expect(page.getByTestId('server-in-server')).toHaveText( - 'server-in-server: 1', - ) + await expect(page.getByTestId('server-in-server')).toHaveText('server-in-server: 1') }) test('server-in-client package', async ({ page }) => { await page.goto(f.url()) await waitForHydration(page) - await expect(page.getByTestId('server-in-client')).toHaveText( - 'server-in-client: ?', - ) + await expect(page.getByTestId('server-in-client')).toHaveText('server-in-client: ?') await page.getByTestId('server-in-client').click() - await expect(page.getByTestId('server-in-client')).toHaveText( - 'server-in-client: 1', - ) + await expect(page.getByTestId('server-in-client')).toHaveText('server-in-client: 1') await page.reload() await waitForHydration(page) - await expect(page.getByTestId('server-in-client')).toHaveText( - 'server-in-client: ?', - ) + await expect(page.getByTestId('server-in-client')).toHaveText('server-in-client: ?') await page.getByTestId('server-in-client').click() - await expect(page.getByTestId('server-in-client')).toHaveText( - 'server-in-client: 2', - ) + await expect(page.getByTestId('server-in-client')).toHaveText('server-in-client: 2') }) test('transitive cjs dep', async ({ page }) => { await page.goto(f.url()) await waitForHydration(page) await expect(page.getByTestId('transitive-cjs-client')).toHaveText('ok') - await expect( - page.getByTestId('transitive-use-sync-external-store-client'), - ).toHaveText('ok:browser') + await expect(page.getByTestId('transitive-use-sync-external-store-client')).toHaveText( + 'ok:browser', + ) }) test('use cache function', async ({ page }) => { await page.goto(f.url()) await waitForHydration(page) const locator = page.getByTestId('test-use-cache-fn') - await expect(locator.locator('span')).toHaveText( - '(actionCount: 0, cacheFnCount: 0)', - ) + await expect(locator.locator('span')).toHaveText('(actionCount: 0, cacheFnCount: 0)') await locator.getByRole('button').click() - await expect(locator.locator('span')).toHaveText( - '(actionCount: 1, cacheFnCount: 1)', - ) + await expect(locator.locator('span')).toHaveText('(actionCount: 1, cacheFnCount: 1)') await locator.getByRole('button').click() - await expect(locator.locator('span')).toHaveText( - '(actionCount: 2, cacheFnCount: 1)', - ) + await expect(locator.locator('span')).toHaveText('(actionCount: 2, cacheFnCount: 1)') await locator.getByRole('textbox').fill('test') await locator.getByRole('button').click() - await expect(locator.locator('span')).toHaveText( - '(actionCount: 3, cacheFnCount: 2)', - ) + await expect(locator.locator('span')).toHaveText('(actionCount: 3, cacheFnCount: 2)') await locator.getByRole('textbox').fill('test') await locator.getByRole('button').click() - await expect(locator.locator('span')).toHaveText( - '(actionCount: 4, cacheFnCount: 2)', - ) + await expect(locator.locator('span')).toHaveText('(actionCount: 4, cacheFnCount: 2)') // revalidate cache await locator.getByRole('textbox').fill('revalidate') await locator.getByRole('button').click() - await expect(locator.locator('span')).toHaveText( - '(actionCount: 5, cacheFnCount: 3)', - ) + await expect(locator.locator('span')).toHaveText('(actionCount: 5, cacheFnCount: 3)') await locator.getByRole('textbox').fill('test') await locator.getByRole('button').click() - await expect(locator.locator('span')).toHaveText( - '(actionCount: 6, cacheFnCount: 4)', - ) + await expect(locator.locator('span')).toHaveText('(actionCount: 6, cacheFnCount: 4)') }) test('use cache component', async ({ page }) => { await page.goto(f.url()) await waitForHydration(page) - const static1 = await page - .getByTestId('test-use-cache-component-static') - .textContent() - const dynamic1 = await page - .getByTestId('test-use-cache-component-dynamic') - .textContent() + const static1 = await page.getByTestId('test-use-cache-component-static').textContent() + const dynamic1 = await page.getByTestId('test-use-cache-component-dynamic').textContent() await page.waitForTimeout(100) await page.reload() - const static2 = await page - .getByTestId('test-use-cache-component-static') - .textContent() - const dynamic2 = await page - .getByTestId('test-use-cache-component-dynamic') - .textContent() + const static2 = await page.getByTestId('test-use-cache-component-static').textContent() + const dynamic2 = await page.getByTestId('test-use-cache-component-dynamic').textContent() expect({ static2, dynamic2 }).toEqual({ static2: expect.stringMatching(static1!), dynamic2: expect.not.stringMatching(dynamic1!), @@ -1437,49 +1133,37 @@ function defineTest(f: Fixture) { await page.goto(f.url()) await waitForHydration(page) const locator = page.getByTestId('test-use-cache-closure') - await expect(locator.locator('span')).toHaveText( - '(actionCount: 0, innerFnCount: 0)', - ) + await expect(locator.locator('span')).toHaveText('(actionCount: 0, innerFnCount: 0)') // (x, y) await locator.getByPlaceholder('outer').fill('x') await locator.getByPlaceholder('inner').fill('y') await locator.getByRole('button').click() - await expect(locator.locator('span')).toHaveText( - '(actionCount: 1, innerFnCount: 1)', - ) + await expect(locator.locator('span')).toHaveText('(actionCount: 1, innerFnCount: 1)') // (x, y) await locator.getByPlaceholder('outer').fill('x') await locator.getByPlaceholder('inner').fill('y') await locator.getByRole('button').click() - await expect(locator.locator('span')).toHaveText( - '(actionCount: 2, innerFnCount: 1)', - ) + await expect(locator.locator('span')).toHaveText('(actionCount: 2, innerFnCount: 1)') // (xx, y) await locator.getByPlaceholder('outer').fill('xx') await locator.getByPlaceholder('inner').fill('y') await locator.getByRole('button').click() - await expect(locator.locator('span')).toHaveText( - '(actionCount: 3, innerFnCount: 2)', - ) + await expect(locator.locator('span')).toHaveText('(actionCount: 3, innerFnCount: 2)') // (xx, y) await locator.getByPlaceholder('outer').fill('xx') await locator.getByPlaceholder('inner').fill('y') await locator.getByRole('button').click() - await expect(locator.locator('span')).toHaveText( - '(actionCount: 4, innerFnCount: 2)', - ) + await expect(locator.locator('span')).toHaveText('(actionCount: 4, innerFnCount: 2)') // (xx, yy) await locator.getByPlaceholder('outer').fill('xx') await locator.getByPlaceholder('inner').fill('yy') await locator.getByRole('button').click() - await expect(locator.locator('span')).toHaveText( - '(actionCount: 5, innerFnCount: 3)', - ) + await expect(locator.locator('span')).toHaveText('(actionCount: 5, innerFnCount: 3)') }) test('hydration mismatch', async ({ page }) => { @@ -1505,9 +1189,7 @@ function defineTest(f: Fixture) { test('browser only', async ({ page, browser }) => { await page.goto(f.url()) - await expect(page.getByTestId('test-browser-only')).toHaveText( - 'test-browser-only: true', - ) + await expect(page.getByTestId('test-browser-only')).toHaveText('test-browser-only: true') const pageNoJs = await browser.newPage({ javaScriptEnabled: false }) await pageNoJs.goto(f.url()) @@ -1559,12 +1241,14 @@ function defineTest(f: Fixture) { test('assets', async ({ page }) => { await page.goto(f.url()) await waitForHydration(page) - await expect( - page.getByTestId('test-assets-server-import'), - ).not.toHaveJSProperty('naturalWidth', 0) - await expect( - page.getByTestId('test-assets-client-import'), - ).not.toHaveJSProperty('naturalWidth', 0) + await expect(page.getByTestId('test-assets-server-import')).not.toHaveJSProperty( + 'naturalWidth', + 0, + ) + await expect(page.getByTestId('test-assets-client-import')).not.toHaveJSProperty( + 'naturalWidth', + 0, + ) async function testBackgroundImage(selector: string) { const url = await page diff --git a/packages/plugin-rsc/e2e/browser-mode.test.ts b/packages/plugin-rsc/e2e/browser-mode.test.ts index 84280fd14..17421d80b 100644 --- a/packages/plugin-rsc/e2e/browser-mode.test.ts +++ b/packages/plugin-rsc/e2e/browser-mode.test.ts @@ -27,18 +27,10 @@ function defineBrowserModeTest(f: ReturnType