Skip to content

Commit c7c9b95

Browse files
committed
feat(e2e): add Next.js Spotlight dev mode test application
New test application (nextjs-15-spotlight) that: - Uses 'next dev' to test development-mode behavior - Verifies Spotlight auto-enablement from NEXT_PUBLIC_SENTRY_SPOTLIGHT - Has increased timeout (90s) for dev server startup - Tests that no syntax errors occur during initialization This tests the realistic scenario where Spotlight is used during development with Next.js.
1 parent f16915a commit c7c9b95

File tree

11 files changed

+228
-0
lines changed

11 files changed

+228
-0
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export const metadata = {
2+
title: 'Next.js Spotlight Test',
3+
description: 'Testing Spotlight auto-enablement in development mode',
4+
};
5+
6+
export default function RootLayout({ children }: { children: React.ReactNode }) {
7+
return (
8+
<html lang="en">
9+
<body>{children}</body>
10+
</html>
11+
);
12+
}
13+
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
'use client';
2+
3+
import { useEffect, useState } from 'react';
4+
import * as Sentry from '@sentry/nextjs';
5+
6+
// Next.js replaces process.env.NEXT_PUBLIC_* at BUILD TIME with literal values
7+
const NEXT_PUBLIC_SPOTLIGHT_VALUE = process.env.NEXT_PUBLIC_SENTRY_SPOTLIGHT;
8+
9+
export default function SpotlightTestPage() {
10+
const [spotlightEnabled, setSpotlightEnabled] = useState<boolean | null>(null);
11+
12+
useEffect(() => {
13+
// Check if Spotlight integration is registered
14+
const client = Sentry.getClient();
15+
const integration = client?.getIntegrationByName?.('SpotlightBrowser');
16+
setSpotlightEnabled(!!integration);
17+
18+
// Log for debugging
19+
console.log('Spotlight test results:', {
20+
envValue: NEXT_PUBLIC_SPOTLIGHT_VALUE,
21+
integrationFound: !!integration,
22+
clientExists: !!client,
23+
});
24+
}, []);
25+
26+
return (
27+
<div>
28+
<h1>Next.js Spotlight Auto-Enablement Test</h1>
29+
30+
<div data-testid="env-value">
31+
<h2>Environment Variable</h2>
32+
<p>NEXT_PUBLIC_SENTRY_SPOTLIGHT: {NEXT_PUBLIC_SPOTLIGHT_VALUE || 'undefined'}</p>
33+
</div>
34+
35+
<div data-testid="spotlight-status">
36+
<h2>Spotlight Integration Status</h2>
37+
<p data-testid="spotlight-enabled">
38+
{spotlightEnabled === null ? 'Loading...' : spotlightEnabled ? 'ENABLED' : 'DISABLED'}
39+
</p>
40+
</div>
41+
</div>
42+
);
43+
}
44+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import * as Sentry from '@sentry/nextjs';
2+
3+
Sentry.init({
4+
environment: 'qa',
5+
dsn: process.env.NEXT_PUBLIC_E2E_TEST_DSN,
6+
tunnel: `http://localhost:3031/`,
7+
tracesSampleRate: 1.0,
8+
debug: true,
9+
// Note: We don't explicitly set spotlight here - it should be auto-enabled
10+
// from NEXT_PUBLIC_SENTRY_SPOTLIGHT env var in development mode
11+
});
12+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export async function register() {
2+
if (process.env.NEXT_RUNTIME === 'nodejs') {
3+
const Sentry = await import('@sentry/nextjs');
4+
Sentry.init({
5+
environment: 'qa',
6+
dsn: process.env.E2E_TEST_DSN,
7+
tunnel: `http://localhost:3031/`,
8+
tracesSampleRate: 1.0,
9+
});
10+
}
11+
}
12+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/// <reference types="next" />
2+
/// <reference types="next/image-types/global" />
3+
4+
// NOTE: This file should not be edited
5+
// see https://nextjs.org/docs/basic-features/typescript for more information.
6+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
const { withSentryConfig } = require('@sentry/nextjs');
2+
3+
/** @type {import('next').NextConfig} */
4+
const nextConfig = {
5+
// Environment variables for Spotlight testing
6+
// NEXT_PUBLIC_* vars are embedded in the client bundle
7+
env: {
8+
NEXT_PUBLIC_SENTRY_SPOTLIGHT: 'true',
9+
},
10+
};
11+
12+
module.exports = withSentryConfig(nextConfig, {
13+
silent: true,
14+
});
15+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"name": "nextjs-15-spotlight",
3+
"version": "0.1.0",
4+
"private": true,
5+
"scripts": {
6+
"dev": "next dev -p 3030",
7+
"build": "next build",
8+
"test": "playwright test",
9+
"test:build": "pnpm install",
10+
"test:assert": "pnpm test"
11+
},
12+
"dependencies": {
13+
"@sentry/nextjs": "latest || *",
14+
"@types/node": "^18.19.1",
15+
"@types/react": "18.0.26",
16+
"@types/react-dom": "18.0.9",
17+
"next": "15.5.7",
18+
"react": "latest",
19+
"react-dom": "latest",
20+
"typescript": "~5.0.0"
21+
},
22+
"devDependencies": {
23+
"@playwright/test": "~1.53.2",
24+
"@sentry-internal/test-utils": "link:../../../test-utils"
25+
},
26+
"volta": {
27+
"extends": "../../package.json"
28+
}
29+
}
30+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { getPlaywrightConfig } from '@sentry-internal/test-utils';
2+
3+
const config = getPlaywrightConfig({
4+
// Use next dev to test development-mode behavior where Spotlight is auto-enabled
5+
startCommand: 'pnpm dev',
6+
port: 3030,
7+
eventProxyFile: 'start-event-proxy.mjs',
8+
eventProxyPort: 3031,
9+
// Increase timeout for dev server startup (slower than production)
10+
timeout: 90_000,
11+
});
12+
13+
export default config;
14+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { startEventProxyServer } from '@sentry-internal/test-utils';
2+
3+
startEventProxyServer({
4+
port: 3031,
5+
proxyServerName: 'nextjs-15-spotlight',
6+
});
7+
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { expect, test } from '@playwright/test';
2+
3+
test.describe('Spotlight auto-enablement in Next.js development mode', () => {
4+
test('Spotlight is automatically enabled when NEXT_PUBLIC_SENTRY_SPOTLIGHT=true', async ({ page }) => {
5+
await page.goto('/');
6+
7+
// Wait for client-side hydration and Sentry initialization
8+
await page.waitForTimeout(2000);
9+
10+
// Check environment variable is accessible
11+
const envValue = await page.getByTestId('env-value').textContent();
12+
expect(envValue).toContain('true');
13+
14+
// Check Spotlight integration is enabled
15+
const spotlightStatus = await page.getByTestId('spotlight-enabled').textContent();
16+
expect(spotlightStatus).toBe('ENABLED');
17+
});
18+
19+
test('no console errors during initialization', async ({ page }) => {
20+
const consoleErrors: string[] = [];
21+
22+
page.on('console', msg => {
23+
if (msg.type() === 'error') {
24+
consoleErrors.push(msg.text());
25+
}
26+
});
27+
28+
page.on('pageerror', error => {
29+
consoleErrors.push(error.message);
30+
});
31+
32+
await page.goto('/');
33+
await page.waitForTimeout(2000);
34+
35+
// Filter out known non-critical errors (if any)
36+
const criticalErrors = consoleErrors.filter(
37+
err =>
38+
err.includes('SyntaxError') ||
39+
err.includes('import.meta') ||
40+
err.includes('Unexpected token') ||
41+
err.includes('Cannot use'),
42+
);
43+
44+
expect(criticalErrors).toHaveLength(0);
45+
});
46+
});
47+

0 commit comments

Comments
 (0)