Skip to content

Commit

Permalink
feat(nuxt): Add E2E test for Nuxt 4 preview
Browse files Browse the repository at this point in the history
  • Loading branch information
s1gr1d committed Sep 25, 2024
1 parent a3b5dca commit f660901
Show file tree
Hide file tree
Showing 26 changed files with 1,760 additions and 1,159 deletions.
24 changes: 24 additions & 0 deletions dev-packages/e2e-tests/test-applications/nuxt-4/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Nuxt dev/build outputs
.output
.data
.nuxt
.nitro
.cache
dist

# Node dependencies
node_modules

# Logs
logs
*.log

# Misc
.DS_Store
.fleet
.idea

# Local env files
.env
.env.*
!.env.example
2 changes: 2 additions & 0 deletions dev-packages/e2e-tests/test-applications/nuxt-4/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@sentry:registry=http://127.0.0.1:4873
@sentry-internal:registry=http://127.0.0.1:4873
17 changes: 17 additions & 0 deletions dev-packages/e2e-tests/test-applications/nuxt-4/app/app.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<template>
<NuxtLayout>
<header>
<nav>
<ul>
<li><NuxtLink to="/fetch-server-error">Fetch Server Error</NuxtLink></li>
<li><NuxtLink to="/test-param/1234">Fetch Param</NuxtLink></li>
<li><NuxtLink to="/client-error">Client Error</NuxtLink></li>
</ul>
</nav>
</header>
<NuxtPage />
</NuxtLayout>
</template>

<script setup>
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script setup>
import { defineProps } from 'vue';
const props = defineProps({
errorText: {
type: String,
required: true
},
id: {
type: String,
required: true
}
})
const triggerError = () => {
throw new Error(props.errorText);
};
</script>

<template>
<button :id="props.id" @click="triggerError">Trigger Error</button>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script setup>
import ErrorButton from '../components/ErrorButton.vue';
</script>

<template>
<ErrorButton id="errorBtn" error-text="Error thrown from nuxt-4 E2E test app"/>
<ErrorButton id="errorBtn2" error-text="Another Error thrown from nuxt-4 E2E test app"/>
</template>



Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<template>
<div>
<button @click="fetchData">Fetch Server Data</button>
</div>
</template>

<script setup lang="ts">
import { useFetch} from '#imports'
const fetchData = async () => {
await useFetch('/api/server-error');
}
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template>
<h1>Hello!</h1>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<template>
<p>{{ $route.params.param }} - {{ $route.params.param }}</p>

<ErrorButton id="errorBtn" errorText="Error thrown from Param Route Button" />
<button @click="fetchData">Fetch Server Data</button>
</template>

<script setup lang="ts">
import { useRoute, useFetch } from '#imports'
const route = useRoute();
const param = route.params.param;
const fetchData = async () => {
await useFetch(`/api/param-error/${param}`);
}
</script>
16 changes: 16 additions & 0 deletions dev-packages/e2e-tests/test-applications/nuxt-4/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
future: { compatibilityVersion: 4 },
compatibilityDate: '2024-04-03',
imports: { autoImport: false },

modules: ['@sentry/nuxt/module'],

runtimeConfig: {
public: {
sentry: {
dsn: 'https://[email protected]/1337',
},
},
},
});
26 changes: 26 additions & 0 deletions dev-packages/e2e-tests/test-applications/nuxt-4/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "nuxt-4",
"private": true,
"type": "module",
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "NODE_OPTIONS='--import ./public/instrument.server.mjs' nuxt preview",
"clean": "npx nuxi cleanup",
"test": "playwright test",
"test:build": "pnpm install && npx playwright install && pnpm build",
"test:assert": "pnpm test"
},
"dependencies": {
"@sentry/nuxt": "latest || *",
"nuxt": "^3.13.2",
"vue": "latest",
"vue-router": "latest"
},
"devDependencies": {
"@nuxt/test-utils": "^3.14.1",
"@playwright/test": "^1.44.1",
"@sentry-internal/test-utils": "link:../../../test-utils"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { fileURLToPath } from 'node:url';
import type { ConfigOptions } from '@nuxt/test-utils/playwright';
import { getPlaywrightConfig } from '@sentry-internal/test-utils';

const nuxtConfigOptions: ConfigOptions = {
nuxt: {
rootDir: fileURLToPath(new URL('.', import.meta.url)),
},
};

/* Make sure to import from '@nuxt/test-utils/playwright' in the tests
* Like this: import { expect, test } from '@nuxt/test-utils/playwright' */

const config = getPlaywrightConfig({
startCommand: `pnpm preview`,
use: { ...nuxtConfigOptions },
});

export default config;
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as Sentry from '@sentry/nuxt';

Sentry.init({
dsn: 'https://[email protected]/1337',
environment: 'qa', // dynamic sampling bias to keep transactions
tracesSampleRate: 1.0, // Capture 100% of the transactions
tunnel: 'http://localhost:3031/', // proxy server
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as Sentry from '@sentry/nuxt';
import { useRuntimeConfig } from '#imports';

Sentry.init({
environment: 'qa', // dynamic sampling bias to keep transactions
dsn: useRuntimeConfig().public.sentry.dsn,
tunnel: `http://localhost:3031/`, // proxy server
tracesSampleRate: 1.0,
trackComponents: true,
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { defineEventHandler } from '#imports';

export default defineEventHandler(_e => {
throw new Error('Nuxt 3 Param Server error');
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { defineEventHandler } from '#imports';

export default defineEventHandler(event => {
throw new Error('Nuxt 3 Server error');
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineEventHandler, getRouterParam } from '#imports';

export default defineEventHandler(event => {
const param = getRouterParam(event, 'param');

return `Param: ${param}!`;
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "../.nuxt/tsconfig.server.json"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { startEventProxyServer } from '@sentry-internal/test-utils';

startEventProxyServer({
port: 3031,
proxyServerName: 'nuxt-4',
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { expect, test } from '@nuxt/test-utils/playwright';
import { waitForError } from '@sentry-internal/test-utils';

test.describe('client-side errors', async () => {
test('captures error thrown on click', async ({ page }) => {
const errorPromise = waitForError('nuxt-4', async errorEvent => {
return errorEvent?.exception?.values?.[0]?.value === 'Error thrown from nuxt-4 E2E test app';
});

await page.goto(`/client-error`);
await page.locator('#errorBtn').click();

const error = await errorPromise;

expect(error.transaction).toEqual('/client-error');
expect(error).toMatchObject({
exception: {
values: [
{
type: 'Error',
value: 'Error thrown from nuxt-4 E2E test app',
mechanism: {
handled: false,
},
},
],
},
});
});

test('shows parametrized route on button error', async ({ page }) => {
const errorPromise = waitForError('nuxt-4', async errorEvent => {
return errorEvent?.exception?.values?.[0]?.value === 'Error thrown from Param Route Button';
});

await page.goto(`/test-param/1234`);
await page.locator('#errorBtn').click();

const error = await errorPromise;

expect(error.sdk.name).toEqual('sentry.javascript.nuxt');
expect(error.transaction).toEqual('/test-param/:param()');
expect(error.request.url).toMatch(/\/test-param\/1234/);
expect(error).toMatchObject({
exception: {
values: [
{
type: 'Error',
value: 'Error thrown from Param Route Button',
mechanism: {
handled: false,
},
},
],
},
});
});

test('page is still interactive after client error', async ({ page }) => {
const error1Promise = waitForError('nuxt-4', async errorEvent => {
return errorEvent?.exception?.values?.[0]?.value === 'Error thrown from nuxt-4 E2E test app';
});

await page.goto(`/client-error`);
await page.locator('#errorBtn').click();

const error1 = await error1Promise;

const error2Promise = waitForError('nuxt-4', async errorEvent => {
return errorEvent?.exception?.values?.[0]?.value === 'Another Error thrown from nuxt-4 E2E test app';
});

await page.locator('#errorBtn2').click();

const error2 = await error2Promise;

expect(error1).toMatchObject({
exception: {
values: [
{
type: 'Error',
value: 'Error thrown from nuxt-4 E2E test app',
mechanism: {
handled: false,
},
},
],
},
});

expect(error2).toMatchObject({
exception: {
values: [
{
type: 'Error',
value: 'Another Error thrown from nuxt-4 E2E test app',
mechanism: {
handled: false,
},
},
],
},
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { expect, test } from '@playwright/test';
import { waitForError } from '@sentry-internal/test-utils';

test.describe('server-side errors', async () => {
test('captures api fetch error (fetched on click)', async ({ page }) => {
const errorPromise = waitForError('nuxt-4', async errorEvent => {
return errorEvent?.exception?.values?.[0]?.value === 'Nuxt 3 Server error';
});

await page.goto(`/fetch-server-error`);
await page.getByText('Fetch Server Data').click();

const error = await errorPromise;

expect(error.transaction).toEqual('GET /api/server-error');

const exception = error.exception.values[0];
expect(exception.type).toEqual('Error');
expect(exception.value).toEqual('Nuxt 3 Server error');
expect(exception.mechanism.handled).toBe(false);
});

test('captures api fetch error (fetched on click) with parametrized route', async ({ page }) => {
const errorPromise = waitForError('nuxt-4', async errorEvent => {
return errorEvent?.exception?.values?.[0]?.value === 'Nuxt 3 Param Server error';
});

await page.goto(`/test-param/1234`);
await page.getByText('Fetch Server Data').click();

const error = await errorPromise;

expect(error.transaction).toEqual('GET /api/param-error/1234');

const exception = error.exception.values[0];
expect(exception.type).toEqual('Error');
expect(exception.value).toEqual('Nuxt 3 Param Server error');
expect(exception.mechanism.handled).toBe(false);
});
});
Loading

0 comments on commit f660901

Please sign in to comment.