Skip to content

Commit e2e52b8

Browse files
hi-ogawaclaude
andcommitted
test(rsc): add comprehensive syntax error handling tests
Add e2e tests for syntax error scenarios: - Client HMR syntax error with error overlay - Server HMR syntax error with error overlay - Initial SSR with server component syntax error - Initial SSR with client component syntax error Tests validate the fix for handling syntax errors before server HMR and proper error overlay behavior during development. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent b30d6e6 commit e2e52b8

File tree

1 file changed

+192
-0
lines changed

1 file changed

+192
-0
lines changed
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
import { test, expect } from '@playwright/test'
2+
import { setupInlineFixture, type Fixture, useFixture } from './fixture'
3+
import { waitForHydration } from './helper'
4+
5+
test.describe(() => {
6+
const root = 'examples/e2e/temp/syntax-error'
7+
8+
test.beforeAll(async () => {
9+
await setupInlineFixture({
10+
src: 'examples/starter',
11+
dest: root,
12+
files: {
13+
'src/root.tsx': /* tsx */ `
14+
import { TestSyntaxErrorClient } from './client.tsx'
15+
import { TestSyntaxErrorServer } from './server.tsx'
16+
17+
export function Root() {
18+
return (
19+
<html lang="en">
20+
<head>
21+
<meta charSet="UTF-8" />
22+
</head>
23+
<body>
24+
<TestSyntaxErrorClient />
25+
<TestSyntaxErrorServer />
26+
</body>
27+
</html>
28+
)
29+
}
30+
`,
31+
'src/client.tsx': /* tsx */ `
32+
"use client";
33+
import { useState } from 'react'
34+
35+
export function TestSyntaxErrorClient() {
36+
const [triggerError, setTriggerError] = useState(false)
37+
38+
return (
39+
<div data-testid="client-syntax-ready">
40+
<button
41+
onClick={() => setTriggerError(true)}
42+
data-testid="trigger-client-syntax-error"
43+
>
44+
Trigger Client Syntax Error
45+
</button>
46+
{triggerError && <div>Client ready for syntax error</div>}
47+
</div>
48+
)
49+
}
50+
`,
51+
'src/server.tsx': /* tsx */ `
52+
export function TestSyntaxErrorServer() {
53+
return (
54+
<div data-testid="server-syntax-ready">
55+
Server ready for syntax error testing
56+
</div>
57+
)
58+
}
59+
`,
60+
},
61+
})
62+
})
63+
64+
function defineSyntaxErrorTests(f: Fixture) {
65+
test('client syntax error triggers error overlay', async ({ page }) => {
66+
await page.goto(f.url())
67+
await waitForHydration(page)
68+
69+
await expect(page.getByTestId('client-syntax-ready')).toBeVisible()
70+
71+
// Edit client file to introduce syntax error
72+
const editor = f.createEditor('src/client.tsx')
73+
editor.edit((s) =>
74+
s.replace(
75+
'export function TestSyntaxErrorClient() {',
76+
'export function TestSyntaxErrorClient() { const invalid = ;',
77+
),
78+
)
79+
80+
// Should see error overlay
81+
await expect(page.locator('vite-error-overlay')).toBeVisible({
82+
timeout: 5000,
83+
})
84+
85+
// Fix syntax error
86+
editor.reset()
87+
88+
// Error overlay should disappear and page should work
89+
await expect(page.locator('vite-error-overlay')).not.toBeVisible({
90+
timeout: 5000,
91+
})
92+
await expect(page.getByTestId('client-syntax-ready')).toBeVisible()
93+
})
94+
95+
test('server syntax error triggers error overlay', async ({ page }) => {
96+
await page.goto(f.url())
97+
await waitForHydration(page)
98+
99+
await expect(page.getByTestId('server-syntax-ready')).toBeVisible()
100+
101+
// Edit server file to introduce syntax error
102+
const editor = f.createEditor('src/server.tsx')
103+
editor.edit((s) =>
104+
s.replace(
105+
'export function TestSyntaxErrorServer() {',
106+
'export function TestSyntaxErrorServer() { const invalid = ;',
107+
),
108+
)
109+
110+
// Should see error overlay
111+
await expect(page.locator('vite-error-overlay')).toBeVisible({
112+
timeout: 5000,
113+
})
114+
115+
// Fix syntax error
116+
editor.reset()
117+
118+
// Error overlay should disappear and server HMR should work
119+
await expect(page.locator('vite-error-overlay')).not.toBeVisible({
120+
timeout: 10000,
121+
})
122+
await expect(page.getByTestId('server-syntax-ready')).toBeVisible()
123+
})
124+
125+
test('initial SSR with server component syntax error shows error page', async ({
126+
page,
127+
}) => {
128+
// Edit server file to introduce syntax error before navigation
129+
const editor = f.createEditor('src/server.tsx')
130+
editor.edit((s) =>
131+
s.replace(
132+
'export function TestSyntaxErrorServer() {',
133+
'export function TestSyntaxErrorServer() { const invalid = ;',
134+
),
135+
)
136+
137+
// Navigate to page with syntax error
138+
await page.goto(f.url())
139+
140+
// Should see error content (check for the actual error text visible in the output)
141+
await expect(page.locator('body')).toContainText(
142+
'Transform failed with 1 error',
143+
)
144+
145+
// Fix syntax error
146+
editor.reset()
147+
148+
// Wait a bit for file system changes to be detected
149+
await page.waitForTimeout(100)
150+
151+
// Should work normally now
152+
await page.goto(f.url())
153+
await waitForHydration(page)
154+
await expect(page.getByTestId('server-syntax-ready')).toBeVisible()
155+
})
156+
157+
test('initial SSR with client component syntax error shows error page', async ({
158+
page,
159+
}) => {
160+
// Edit client file to introduce syntax error before navigation
161+
const editor = f.createEditor('src/client.tsx')
162+
editor.edit((s) =>
163+
s.replace(
164+
'export function TestSyntaxErrorClient() {',
165+
'export function TestSyntaxErrorClient() { const invalid = ;',
166+
),
167+
)
168+
169+
// Navigate to page with syntax error
170+
await page.goto(f.url())
171+
172+
// Should see error content (client syntax errors during SSR)
173+
await expect(page.locator('body')).toContainText('Unexpected token')
174+
175+
// Fix syntax error
176+
editor.reset()
177+
178+
// Wait a bit for file system changes to be detected
179+
await page.waitForTimeout(100)
180+
181+
// Should work normally now
182+
await page.goto(f.url())
183+
await waitForHydration(page)
184+
await expect(page.getByTestId('client-syntax-ready')).toBeVisible()
185+
})
186+
}
187+
188+
test.describe('dev', () => {
189+
const f = useFixture({ root, mode: 'dev' })
190+
defineSyntaxErrorTests(f)
191+
})
192+
})

0 commit comments

Comments
 (0)