Skip to content

Commit f5ffacf

Browse files
authored
test(e2e): Add tests to SvelteKit 2.x E2E test app (#9944)
Add proper e2e tests to our Sveltekit 2.x test application. 1. Distributed pageload trace - important for browserTracing rework 2. Distributed navigation trace - important for browserTracing rework 3. Client side component error 4. Client side universal load error 5. Server side universal load error 6. Server side server load error 7. Server route/API error
1 parent acc5e33 commit f5ffacf

File tree

28 files changed

+574
-78
lines changed

28 files changed

+574
-78
lines changed

dev-packages/e2e-tests/test-applications/sveltekit-2/event-proxy-server.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as os from 'os';
66
import * as path from 'path';
77
import * as util from 'util';
88
import * as zlib from 'zlib';
9-
import type { Envelope, EnvelopeItem, Event } from '@sentry/types';
9+
import type { Envelope, EnvelopeItem, SerializedEvent } from '@sentry/types';
1010
import { parseEnvelope } from '@sentry/utils';
1111

1212
const readFile = util.promisify(fs.readFile);
@@ -210,13 +210,13 @@ export function waitForEnvelopeItem(
210210

211211
export function waitForError(
212212
proxyServerName: string,
213-
callback: (transactionEvent: Event) => Promise<boolean> | boolean,
214-
): Promise<Event> {
213+
callback: (transactionEvent: SerializedEvent) => Promise<boolean> | boolean,
214+
): Promise<SerializedEvent> {
215215
return new Promise((resolve, reject) => {
216216
waitForEnvelopeItem(proxyServerName, async envelopeItem => {
217217
const [envelopeItemHeader, envelopeItemBody] = envelopeItem;
218-
if (envelopeItemHeader.type === 'event' && (await callback(envelopeItemBody as Event))) {
219-
resolve(envelopeItemBody as Event);
218+
if (envelopeItemHeader.type === 'event' && (await callback(envelopeItemBody as SerializedEvent))) {
219+
resolve(envelopeItemBody as SerializedEvent);
220220
return true;
221221
}
222222
return false;
@@ -226,13 +226,13 @@ export function waitForError(
226226

227227
export function waitForTransaction(
228228
proxyServerName: string,
229-
callback: (transactionEvent: Event) => Promise<boolean> | boolean,
230-
): Promise<Event> {
229+
callback: (transactionEvent: SerializedEvent) => Promise<boolean> | boolean,
230+
): Promise<SerializedEvent> {
231231
return new Promise((resolve, reject) => {
232232
waitForEnvelopeItem(proxyServerName, async envelopeItem => {
233233
const [envelopeItemHeader, envelopeItemBody] = envelopeItem;
234-
if (envelopeItemHeader.type === 'transaction' && (await callback(envelopeItemBody as Event))) {
235-
resolve(envelopeItemBody as Event);
234+
if (envelopeItemHeader.type === 'transaction' && (await callback(envelopeItemBody as SerializedEvent))) {
235+
resolve(envelopeItemBody as SerializedEvent);
236236
return true;
237237
}
238238
return false;
@@ -247,7 +247,7 @@ async function registerCallbackServerPort(serverName: string, port: string): Pro
247247
await writeFile(tmpFilePath, port, { encoding: 'utf8' });
248248
}
249249

250-
async function retrieveCallbackServerPort(serverName: string): Promise<string> {
250+
function retrieveCallbackServerPort(serverName: string): Promise<string> {
251251
const tmpFilePath = path.join(os.tmpdir(), `${TEMP_FILE_PREFIX}${serverName}`);
252-
return await readFile(tmpFilePath, 'utf8');
252+
return readFile(tmpFilePath, 'utf8');
253253
}

dev-packages/e2e-tests/test-applications/sveltekit-2/package.json

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,19 @@
1010
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
1111
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
1212
"test:prod": "TEST_ENV=production playwright test",
13-
"test:dev": "TEST_ENV=development playwright test",
14-
"test:build": "pnpm install && pnpm build",
15-
"test:assert": "pnpm -v"
13+
"test:build": "pnpm install && npx playwright install && pnpm build",
14+
"test:assert": "pnpm test:prod"
1615
},
1716
"dependencies": {
1817
"@sentry/sveltekit": "latest || *"
1918
},
2019
"devDependencies": {
21-
"@playwright/test": "^1.27.1",
20+
"@playwright/test": "^1.36.2",
2221
"@sentry/types": "latest || *",
2322
"@sentry/utils": "latest || *",
2423
"@sveltejs/adapter-auto": "^3.0.0",
2524
"@sveltejs/adapter-node": "^2.0.0",
26-
"@sveltejs/kit": "^2.0.0",
25+
"@sveltejs/kit": "^2.5.0",
2726
"@sveltejs/vite-plugin-svelte": "^3.0.0",
2827
"svelte": "^4.2.8",
2928
"svelte-check": "^3.6.0",

dev-packages/e2e-tests/test-applications/sveltekit-2/playwright.config.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
import type { PlaywrightTestConfig } from '@playwright/test';
22
import { devices } from '@playwright/test';
33

4+
// Fix urls not resolving to localhost on Node v17+
5+
// See: https://github.com/axios/axios/issues/3821#issuecomment-1413727575
6+
import { setDefaultResultOrder } from 'dns';
7+
setDefaultResultOrder('ipv4first');
8+
49
const testEnv = process.env.TEST_ENV;
510

611
if (!testEnv) {
712
throw new Error('No test env defined');
813
}
914

10-
const port = 3030;
15+
const svelteKitPort = 3030;
16+
const eventProxyPort = 3031;
1117

1218
/**
1319
* See https://playwright.dev/docs/test-configuration.
@@ -24,7 +30,8 @@ const config: PlaywrightTestConfig = {
2430
timeout: 10000,
2531
},
2632
/* Run tests in files in parallel */
27-
fullyParallel: true,
33+
fullyParallel: false,
34+
workers: 1,
2835
/* Fail the build on CI if you accidentally left test.only in the source code. */
2936
forbidOnly: !!process.env.CI,
3037
/* `next dev` is incredibly buggy with the app dir */
@@ -36,7 +43,7 @@ const config: PlaywrightTestConfig = {
3643
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
3744
actionTimeout: 0,
3845
/* Base URL to use in actions like `await page.goto('/')`. */
39-
baseURL: `http://localhost:${port}`,
46+
baseURL: `http://localhost:${svelteKitPort}`,
4047

4148
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
4249
trace: 'on-first-retry',
@@ -55,15 +62,17 @@ const config: PlaywrightTestConfig = {
5562
/* Run your local dev server before starting the tests */
5663
webServer: [
5764
{
58-
command: 'pnpm ts-node --esm start-event-proxy.ts',
59-
port: 3031,
65+
command: 'pnpm ts-node-script start-event-proxy.ts',
66+
port: eventProxyPort,
67+
reuseExistingServer: false,
6068
},
6169
{
6270
command:
6371
testEnv === 'development'
64-
? `pnpm wait-port ${port} && pnpm dev --port ${port}`
65-
: `pnpm wait-port ${port} && pnpm preview --port ${port}`,
66-
port,
72+
? `pnpm wait-port ${eventProxyPort} && pnpm dev --port ${svelteKitPort}`
73+
: `pnpm wait-port ${eventProxyPort} && PORT=${svelteKitPort} node build`,
74+
port: svelteKitPort,
75+
reuseExistingServer: false,
6776
},
6877
],
6978
};

dev-packages/e2e-tests/test-applications/sveltekit-2/src/app.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<meta name="viewport" content="width=device-width" />
77
%sveltekit.head%
88
</head>
9-
<body data-sveltekit-preload-data="hover">
9+
<body data-sveltekit-preload-data="off">
1010
<div style="display: contents">%sveltekit.body%</div>
1111
</body>
1212
</html>

dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.server.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@ Sentry.init({
99
tracesSampleRate: 1.0,
1010
});
1111

12-
const myErrorHandler = ({ error, event }: any) => {
13-
console.error('An error occurred on the server side:', error, event);
14-
};
15-
16-
export const handleError = Sentry.handleErrorWithSentry(myErrorHandler);
12+
// not logging anything to console to avoid noise in the test output
13+
export const handleError = Sentry.handleErrorWithSentry(() => {});
1714

1815
export const handle = Sentry.sentryHandle();
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<script lang="ts">
2+
import { onMount } from "svelte";
3+
4+
onMount(() => {
5+
// Indicate that the SvelteKit app was hydrated
6+
document.body.classList.add("hydrated");
7+
});
8+
</script>
9+
10+
<h1>Sveltekit E2E Test app</h1>
11+
<div data-sveltekit-preload-data="off">
12+
<slot></slot>
13+
</div>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,26 @@
11
<h1>Welcome to SvelteKit</h1>
22
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
3+
4+
<ul>
5+
<li>
6+
<a href="/client-error">Client error</a>
7+
</li>
8+
<li>
9+
<a href="/universal-load-error">Universal Load error</a>
10+
</li>
11+
<li>
12+
<a href="/server-load-error">Server Load error</a>
13+
</li>
14+
<li>
15+
<a href="/server-route-error">Server Route error</a>
16+
</li>
17+
<li>
18+
<a href="/users/123abc">Route with Params</a>
19+
</li>
20+
<li>
21+
<a href="/users">Route with Server Load</a>
22+
</li>
23+
<li>
24+
<a href="/universal-load-fetch">Route with fetch in universal load</a>
25+
</li>
26+
</ul>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const GET = () => {
2+
return new Response(JSON.stringify({ users: ['alice', 'bob', 'carol'] }));
3+
};

dev-packages/e2e-tests/test-applications/sveltekit-2/src/routes/building/+page.svelte

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
<script lang="ts">
2+
import * as Sentry from '@sentry/sveltekit';
3+
4+
async function getSentryData() {
5+
Sentry.startSpan({
6+
name: 'Example Frontend Span',
7+
}, async () => {
8+
const res = await fetch('/sentry-example');
9+
if (!res.ok) {
10+
throw new Error('Sentry Example Frontend Error');
11+
}
12+
})
13+
}
14+
</script>
15+
116
<h1>Check Build</h1>
217

318
<p>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<script lang="ts">
2+
function throwError() {
3+
throw new Error('Click Error');
4+
}
5+
</script>
6+
7+
<h1>Client error</h1>
8+
9+
<button on:click={throwError}>Throw error</button>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const load = async () => {
2+
throw new Error('Server Load Error');
3+
return {
4+
msg: 'Hello World',
5+
};
6+
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<script lang="ts">
2+
export let data
3+
</script>
4+
5+
<h1>Server load error</h1>
6+
7+
<p>
8+
Message: {data.msg}
9+
</p>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<script lang="ts">
2+
export let data;
3+
</script>
4+
5+
<h1>Server Route error</h1>
6+
7+
<p>
8+
Message: {data.msg}
9+
</p>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export const load = async ({ fetch }) => {
2+
const res = await fetch('/server-route-error');
3+
const data = await res.json();
4+
return {
5+
msg: data,
6+
};
7+
};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const GET = async () => {
2+
throw new Error('Server Route Error');
3+
return {
4+
msg: 'Hello World',
5+
};
6+
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<script lang="ts">
2+
export let data
3+
</script>
4+
5+
<h1>Universal load error</h1>
6+
7+
<p>
8+
To trigger from client: Load on another route, then navigate to this route.
9+
</p>
10+
11+
<p>
12+
To trigger from server: Load on this route
13+
</p>
14+
15+
<p>
16+
Message: {data.msg}
17+
</p>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { browser } from '$app/environment';
2+
3+
export const load = async () => {
4+
throw new Error(`Universal Load Error (${browser ? 'browser' : 'server'})`);
5+
return {
6+
msg: 'Hello World',
7+
};
8+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script lang="ts">
2+
export let data;
3+
console.log(data);
4+
</script>
5+
6+
<h2>Fetching in universal load</h2>
7+
8+
<p>Here's a list of a few users:</p>
9+
10+
<ul>
11+
{#each data.users as user}
12+
<li>{user}</li>
13+
{/each}
14+
</ul>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const load = async ({ fetch }) => {
2+
const usersRes = await fetch('/api/users');
3+
const data = await usersRes.json();
4+
return { users: data.users };
5+
};
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const load = async () => {
2+
return {
3+
msg: 'Hi everyone!',
4+
};
5+
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<script lang="ts">
2+
export let data;
3+
</script>
4+
<h2>
5+
All Users:
6+
</h2>
7+
8+
<p>
9+
message: {data.msg}
10+
</p>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const load = async ({ params }) => {
2+
return {
3+
msg: `This is a special message for user ${params.id}`,
4+
};
5+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script lang="ts">
2+
import { page } from '$app/stores';
3+
export let data;
4+
</script>
5+
6+
<h1>Route with dynamic params</h1>
7+
8+
<p>
9+
User id: {$page.params.id}
10+
</p>
11+
12+
<p>
13+
Secret message for user: {data.msg}
14+
</p>

0 commit comments

Comments
 (0)