|
1 | 1 | import { createHash } from 'node:crypto' |
2 | 2 | import { readFileSync } from 'node:fs' |
3 | | -import { type Page, expect, test } from '@playwright/test' |
| 3 | +import { |
| 4 | + type Page, |
| 5 | + type Response as PlaywrightResponse, |
| 6 | + expect, |
| 7 | + test, |
| 8 | +} from '@playwright/test' |
4 | 9 | import { type Fixture, useCreateEditor, useFixture } from './fixture' |
5 | 10 | import { |
6 | 11 | expectNoPageError, |
@@ -1107,14 +1112,74 @@ function defineTest(f: Fixture) { |
1107 | 1112 | // this need to be verified manually on browser devtools console. |
1108 | 1113 | await page.goto(f.url()) |
1109 | 1114 | await waitForHydration(page) |
| 1115 | + const errorResponse = new Promise((resolve) => { |
| 1116 | + page.on('response', async (response) => { |
| 1117 | + if (response.request().method() === 'POST') { |
| 1118 | + resolve(response.status()) |
| 1119 | + } |
| 1120 | + }) |
| 1121 | + }) |
1110 | 1122 | await page.getByRole('button', { name: 'test-server-action-error' }).click() |
1111 | | - await expect(page.getByText('ErrorBoundary caught')).toBeVisible() |
| 1123 | + await expect(page.getByTestId('action-error-boundary')).toContainText( |
| 1124 | + 'ErrorBoundary triggered', |
| 1125 | + ) |
| 1126 | + await expect(errorResponse).resolves.toEqual(500) |
| 1127 | + if (f.mode === 'dev') { |
| 1128 | + await expect(page.getByTestId('action-error-boundary')).toContainText( |
| 1129 | + '(Error: boom!)', |
| 1130 | + ) |
| 1131 | + } else { |
| 1132 | + await expect(page.getByTestId('action-error-boundary')).toContainText( |
| 1133 | + '(Error: An error occurred in the Server Components render.', |
| 1134 | + ) |
| 1135 | + } |
1112 | 1136 | await page.getByRole('button', { name: 'reset-error' }).click() |
1113 | 1137 | await expect( |
1114 | 1138 | page.getByRole('button', { name: 'test-server-action-error' }), |
1115 | 1139 | ).toBeVisible() |
1116 | 1140 | }) |
1117 | 1141 |
|
| 1142 | + test.describe(() => { |
| 1143 | + test.use({ javaScriptEnabled: false }) |
| 1144 | + |
| 1145 | + test('server action error @nojs', async ({ page }) => { |
| 1146 | + await page.goto(f.url()) |
| 1147 | + const responsePromise = new Promise<PlaywrightResponse>((resolve) => { |
| 1148 | + page.on('response', async (response) => { |
| 1149 | + if (response.request().method() === 'POST') { |
| 1150 | + resolve(response) |
| 1151 | + } |
| 1152 | + }) |
| 1153 | + }) |
| 1154 | + await page |
| 1155 | + .getByRole('button', { name: 'test-server-action-error' }) |
| 1156 | + .click() |
| 1157 | + const response = await responsePromise |
| 1158 | + expect(response.status()).toBe(500) |
| 1159 | + await expect(response.text()).resolves.toBe('Internal Server Error') |
| 1160 | + }) |
| 1161 | + }) |
| 1162 | + |
| 1163 | + test('client error', async ({ page }) => { |
| 1164 | + await page.goto(f.url()) |
| 1165 | + await waitForHydration(page) |
| 1166 | + const locator = page.getByTestId('test-client-error') |
| 1167 | + await expect(locator).toHaveText('test-client-error: 0') |
| 1168 | + await locator.click() |
| 1169 | + await expect(locator).toHaveText('test-client-error: 1') |
| 1170 | + await locator.click() |
| 1171 | + await expect(page.getByText('Caught an unexpected error')).toBeVisible() |
| 1172 | + if (f.mode === 'dev') { |
| 1173 | + await expect( |
| 1174 | + page.getByText('Error: Client error triggered'), |
| 1175 | + ).toBeVisible() |
| 1176 | + } else { |
| 1177 | + await expect(page.getByText('Error: (Unknown)')).toBeVisible() |
| 1178 | + } |
| 1179 | + await page.getByRole('button', { name: 'Reset' }).click() |
| 1180 | + await expect(locator).toHaveText('test-client-error: 0') |
| 1181 | + }) |
| 1182 | + |
1118 | 1183 | test('hydrate while streaming @js', async ({ page }) => { |
1119 | 1184 | // client is interactive before suspense is resolved |
1120 | 1185 | await page.goto(f.url('./?test-suspense=1000'), { waitUntil: 'commit' }) |
|
0 commit comments