Skip to content

Commit 9ef14ff

Browse files
committed
simplifications
1 parent 5deeb64 commit 9ef14ff

File tree

6 files changed

+97
-55
lines changed

6 files changed

+97
-55
lines changed

CONTRIBUTING.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,72 @@ the tests in each location. Check out the `scripts` entry of the corresponding `
7373

7474
Note: you must run `yarn build` before `yarn test` will work.
7575

76+
## Running E2E Tests Locally
77+
78+
The E2E tests in `dev-packages/e2e-tests/test-applications/` use Playwright and pnpm. To run them locally:
79+
80+
### Prerequisites
81+
82+
1. **Enable pnpm support in Volta** (required for E2E tests):
83+
84+
```bash
85+
export VOLTA_FEATURE_PNPM=1
86+
```
87+
88+
Add this to your shell profile (`.bashrc`, `.zshrc`, etc.) for persistence.
89+
90+
2. **Build the SDK packages** you want to test:
91+
92+
```bash
93+
yarn build:dev:filter @sentry/nextjs # or whichever package you're testing
94+
```
95+
96+
### Running a specific E2E test app
97+
98+
1. Navigate to the test application directory:
99+
100+
```bash
101+
cd dev-packages/e2e-tests/test-applications/<app-name>
102+
```
103+
104+
2. Install dependencies:
105+
106+
```bash
107+
pnpm install
108+
```
109+
110+
3. Link local SDK packages (to test your changes instead of the published version):
111+
112+
```bash
113+
# Remove existing @sentry packages and create symlinks to local builds
114+
rm -rf node_modules/@sentry
115+
mkdir -p node_modules/@sentry
116+
ln -sf ../../../../../../../../packages/nextjs node_modules/@sentry/nextjs
117+
ln -sf ../../../../../../../../packages/core node_modules/@sentry/core
118+
ln -sf ../../../../../../../../packages/browser node_modules/@sentry/browser
119+
ln -sf ../../../../../../../../packages/react node_modules/@sentry/react
120+
# Add other packages as needed for your test
121+
```
122+
123+
4. Install Playwright browsers (first time only):
124+
125+
```bash
126+
npx playwright install chromium
127+
```
128+
129+
5. Run the tests:
130+
131+
```bash
132+
npx playwright test
133+
```
134+
135+
### Troubleshooting
136+
137+
- **WSL2 Chromium issues**: If you encounter "Invalid file descriptor to ICU data" or segfaults, you may need a newer
138+
Playwright version. The test apps use `@playwright/test: ~1.56.0` which works in WSL2.
139+
- **Stale builds**: After making SDK changes, rebuild with `yarn build:dev:filter @sentry/<package>` and re-link.
140+
- **Port conflicts**: Check if the test app's port (usually 3030) is available.
141+
76142
## Debug Build Flags
77143

78144
Throughout the codebase, you will find a `__DEBUG_BUILD__` constant. This flag serves two purposes:

dev-packages/e2e-tests/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ tmp
44
.tmp_build_stderr
55
pnpm-lock.yaml
66
.last-run.json
7+
.next

packages/browser/src/utils/env.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
/**
22
* Safely gets an environment variable value with defensive guards for browser environments.
3-
* Checks both process.env and import.meta.env to support different bundlers:
3+
* Checks multiple sources to support different bundlers:
44
* - process.env: Webpack, Next.js, Create React App, Parcel (works in both ESM and CJS)
55
* - import.meta.env: Vite, Astro, SvelteKit (ESM only - stripped from CJS builds)
6+
* - globalThis: Turbopack and other bundlers that inject values at runtime
67
*
78
* @param key - The environment variable key to look up
89
* @returns The value of the environment variable or undefined if not found
@@ -38,5 +39,17 @@ export function getEnvValue(key: string): string | undefined {
3839
}
3940
/* rollup-esm-only-end */
4041

42+
// Check globalThis for bundler-injected values (e.g., Turbopack's valueInjectionLoader)
43+
try {
44+
if (typeof globalThis !== 'undefined') {
45+
const value = (globalThis as Record<string, unknown>)[key];
46+
if (typeof value === 'string') {
47+
return value;
48+
}
49+
}
50+
} catch (e) {
51+
// Silently ignore
52+
}
53+
4154
return undefined;
4255
}

packages/nextjs/src/client/index.ts

Lines changed: 7 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,9 @@
22
// can be removed once following issue is fixed: https://github.com/import-js/eslint-plugin-import/issues/703
33
/* eslint-disable import/export */
44
import type { Client, EventProcessor, Integration } from '@sentry/core';
5-
import {
6-
addEventProcessor,
7-
applySdkMetadata,
8-
consoleSandbox,
9-
envToBool,
10-
getGlobalScope,
11-
GLOBAL_OBJ,
12-
resolveSpotlightOptions,
13-
} from '@sentry/core';
5+
import { addEventProcessor, applySdkMetadata, consoleSandbox, getGlobalScope, GLOBAL_OBJ } from '@sentry/core';
146
import type { BrowserOptions } from '@sentry/react';
15-
import {
16-
getDefaultIntegrations as getReactDefaultIntegrations,
17-
init as reactInit,
18-
spotlightBrowserIntegration,
19-
} from '@sentry/react';
7+
import { getDefaultIntegrations as getReactDefaultIntegrations, init as reactInit } from '@sentry/react';
208
import { devErrorSymbolicationEventProcessor } from '../common/devErrorSymbolicationEventProcessor';
219
import { getVercelEnv } from '../common/getVercelEnv';
2210
import { isRedirectNavigationError } from '../common/nextNavigationErrorUtils';
@@ -43,7 +31,6 @@ const globalWithInjectedValues = GLOBAL_OBJ as typeof GLOBAL_OBJ & {
4331
_sentryBasePath?: string;
4432
_sentryRelease?: string;
4533
_experimentalThirdPartyOriginStackFrames?: string;
46-
_sentrySpotlight?: string;
4734
};
4835

4936
// Treeshakable guard to remove all code related to tracing
@@ -143,39 +130,11 @@ function getDefaultIntegrations(options: BrowserOptions): Integration[] {
143130
}),
144131
);
145132

146-
// Auto-enable Spotlight from NEXT_PUBLIC_SENTRY_SPOTLIGHT env var
147-
// The value is injected at build time:
148-
// - Webpack: via DefinePlugin which replaces process.env._sentrySpotlight
149-
// - Turbopack: via valueInjectionLoader which sets globalThis._sentrySpotlight
150-
// - Manual: user can set window._sentrySpotlight in instrumentation-client.ts
151-
const processEnvSpotlight = process.env._sentrySpotlight;
152-
const globalSpotlight = globalWithInjectedValues._sentrySpotlight;
153-
154-
// Check window directly for manual setting (most reliable in browser)
155-
// This is set in instrumentation-client.ts before Sentry.init()
156-
const windowObj = typeof window !== 'undefined' ? window : undefined;
157-
const windowSpotlight = windowObj ? (windowObj as unknown as Record<string, unknown>)._sentrySpotlight : undefined;
158-
159-
// Convert window value to string if it's a boolean or other type
160-
const windowSpotlightStr =
161-
typeof windowSpotlight === 'string'
162-
? windowSpotlight
163-
: typeof windowSpotlight === 'boolean'
164-
? String(windowSpotlight)
165-
: undefined;
166-
167-
const spotlightEnvValue: string | undefined = processEnvSpotlight || globalSpotlight || windowSpotlightStr;
168-
169-
if (spotlightEnvValue !== undefined && options.spotlight === undefined) {
170-
const boolValue = envToBool(spotlightEnvValue, { strict: true });
171-
const spotlightConfig = boolValue !== null ? boolValue : spotlightEnvValue;
172-
const spotlightValue = resolveSpotlightOptions(undefined, spotlightConfig);
173-
174-
if (spotlightValue) {
175-
const spotlightArgs = typeof spotlightValue === 'string' ? { sidecarUrl: spotlightValue } : undefined;
176-
customDefaultIntegrations.push(spotlightBrowserIntegration(spotlightArgs));
177-
}
178-
}
133+
// Note: Spotlight auto-enablement from NEXT_PUBLIC_SENTRY_SPOTLIGHT is handled by the
134+
// browser SDK's init() function. The Next.js build config injects the env var value via:
135+
// - Webpack: DefinePlugin replaces process.env.NEXT_PUBLIC_SENTRY_SPOTLIGHT
136+
// - Turbopack: valueInjectionLoader sets globalThis.NEXT_PUBLIC_SENTRY_SPOTLIGHT
137+
// The browser SDK's getEnvValue() checks both sources.
179138

180139
return customDefaultIntegrations;
181140
}

packages/nextjs/src/config/turbopack/generateValueInjectionRules.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ export function generateValueInjectionRules({
3535
isomorphicValues._sentryRewritesTunnelPath = tunnelPath;
3636
}
3737

38-
// Inject Spotlight config for client (Spotlight is a client-side feature)
38+
// Inject Spotlight config for client so the browser SDK can auto-enable Spotlight.
39+
// Next.js doesn't expose NEXT_PUBLIC_* vars to node_modules, so we inject it via
40+
// globalThis. The browser SDK's getEnvValue() checks globalThis as a fallback.
3941
if (spotlightConfig) {
40-
clientValues._sentrySpotlight = spotlightConfig;
42+
clientValues.NEXT_PUBLIC_SENTRY_SPOTLIGHT = spotlightConfig;
4143
}
4244

4345
if (Object.keys(isomorphicValues).length > 0) {

packages/nextjs/src/config/webpack.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -447,13 +447,14 @@ export function constructWebpackConfigFunction({
447447
}),
448448
);
449449

450-
// Inject Spotlight config for client builds so the SDK can auto-enable Spotlight
451-
// when NEXT_PUBLIC_SENTRY_SPOTLIGHT is set. We use DefinePlugin because Next.js
452-
// doesn't replace process.env.* in node_modules code.
450+
// Inject Spotlight config for client builds so the browser SDK can auto-enable Spotlight.
451+
// Next.js doesn't replace process.env.NEXT_PUBLIC_* in node_modules code, so we use
452+
// DefinePlugin to inject the value directly. The browser SDK's getSpotlightConfig()
453+
// already checks for NEXT_PUBLIC_SENTRY_SPOTLIGHT.
453454
if (runtime === 'client' && spotlightConfig) {
454455
newConfig.plugins.push(
455456
new buildContext.webpack.DefinePlugin({
456-
'process.env._sentrySpotlight': JSON.stringify(spotlightConfig),
457+
'process.env.NEXT_PUBLIC_SENTRY_SPOTLIGHT': JSON.stringify(spotlightConfig),
457458
}),
458459
);
459460
}

0 commit comments

Comments
 (0)