From 59a985fed28d42ee3677af695bb7eeb798a64aae Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Thu, 30 May 2024 19:13:49 -0400 Subject: [PATCH 01/41] replay web vital breadcrumbs --- .../src/coreHandlers/performanceObserver.ts | 14 ++- .../replay-internal/src/types/performance.ts | 38 +++++++- .../replay-internal/src/types/replayFrame.ts | 21 ++++ .../src/util/createPerformanceEntries.ts | 97 ++++++++++++++++++- 4 files changed, 165 insertions(+), 5 deletions(-) diff --git a/packages/replay-internal/src/coreHandlers/performanceObserver.ts b/packages/replay-internal/src/coreHandlers/performanceObserver.ts index 45b843760e52..6f5b2d2633aa 100644 --- a/packages/replay-internal/src/coreHandlers/performanceObserver.ts +++ b/packages/replay-internal/src/coreHandlers/performanceObserver.ts @@ -1,7 +1,8 @@ -import { addLcpInstrumentationHandler, addPerformanceInstrumentationHandler } from '@sentry-internal/browser-utils'; +import { addClsInstrumentationHandler, addFidInstrumentationHandler, addLcpInstrumentationHandler, addPerformanceInstrumentationHandler } from '@sentry-internal/browser-utils'; import type { ReplayContainer } from '../types'; -import { getLargestContentfulPaint } from '../util/createPerformanceEntries'; +import { getLargestContentfulPaint, getCumulativeLayoutShift, getFirstInputDelay, getInteractionToNextPaint } from '../util/createPerformanceEntries'; +import { addInpInstrumentationHandler } from '@sentry-internal/browser-utils/build/types/metrics/instrument'; /** * Sets up a PerformanceObserver to listen to all performance entry types. @@ -29,6 +30,15 @@ export function setupPerformanceObserver(replay: ReplayContainer): () => void { addLcpInstrumentationHandler(({ metric }) => { replay.replayPerformanceEntries.push(getLargestContentfulPaint(metric)); }), + addClsInstrumentationHandler(({ metric }) => { + replay.replayPerformanceEntries.push(getCumulativeLayoutShift(metric)); + }), + addFidInstrumentationHandler(({ metric }) => { + replay.replayPerformanceEntries.push(getFirstInputDelay(metric)); + }), + addInpInstrumentationHandler(({ metric }) => { + replay.replayPerformanceEntries.push(getInteractionToNextPaint(metric)); + }), ); // A callback to cleanup all handlers diff --git a/packages/replay-internal/src/types/performance.ts b/packages/replay-internal/src/types/performance.ts index 2fe87d24a9c8..590d68d56c2d 100644 --- a/packages/replay-internal/src/types/performance.ts +++ b/packages/replay-internal/src/types/performance.ts @@ -108,10 +108,46 @@ export interface LargestContentfulPaintData { nodeId?: number; } +export interface CumulativeLayoutShiftData { + /** + * Render time (in ms) of the CLS + */ + value: number; + size: number; + /** + * The recording id of the CLS node. -1 if not found + */ + nodeId?: number; +} + +export interface FirstInputDelayData { + /** + * Render time (in ms) of the FID + */ + value: number; + size: number; + /** + * The recording id of the FID node. -1 if not found + */ + nodeId?: number; +} + +export interface InteractionToNextPaintData { + /** + * Render time (in ms) of the INP + */ + value: number; + size: number; + /** + * The recording id of the INP node. -1 if not found + */ + nodeId?: number; +} + /** * Entries that come from window.performance */ -export type AllPerformanceEntryData = PaintData | NavigationData | ResourceData | LargestContentfulPaintData; +export type AllPerformanceEntryData = PaintData | NavigationData | ResourceData | LargestContentfulPaintData | CumulativeLayoutShiftData | FirstInputDelayData; export interface MemoryData { memory: { diff --git a/packages/replay-internal/src/types/replayFrame.ts b/packages/replay-internal/src/types/replayFrame.ts index 48dc4aa72a2a..b2237f1722e7 100644 --- a/packages/replay-internal/src/types/replayFrame.ts +++ b/packages/replay-internal/src/types/replayFrame.ts @@ -3,6 +3,9 @@ import type { Breadcrumb } from '@sentry/types'; import type { HistoryData, LargestContentfulPaintData, + CumulativeLayoutShiftData, + FirstInputDelayData, + InteractionToNextPaintData, MemoryData, NavigationData, NetworkRequestData, @@ -167,6 +170,21 @@ interface ReplayLargestContentfulPaintFrame extends ReplayBaseSpanFrame { op: 'largest-contentful-paint'; } +interface ReplayCumulativeLayoutShiftFrame extends ReplayBaseSpanFrame { + data: CumulativeLayoutShiftData; + op: 'cumulative-layout-shift'; +} + +interface ReplayFirstInputDelayFrame extends ReplayBaseSpanFrame { + data: FirstInputDelayData; + op: 'first-input-delay'; +} + +interface ReplayInteractionToNextPaintFrame extends ReplayBaseSpanFrame { + data: InteractionToNextPaintData; + op: 'interaction-to-next-paint'; +} + interface ReplayMemoryFrame extends ReplayBaseSpanFrame { data: MemoryData; op: 'memory'; @@ -197,6 +215,9 @@ export type ReplaySpanFrame = | ReplayHistoryFrame | ReplayRequestFrame | ReplayLargestContentfulPaintFrame + | ReplayCumulativeLayoutShiftFrame + | ReplayFirstInputDelayFrame + | ReplayInteractionToNextPaintFrame | ReplayMemoryFrame | ReplayNavigationFrame | ReplayPaintFrame diff --git a/packages/replay-internal/src/util/createPerformanceEntries.ts b/packages/replay-internal/src/util/createPerformanceEntries.ts index 20217d9e4083..dfb91382e613 100644 --- a/packages/replay-internal/src/util/createPerformanceEntries.ts +++ b/packages/replay-internal/src/util/createPerformanceEntries.ts @@ -7,6 +7,9 @@ import type { AllPerformanceEntryData, ExperimentalPerformanceResourceTiming, LargestContentfulPaintData, + CumulativeLayoutShiftData, + FirstInputDelayData, + InteractionToNextPaintData, NavigationData, PaintData, ReplayPerformanceEntry, @@ -141,7 +144,7 @@ function createResourceEntry( } /** - * Add a LCP event to the replay based on an LCP metric. + * Add a LCP event to the replay based on a LCP metric. */ export function getLargestContentfulPaint(metric: { value: number; @@ -156,7 +159,7 @@ export function getLargestContentfulPaint(metric: { const end = getAbsoluteTime(value); const data: ReplayPerformanceEntry = { - type: 'largest-contentful-paint', + type: 'web-vital', name: 'largest-contentful-paint', start: end, end, @@ -169,3 +172,93 @@ export function getLargestContentfulPaint(metric: { return data; } + +/** + * Add a CLS event to the replay based on a CLS metric. + */ +export function getCumulativeLayoutShift(metric: { + value: number; + entries: PerformanceEntry[]; +}): ReplayPerformanceEntry { + const entries = metric.entries; + const lastEntry = entries[entries.length - 1] as (PerformanceEntry & { element?: Element }) | undefined; + const element = lastEntry ? lastEntry.element : undefined; + + const value = metric.value; + + const end = getAbsoluteTime(value); + + const data: ReplayPerformanceEntry = { + type: 'web-vital', + name: 'cumulative-layout-shift', + start: end, + end, + data: { + value, + size: value, + nodeId: element ? record.mirror.getId(element) : undefined, + }, + }; + + return data; +} + +/** + * Add a FID event to the replay based on a FID metric. + */ +export function getFirstInputDelay(metric: { + value: number; + entries: PerformanceEntry[]; +}): ReplayPerformanceEntry { + const entries = metric.entries; + const lastEntry = entries[entries.length - 1] as (PerformanceEntry & { element?: Element }) | undefined; + const element = lastEntry ? lastEntry.element : undefined; + + const value = metric.value; + + const end = getAbsoluteTime(value); + + const data: ReplayPerformanceEntry = { + type: 'web-vital', + name: 'first-input-delay', + start: end, + end, + data: { + value, + size: value, + nodeId: element ? record.mirror.getId(element) : undefined, + }, + }; + + return data; +} + +/** + * Add an INP event to the replay based on an INP metric. + */ +export function getInteractionToNextPaint(metric: { + value: number; + entries: PerformanceEntry[]; +}): ReplayPerformanceEntry { + const entries = metric.entries; + const lastEntry = entries[entries.length - 1] as (PerformanceEntry & { element?: Element }) | undefined; + const element = lastEntry ? lastEntry.element : undefined; + + const value = metric.value; + + const end = getAbsoluteTime(value); + + const data: ReplayPerformanceEntry = { + type: 'web-vital', + name: 'interaction-to-next-paint', + start: end, + end, + data: { + value, + size: value, + nodeId: element ? record.mirror.getId(element) : undefined, + }, + }; + + return data; +} From 6e29bcc01a3c74f1e0230a2907e05bc7d7ddbff0 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Fri, 31 May 2024 18:34:51 -0400 Subject: [PATCH 02/41] placeholder tests --- .../utils/replayEventTemplates.ts | 2 +- .../tests/fixtures/ReplayRecordingData.ts | 2 +- .../tests/fixtures/ReplayRecordingData.ts | 2 +- .../unit/util/createPerformanceEntry.test.ts | 61 ++++++++++++++++++- 4 files changed, 62 insertions(+), 5 deletions(-) diff --git a/dev-packages/browser-integration-tests/utils/replayEventTemplates.ts b/dev-packages/browser-integration-tests/utils/replayEventTemplates.ts index 03354c6b3185..9fe881fd0656 100644 --- a/dev-packages/browser-integration-tests/utils/replayEventTemplates.ts +++ b/dev-packages/browser-integration-tests/utils/replayEventTemplates.ts @@ -121,7 +121,7 @@ export const expectedMemoryPerformanceSpan = { }; export const expectedLCPPerformanceSpan = { - op: 'largest-contentful-paint', + op: 'web-vital', description: 'largest-contentful-paint', startTimestamp: expect.any(Number), endTimestamp: expect.any(Number), diff --git a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts index 0b454ba12214..96e180351044 100644 --- a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts +++ b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts @@ -211,7 +211,7 @@ export const ReplayRecordingData = [ data: { tag: 'performanceSpan', payload: { - op: 'largest-contentful-paint', + op: 'web-vital', description: 'largest-contentful-paint', startTimestamp: expect.any(Number), endTimestamp: expect.any(Number), diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/fixtures/ReplayRecordingData.ts b/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/fixtures/ReplayRecordingData.ts index 0b454ba12214..96e180351044 100644 --- a/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/fixtures/ReplayRecordingData.ts +++ b/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/fixtures/ReplayRecordingData.ts @@ -211,7 +211,7 @@ export const ReplayRecordingData = [ data: { tag: 'performanceSpan', payload: { - op: 'largest-contentful-paint', + op: 'web-vital', description: 'largest-contentful-paint', startTimestamp: expect.any(Number), endTimestamp: expect.any(Number), diff --git a/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts b/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts index 176de1c2d32e..aaed822f90df 100644 --- a/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts +++ b/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts @@ -11,7 +11,7 @@ vi.mock('@sentry/utils', async () => ({ })); import { WINDOW } from '../../../src/constants'; -import { createPerformanceEntries, getLargestContentfulPaint } from '../../../src/util/createPerformanceEntries'; +import { createPerformanceEntries, getLargestContentfulPaint, getCumulativeLayoutShift, getFirstInputDelay, getInteractionToNextPaint } from '../../../src/util/createPerformanceEntries'; import { PerformanceEntryNavigation } from '../../fixtures/performanceEntry/navigation'; describe('Unit | util | createPerformanceEntries', () => { @@ -72,7 +72,7 @@ describe('Unit | util | createPerformanceEntries', () => { const event = getLargestContentfulPaint(metric); expect(event).toEqual({ - type: 'largest-contentful-paint', + type: 'web-vital', name: 'largest-contentful-paint', start: 1672531205.108299, end: 1672531205.108299, @@ -80,4 +80,61 @@ describe('Unit | util | createPerformanceEntries', () => { }); }); }); + + describe('getCumulativeLayoutShift', () => { + it('works with an CLS metric', async () => { + const metric = { + value: 5108.299, + entries: [], + }; + + const event = getCumulativeLayoutShift(metric); + + expect(event).toEqual({ + type: 'web-vital', + name: 'cumulative-layout-shift', + start: 1672531205.108299, + end: 1672531205.108299, + data: { value: 5108.299, size: 5108.299, nodeId: undefined }, + }); + }); + }); + + describe('getFirstInputDelay', () => { + it('works with an FID metric', async () => { + const metric = { + value: 5108.299, + entries: [], + }; + + const event = getFirstInputDelay(metric); + + expect(event).toEqual({ + type: 'web-vital', + name: 'first-input-delay', + start: 1672531205.108299, + end: 1672531205.108299, + data: { value: 5108.299, size: 5108.299, nodeId: undefined }, + }); + }); + }); + + describe('getInteractionToNextPaint', () => { + it('works with an INP metric', async () => { + const metric = { + value: 5108.299, + entries: [], + }; + + const event = getInteractionToNextPaint(metric); + + expect(event).toEqual({ + type: 'web-vital', + name: 'interaction-to-next-paint', + start: 1672531205.108299, + end: 1672531205.108299, + data: { value: 5108.299, size: 5108.299, nodeId: undefined }, + }); + }); + }); }); From 32a774b41f77e8fef12e58d4752c2c03d87c4bdb Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Mon, 3 Jun 2024 19:59:00 -0400 Subject: [PATCH 03/41] update tests and refactor --- .../suites/replay/customEvents/test.ts | 6 ++ .../suites/replay/multiple-pages/test.ts | 15 +++ .../utils/replayEventTemplates.ts | 40 +++++++ .../tests/fixtures/ReplayRecordingData.ts | 2 +- .../replay-internal/src/types/performance.ts | 43 ++------ .../replay-internal/src/types/replayFrame.ts | 13 +-- .../src/util/createPerformanceEntries.ts | 100 +++++------------- .../unit/util/createPerformanceEntry.test.ts | 12 ++- 8 files changed, 108 insertions(+), 123 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts index 41c90d94ffdf..a5f4d167b8cb 100644 --- a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts @@ -6,6 +6,9 @@ import { expectedFCPPerformanceSpan, expectedFPPerformanceSpan, expectedLCPPerformanceSpan, + expectedCLSPerformanceSpan, + expectedFIDPerformanceSpan, + expectedINPPerformanceSpan, expectedMemoryPerformanceSpan, expectedNavigationPerformanceSpan, getExpectedReplayEvent, @@ -62,6 +65,9 @@ sentryTest( expect.arrayContaining([ expectedNavigationPerformanceSpan, expectedLCPPerformanceSpan, + expectedCLSPerformanceSpan, + expectedFIDPerformanceSpan, + expectedINPPerformanceSpan, expectedFPPerformanceSpan, expectedFCPPerformanceSpan, expectedMemoryPerformanceSpan, // two memory spans - once per flush diff --git a/dev-packages/browser-integration-tests/suites/replay/multiple-pages/test.ts b/dev-packages/browser-integration-tests/suites/replay/multiple-pages/test.ts index 1148847f09c7..3fdd63b30cd9 100644 --- a/dev-packages/browser-integration-tests/suites/replay/multiple-pages/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/multiple-pages/test.ts @@ -6,6 +6,9 @@ import { expectedFCPPerformanceSpan, expectedFPPerformanceSpan, expectedLCPPerformanceSpan, + expectedCLSPerformanceSpan, + expectedFIDPerformanceSpan, + expectedINPPerformanceSpan, expectedMemoryPerformanceSpan, expectedNavigationBreadcrumb, expectedNavigationPerformanceSpan, @@ -83,6 +86,9 @@ sentryTest( expect.arrayContaining([ expectedNavigationPerformanceSpan, expectedLCPPerformanceSpan, + expectedCLSPerformanceSpan, + expectedFIDPerformanceSpan, + expectedINPPerformanceSpan, expectedFPPerformanceSpan, expectedFCPPerformanceSpan, expectedMemoryPerformanceSpan, // two memory spans - once per flush @@ -121,6 +127,9 @@ sentryTest( expect.arrayContaining([ expectedReloadPerformanceSpan, expectedLCPPerformanceSpan, + expectedCLSPerformanceSpan, + expectedFIDPerformanceSpan, + expectedINPPerformanceSpan, expectedFPPerformanceSpan, expectedFCPPerformanceSpan, expectedMemoryPerformanceSpan, @@ -188,6 +197,9 @@ sentryTest( expect.arrayContaining([ expectedNavigationPerformanceSpan, expectedLCPPerformanceSpan, + expectedCLSPerformanceSpan, + expectedFIDPerformanceSpan, + expectedINPPerformanceSpan, expectedFPPerformanceSpan, expectedFCPPerformanceSpan, expectedMemoryPerformanceSpan, @@ -309,6 +321,9 @@ sentryTest( expect.arrayContaining([ expectedNavigationPerformanceSpan, expectedLCPPerformanceSpan, + expectedCLSPerformanceSpan, + expectedFIDPerformanceSpan, + expectedINPPerformanceSpan, expectedFPPerformanceSpan, expectedFCPPerformanceSpan, expectedMemoryPerformanceSpan, diff --git a/dev-packages/browser-integration-tests/utils/replayEventTemplates.ts b/dev-packages/browser-integration-tests/utils/replayEventTemplates.ts index 9fe881fd0656..878edd77b58e 100644 --- a/dev-packages/browser-integration-tests/utils/replayEventTemplates.ts +++ b/dev-packages/browser-integration-tests/utils/replayEventTemplates.ts @@ -128,6 +128,46 @@ export const expectedLCPPerformanceSpan = { data: { value: expect.any(Number), nodeId: expect.any(Number), + rating: expect.any(String), + size: expect.any(Number), + }, +}; + +export const expectedCLSPerformanceSpan = { + op: 'web-vital', + description: 'cumulative-layout-shift', + startTimestamp: expect.any(Number), + endTimestamp: expect.any(Number), + data: { + value: expect.any(Number), + nodeId: expect.any(Number), + rating: expect.any(String), + size: expect.any(Number), + }, +}; + +export const expectedFIDPerformanceSpan = { + op: 'web-vital', + description: 'first-input-delay', + startTimestamp: expect.any(Number), + endTimestamp: expect.any(Number), + data: { + value: expect.any(Number), + nodeId: expect.any(Number), + rating: expect.any(String), + size: expect.any(Number), + }, +}; + +export const expectedINPPerformanceSpan = { + op: 'web-vital', + description: 'interaction-to-next-paint', + startTimestamp: expect.any(Number), + endTimestamp: expect.any(Number), + data: { + value: expect.any(Number), + nodeId: expect.any(Number), + rating: expect.any(String), size: expect.any(Number), }, }; diff --git a/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/fixtures/ReplayRecordingData.ts b/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/fixtures/ReplayRecordingData.ts index 554fac59f88e..e7fd943c0f08 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/fixtures/ReplayRecordingData.ts +++ b/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/fixtures/ReplayRecordingData.ts @@ -212,7 +212,7 @@ export const ReplayRecordingData = [ data: { tag: 'performanceSpan', payload: { - op: 'largest-contentful-paint', + op: 'web-vital', description: 'largest-contentful-paint', startTimestamp: expect.any(Number), endTimestamp: expect.any(Number), diff --git a/packages/replay-internal/src/types/performance.ts b/packages/replay-internal/src/types/performance.ts index 590d68d56c2d..5241c12d847a 100644 --- a/packages/replay-internal/src/types/performance.ts +++ b/packages/replay-internal/src/types/performance.ts @@ -96,50 +96,19 @@ export type ResourceData = Pick function to normalize data for event @@ -148,29 +145,10 @@ function createResourceEntry( */ export function getLargestContentfulPaint(metric: { value: number; + rating: 'good' | 'needs-improvement' | 'poor'; entries: PerformanceEntry[]; -}): ReplayPerformanceEntry { - const entries = metric.entries; - const lastEntry = entries[entries.length - 1] as (PerformanceEntry & { element?: Element }) | undefined; - const element = lastEntry ? lastEntry.element : undefined; - - const value = metric.value; - - const end = getAbsoluteTime(value); - - const data: ReplayPerformanceEntry = { - type: 'web-vital', - name: 'largest-contentful-paint', - start: end, - end, - data: { - value, - size: value, - nodeId: element ? record.mirror.getId(element) : undefined, - }, - }; - - return data; +}): ReplayPerformanceEntry { + return getWebVital(metric, 'largest-contentful-paint'); } /** @@ -178,29 +156,10 @@ export function getLargestContentfulPaint(metric: { */ export function getCumulativeLayoutShift(metric: { value: number; + rating: 'good' | 'needs-improvement' | 'poor'; entries: PerformanceEntry[]; -}): ReplayPerformanceEntry { - const entries = metric.entries; - const lastEntry = entries[entries.length - 1] as (PerformanceEntry & { element?: Element }) | undefined; - const element = lastEntry ? lastEntry.element : undefined; - - const value = metric.value; - - const end = getAbsoluteTime(value); - - const data: ReplayPerformanceEntry = { - type: 'web-vital', - name: 'cumulative-layout-shift', - start: end, - end, - data: { - value, - size: value, - nodeId: element ? record.mirror.getId(element) : undefined, - }, - }; - - return data; +}): ReplayPerformanceEntry { + return getWebVital(metric, 'cumulative-layout-shift'); } /** @@ -208,29 +167,10 @@ export function getCumulativeLayoutShift(metric: { */ export function getFirstInputDelay(metric: { value: number; + rating: 'good' | 'needs-improvement' | 'poor'; entries: PerformanceEntry[]; -}): ReplayPerformanceEntry { - const entries = metric.entries; - const lastEntry = entries[entries.length - 1] as (PerformanceEntry & { element?: Element }) | undefined; - const element = lastEntry ? lastEntry.element : undefined; - - const value = metric.value; - - const end = getAbsoluteTime(value); - - const data: ReplayPerformanceEntry = { - type: 'web-vital', - name: 'first-input-delay', - start: end, - end, - data: { - value, - size: value, - nodeId: element ? record.mirror.getId(element) : undefined, - }, - }; - - return data; +}): ReplayPerformanceEntry { + return getWebVital(metric, 'first-input-delay'); } /** @@ -238,24 +178,38 @@ export function getFirstInputDelay(metric: { */ export function getInteractionToNextPaint(metric: { value: number; + rating: 'good' | 'needs-improvement' | 'poor'; + entries: PerformanceEntry[]; +}): ReplayPerformanceEntry { + return getWebVital(metric, 'interaction-to-next-paint'); +} + +/** + * Add an web vital event to the replay based on the web vital metric. + */ +export function getWebVital(metric: { + value: number; + rating: 'good' | 'needs-improvement' | 'poor'; entries: PerformanceEntry[]; -}): ReplayPerformanceEntry { +}, name: string): ReplayPerformanceEntry { const entries = metric.entries; const lastEntry = entries[entries.length - 1] as (PerformanceEntry & { element?: Element }) | undefined; const element = lastEntry ? lastEntry.element : undefined; const value = metric.value; + const rating = metric.rating; const end = getAbsoluteTime(value); - const data: ReplayPerformanceEntry = { + const data: ReplayPerformanceEntry = { type: 'web-vital', - name: 'interaction-to-next-paint', + name, start: end, end, data: { value, size: value, + rating, nodeId: element ? record.mirror.getId(element) : undefined, }, }; diff --git a/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts b/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts index aaed822f90df..1433159ed9e2 100644 --- a/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts +++ b/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts @@ -66,6 +66,7 @@ describe('Unit | util | createPerformanceEntries', () => { it('works with an LCP metric', async () => { const metric = { value: 5108.299, + rating: 'good' as const, entries: [], }; @@ -76,7 +77,7 @@ describe('Unit | util | createPerformanceEntries', () => { name: 'largest-contentful-paint', start: 1672531205.108299, end: 1672531205.108299, - data: { value: 5108.299, size: 5108.299, nodeId: undefined }, + data: { value: 5108.299, rating: 'good', size: 5108.299, nodeId: undefined }, }); }); }); @@ -85,6 +86,7 @@ describe('Unit | util | createPerformanceEntries', () => { it('works with an CLS metric', async () => { const metric = { value: 5108.299, + rating: 'good' as const, entries: [], }; @@ -95,7 +97,7 @@ describe('Unit | util | createPerformanceEntries', () => { name: 'cumulative-layout-shift', start: 1672531205.108299, end: 1672531205.108299, - data: { value: 5108.299, size: 5108.299, nodeId: undefined }, + data: { value: 5108.299, size: 5108.299, rating: 'good', nodeId: undefined }, }); }); }); @@ -104,6 +106,7 @@ describe('Unit | util | createPerformanceEntries', () => { it('works with an FID metric', async () => { const metric = { value: 5108.299, + rating: 'good' as const, entries: [], }; @@ -114,7 +117,7 @@ describe('Unit | util | createPerformanceEntries', () => { name: 'first-input-delay', start: 1672531205.108299, end: 1672531205.108299, - data: { value: 5108.299, size: 5108.299, nodeId: undefined }, + data: { value: 5108.299, size: 5108.299, rating: 'good', nodeId: undefined }, }); }); }); @@ -123,6 +126,7 @@ describe('Unit | util | createPerformanceEntries', () => { it('works with an INP metric', async () => { const metric = { value: 5108.299, + rating: 'good' as const, entries: [], }; @@ -133,7 +137,7 @@ describe('Unit | util | createPerformanceEntries', () => { name: 'interaction-to-next-paint', start: 1672531205.108299, end: 1672531205.108299, - data: { value: 5108.299, size: 5108.299, nodeId: undefined }, + data: { value: 5108.299, size: 5108.299, rating: 'good', nodeId: undefined }, }); }); }); From 35c1db0dda4d0938dbba465e57ef5acfa25646f6 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Fri, 31 May 2024 11:15:30 +0200 Subject: [PATCH 04/41] chore: Document e2e test env vars (#12303) Co-authored-by: Andrei <168741329+andreiborza@users.noreply.github.com> --- .github/workflows/build.yml | 6 +++--- .github/workflows/canary.yml | 2 +- dev-packages/e2e-tests/.env.example | 11 ++++++++++- dev-packages/e2e-tests/README.md | 1 - dev-packages/e2e-tests/lib/validate.ts | 4 ++-- .../create-next-app/tests/behaviour-client.test.ts | 2 +- .../create-next-app/tests/behaviour-server.test.ts | 2 +- .../tests/behaviour-client.test.ts | 2 +- .../tests/behaviour-client.test.ts | 2 +- .../tests/behaviour-client.test.ts | 2 +- .../create-remix-app/tests/behaviour-client.test.ts | 2 +- .../create-remix-app/upload-sourcemaps.sh | 2 +- .../debug-id-sourcemaps/rollup.config.mjs | 2 +- .../debug-id-sourcemaps/tests/server.test.ts | 2 +- .../nextjs-app-dir/tests/exceptions.test.ts | 2 +- .../nextjs-app-dir/tests/server-components.test.ts | 2 +- .../nextjs-app-dir/tests/transactions.test.ts | 2 +- .../node-connect/tests/transactions.test.ts | 2 +- .../tests/send-to-sentry.test.ts | 2 +- .../tests/behaviour-test.test.ts | 2 +- .../react-send-to-sentry/tests/send-to-sentry.test.ts | 2 +- .../tests/behaviour-test.spec.ts | 2 +- .../webpack-4/tests/behaviour-test.spec.ts | 2 +- .../webpack-5/tests/behaviour-test.spec.ts | 2 +- 24 files changed, 35 insertions(+), 27 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 93e4b3254ccf..6c2974d4313e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -983,7 +983,7 @@ jobs: PUBLIC_E2E_TEST_DSN: ${{ secrets.E2E_TEST_DSN }} REACT_APP_E2E_TEST_DSN: ${{ secrets.E2E_TEST_DSN }} E2E_TEST_SENTRY_ORG_SLUG: 'sentry-javascript-sdks' - E2E_TEST_SENTRY_TEST_PROJECT: 'sentry-javascript-e2e-tests' + E2E_TEST_SENTRY_PROJECT: 'sentry-javascript-e2e-tests' strategy: fail-fast: false matrix: @@ -1132,7 +1132,7 @@ jobs: PUBLIC_E2E_TEST_DSN: ${{ secrets.E2E_TEST_DSN }} REACT_APP_E2E_TEST_DSN: ${{ secrets.E2E_TEST_DSN }} E2E_TEST_SENTRY_ORG_SLUG: 'sentry-javascript-sdks' - E2E_TEST_SENTRY_TEST_PROJECT: 'sentry-javascript-e2e-tests' + E2E_TEST_SENTRY_PROJECT: 'sentry-javascript-e2e-tests' strategy: fail-fast: false matrix: @@ -1219,7 +1219,7 @@ jobs: E2E_TEST_AUTH_TOKEN: ${{ secrets.E2E_TEST_AUTH_TOKEN }} E2E_TEST_DSN: ${{ secrets.E2E_TEST_DSN }} E2E_TEST_SENTRY_ORG_SLUG: 'sentry-javascript-sdks' - E2E_TEST_SENTRY_TEST_PROJECT: 'sentry-javascript-e2e-tests' + E2E_TEST_SENTRY_PROJECT: 'sentry-javascript-e2e-tests' strategy: fail-fast: false matrix: diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index 5f58292646df..2cc7361374cd 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -63,7 +63,7 @@ jobs: PUBLIC_E2E_TEST_DSN: ${{ secrets.E2E_TEST_DSN }} REACT_APP_E2E_TEST_DSN: ${{ secrets.E2E_TEST_DSN }} E2E_TEST_SENTRY_ORG_SLUG: 'sentry-javascript-sdks' - E2E_TEST_SENTRY_TEST_PROJECT: 'sentry-javascript-e2e-tests' + E2E_TEST_SENTRY_PROJECT: 'sentry-javascript-e2e-tests' strategy: fail-fast: false matrix: diff --git a/dev-packages/e2e-tests/.env.example b/dev-packages/e2e-tests/.env.example index 559550968130..c598b7cbf597 100644 --- a/dev-packages/e2e-tests/.env.example +++ b/dev-packages/e2e-tests/.env.example @@ -1,4 +1,13 @@ +# A Sentry auth token with the scopes, project:read, project:releases, event:read, org:read +# In the Sentry interface this equates to: Project read, Release admin, Issue & Event read, Organization read +# The auth token should be able to access the orgs and projecs provided in the environment variables below. E2E_TEST_AUTH_TOKEN= + +# A DSN to send events to. Should be sending events to the project provided below. E2E_TEST_DSN= + +# A Sentry organization slug E2E_TEST_SENTRY_ORG_SLUG= -E2E_TEST_SENTRY_TEST_PROJECT= + +# A Sentry project slug +E2E_TEST_SENTRY_PROJECT= diff --git a/dev-packages/e2e-tests/README.md b/dev-packages/e2e-tests/README.md index 76fa6370d154..245f21e8d97a 100644 --- a/dev-packages/e2e-tests/README.md +++ b/dev-packages/e2e-tests/README.md @@ -9,7 +9,6 @@ Prerequisites: Docker - Copy `.env.example` to `.env` - Fill in auth information in `.env` for an example Sentry project - - The `E2E_TEST_AUTH_TOKEN` must have all the default permissions - Run `yarn build:tarball` in the root of the repository To finally run all of the tests: diff --git a/dev-packages/e2e-tests/lib/validate.ts b/dev-packages/e2e-tests/lib/validate.ts index 2abb4974ce70..7476067939de 100644 --- a/dev-packages/e2e-tests/lib/validate.ts +++ b/dev-packages/e2e-tests/lib/validate.ts @@ -22,9 +22,9 @@ export function validate(): boolean { missingEnvVar = true; } - if (!process.env.E2E_TEST_SENTRY_TEST_PROJECT) { + if (!process.env.E2E_TEST_SENTRY_PROJECT) { console.log( - 'No Sentry project configured! Please configure the E2E_TEST_SENTRY_TEST_PROJECT environment variable with a Sentry project slug!', + 'No Sentry project configured! Please configure the `E2E_TEST_SENTRY_PROJECT` environment variable with a Sentry project slug!', ); missingEnvVar = true; } diff --git a/dev-packages/e2e-tests/test-applications/create-next-app/tests/behaviour-client.test.ts b/dev-packages/e2e-tests/test-applications/create-next-app/tests/behaviour-client.test.ts index 022cfd1cb5a6..23d1d7126e16 100644 --- a/dev-packages/e2e-tests/test-applications/create-next-app/tests/behaviour-client.test.ts +++ b/dev-packages/e2e-tests/test-applications/create-next-app/tests/behaviour-client.test.ts @@ -2,7 +2,7 @@ import { expect, test } from '@playwright/test'; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; +const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; const EVENT_POLLING_TIMEOUT = 90_000; test('Sends a client-side exception to Sentry', async ({ page }) => { diff --git a/dev-packages/e2e-tests/test-applications/create-next-app/tests/behaviour-server.test.ts b/dev-packages/e2e-tests/test-applications/create-next-app/tests/behaviour-server.test.ts index 0a5fd828f55d..ef30d70c0a52 100644 --- a/dev-packages/e2e-tests/test-applications/create-next-app/tests/behaviour-server.test.ts +++ b/dev-packages/e2e-tests/test-applications/create-next-app/tests/behaviour-server.test.ts @@ -2,7 +2,7 @@ import { expect, test } from '@playwright/test'; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; +const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; const EVENT_POLLING_TIMEOUT = 90_000; test('Sends a server-side exception to Sentry', async ({ baseURL }) => { diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/tests/behaviour-client.test.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/tests/behaviour-client.test.ts index 76d2a49a5afb..6f4f6b17d029 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/tests/behaviour-client.test.ts +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/tests/behaviour-client.test.ts @@ -4,7 +4,7 @@ const EVENT_POLLING_TIMEOUT = 90_000; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; +const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; test('Sends a client-side exception to Sentry', async ({ page }) => { await page.goto('/'); diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express/tests/behaviour-client.test.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-express/tests/behaviour-client.test.ts index 5c347620701c..aecc2fa8c983 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express/tests/behaviour-client.test.ts +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-express/tests/behaviour-client.test.ts @@ -4,7 +4,7 @@ const EVENT_POLLING_TIMEOUT = 90_000; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; +const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; test('Sends a client-side exception to Sentry', async ({ page }) => { await page.goto('/'); diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2/tests/behaviour-client.test.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-v2/tests/behaviour-client.test.ts index 5c347620701c..aecc2fa8c983 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2/tests/behaviour-client.test.ts +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-v2/tests/behaviour-client.test.ts @@ -4,7 +4,7 @@ const EVENT_POLLING_TIMEOUT = 90_000; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; +const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; test('Sends a client-side exception to Sentry', async ({ page }) => { await page.goto('/'); diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app/tests/behaviour-client.test.ts b/dev-packages/e2e-tests/test-applications/create-remix-app/tests/behaviour-client.test.ts index 5c347620701c..aecc2fa8c983 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app/tests/behaviour-client.test.ts +++ b/dev-packages/e2e-tests/test-applications/create-remix-app/tests/behaviour-client.test.ts @@ -4,7 +4,7 @@ const EVENT_POLLING_TIMEOUT = 90_000; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; +const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; test('Sends a client-side exception to Sentry', async ({ page }) => { await page.goto('/'); diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app/upload-sourcemaps.sh b/dev-packages/e2e-tests/test-applications/create-remix-app/upload-sourcemaps.sh index 721a71490e69..35238b47305d 100755 --- a/dev-packages/e2e-tests/test-applications/create-remix-app/upload-sourcemaps.sh +++ b/dev-packages/e2e-tests/test-applications/create-remix-app/upload-sourcemaps.sh @@ -1,3 +1,3 @@ export SENTRY_AUTH_TOKEN=${E2E_TEST_AUTH_TOKEN} -sentry-upload-sourcemaps --org ${E2E_TEST_SENTRY_ORG_SLUG} --project ${E2E_TEST_SENTRY_TEST_PROJECT} +sentry-upload-sourcemaps --org ${E2E_TEST_SENTRY_ORG_SLUG} --project ${E2E_TEST_SENTRY_PROJECT} diff --git a/dev-packages/e2e-tests/test-applications/debug-id-sourcemaps/rollup.config.mjs b/dev-packages/e2e-tests/test-applications/debug-id-sourcemaps/rollup.config.mjs index e9d8f066727d..296e5faba1bb 100644 --- a/dev-packages/e2e-tests/test-applications/debug-id-sourcemaps/rollup.config.mjs +++ b/dev-packages/e2e-tests/test-applications/debug-id-sourcemaps/rollup.config.mjs @@ -7,7 +7,7 @@ export default defineConfig({ plugins: [ sentryRollupPlugin({ org: process.env.E2E_TEST_SENTRY_ORG_SLUG, - project: process.env.E2E_TEST_SENTRY_TEST_PROJECT, + project: process.env.E2E_TEST_SENTRY_PROJECT, authToken: process.env.E2E_TEST_AUTH_TOKEN, }), ], diff --git a/dev-packages/e2e-tests/test-applications/debug-id-sourcemaps/tests/server.test.ts b/dev-packages/e2e-tests/test-applications/debug-id-sourcemaps/tests/server.test.ts index b42a556757b3..d16e8239990c 100644 --- a/dev-packages/e2e-tests/test-applications/debug-id-sourcemaps/tests/server.test.ts +++ b/dev-packages/e2e-tests/test-applications/debug-id-sourcemaps/tests/server.test.ts @@ -4,7 +4,7 @@ import { test } from 'vitest'; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; +const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; const EVENT_POLLING_TIMEOUT = 90_000; test( diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/exceptions.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/exceptions.test.ts index f4cde4417d13..17262be631c2 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/exceptions.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/exceptions.test.ts @@ -3,7 +3,7 @@ import { waitForError } from '@sentry-internal/event-proxy-server'; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; +const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; const EVENT_POLLING_TIMEOUT = 90_000; test('Sends a client-side exception to Sentry', async ({ page }) => { diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/server-components.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/server-components.test.ts index 7dbb1cc2281f..d33a5b535508 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/server-components.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/server-components.test.ts @@ -3,7 +3,7 @@ import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-s const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; +const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; const EVENT_POLLING_TIMEOUT = 90_000; test('Sends a transaction for a server component', async ({ page }) => { diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/transactions.test.ts index f42922668e75..4e5415db657d 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/transactions.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/transactions.test.ts @@ -5,7 +5,7 @@ const packageJson = require('../package.json'); const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; +const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; const EVENT_POLLING_TIMEOUT = 90_000; test('Sends a pageload transaction', async ({ page }) => { diff --git a/dev-packages/e2e-tests/test-applications/node-connect/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/node-connect/tests/transactions.test.ts index d18e4c1b6c20..8a95f4b12c6f 100644 --- a/dev-packages/e2e-tests/test-applications/node-connect/tests/transactions.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-connect/tests/transactions.test.ts @@ -3,7 +3,7 @@ import { waitForTransaction } from '@sentry-internal/event-proxy-server'; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; +const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; const EVENT_POLLING_TIMEOUT = 90_000; test('Sends an API route transaction', async ({ baseURL }) => { diff --git a/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/tests/send-to-sentry.test.ts b/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/tests/send-to-sentry.test.ts index 230cda70eda8..7f699fa111f9 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/tests/send-to-sentry.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/tests/send-to-sentry.test.ts @@ -4,7 +4,7 @@ const EVENT_POLLING_TIMEOUT = 90_000; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; +const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; test('Sends exception to Sentry', async ({ baseURL }) => { const response = await fetch(`${baseURL}/test-error`); diff --git a/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/behaviour-test.test.ts b/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/behaviour-test.test.ts index a4a0106d2d9c..eaf790f99ceb 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/behaviour-test.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/behaviour-test.test.ts @@ -5,7 +5,7 @@ const EVENT_POLLING_TIMEOUT = 90_000; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; +const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; test('Sends an exception to Sentry', async ({ page }) => { await page.goto('/'); diff --git a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts index 8e61940e574c..9c820e2157de 100644 --- a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts @@ -5,7 +5,7 @@ const EVENT_POLLING_TIMEOUT = 90_000; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; +const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; test('Sends an exception to Sentry', async ({ page }) => { await page.goto('/'); diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/behaviour-test.spec.ts b/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/behaviour-test.spec.ts index 35446d1c069c..fabdd40e588f 100644 --- a/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/behaviour-test.spec.ts +++ b/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/behaviour-test.spec.ts @@ -5,7 +5,7 @@ const EVENT_POLLING_TIMEOUT = 90_000; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; +const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; test('Sends an exception to Sentry', async ({ page }) => { await page.goto('/'); diff --git a/dev-packages/e2e-tests/test-applications/webpack-4/tests/behaviour-test.spec.ts b/dev-packages/e2e-tests/test-applications/webpack-4/tests/behaviour-test.spec.ts index 2ef289910a6b..7b824ef26579 100644 --- a/dev-packages/e2e-tests/test-applications/webpack-4/tests/behaviour-test.spec.ts +++ b/dev-packages/e2e-tests/test-applications/webpack-4/tests/behaviour-test.spec.ts @@ -4,7 +4,7 @@ const EVENT_POLLING_TIMEOUT = 90_000; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; +const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; test('Sends an exception to Sentry', async ({ page }) => { await page.goto('/'); diff --git a/dev-packages/e2e-tests/test-applications/webpack-5/tests/behaviour-test.spec.ts b/dev-packages/e2e-tests/test-applications/webpack-5/tests/behaviour-test.spec.ts index 2ef289910a6b..7b824ef26579 100644 --- a/dev-packages/e2e-tests/test-applications/webpack-5/tests/behaviour-test.spec.ts +++ b/dev-packages/e2e-tests/test-applications/webpack-5/tests/behaviour-test.spec.ts @@ -4,7 +4,7 @@ const EVENT_POLLING_TIMEOUT = 90_000; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_TEST_PROJECT; +const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; test('Sends an exception to Sentry', async ({ page }) => { await page.goto('/'); From 2719b026638f6d33b642985d8068a0158374cc26 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Fri, 31 May 2024 11:44:19 +0200 Subject: [PATCH 05/41] fix(browser): Fix idle span ending (#12306) I noticed here https://github.com/getsentry/sentry-javascript/pulls that some tests were becoming flaky. Investigating this some more, I figured out what was happening: 1. For idle spans, when the span is ended (in `on('spanEnded')`, which is triggered in `span.end()`), we call `onIdleSpanEnded` 2. In there, we call `beforeSpanEnd` 3. This is used by `browserTracingIntegration` to call `addPerformanceEntries(span)`, which adds performance spans to the idle span 4. After that, in `onIdleSpanEnded`, any spans having start/end timestamps outside of the idle span start/end timestamp will be discarded This lead to cases where performance spans were discarded because they were out of bounds of the idle span - which is not what we want! Now, this PR changes the timing of this a bit: Now, we actually patch `span.end` of the SentrySpan, to ensure that we can always run `beforeSpanEnd` with the correct timing, taking all spans that are added in `beforeSpanEnd` into account to adjust the start/end time of the idle span. --- .../tests/transactions.test.ts | 4 +- packages/core/src/tracing/idleSpan.ts | 91 ++++++++++--------- packages/core/src/tracing/sentrySpan.ts | 5 +- .../core/test/lib/tracing/idleSpan.test.ts | 12 ++- 4 files changed, 61 insertions(+), 51 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/react-create-hash-router/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/react-create-hash-router/tests/transactions.test.ts index 971d4f31521b..24548324985a 100644 --- a/dev-packages/e2e-tests/test-applications/react-create-hash-router/tests/transactions.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-create-hash-router/tests/transactions.test.ts @@ -10,7 +10,7 @@ test('Captures a pageload transaction', async ({ page }) => { const transactionEvent = await transactionEventPromise; expect(transactionEvent.contexts?.trace).toEqual({ - data: expect.objectContaining({ + data: { deviceMemory: expect.any(String), effectiveConnectionType: expect.any(String), hardwareConcurrency: expect.any(String), @@ -19,7 +19,7 @@ test('Captures a pageload transaction', async ({ page }) => { 'sentry.origin': 'auto.pageload.react.reactrouter_v6', 'sentry.sample_rate': 1, 'sentry.source': 'route', - }), + }, op: 'pageload', span_id: expect.any(String), trace_id: expect.any(String), diff --git a/packages/core/src/tracing/idleSpan.ts b/packages/core/src/tracing/idleSpan.ts index 2f9230b7dd4b..8f3ecb7e7d35 100644 --- a/packages/core/src/tracing/idleSpan.ts +++ b/packages/core/src/tracing/idleSpan.ts @@ -113,37 +113,48 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti const previousActiveSpan = getActiveSpan(); const span = _startIdleSpan(startSpanOptions); - function _endSpan(timestamp: number = timestampInSeconds()): void { - // Ensure we end with the last span timestamp, if possible - const spans = getSpanDescendants(span).filter(child => child !== span); + // We patch span.end to ensure we can run some things before the span is ended + // eslint-disable-next-line @typescript-eslint/unbound-method + span.end = new Proxy(span.end, { + apply(target, thisArg, args: Parameters) { + if (beforeSpanEnd) { + beforeSpanEnd(span); + } - // If we have no spans, we just end, nothing else to do here - if (!spans.length) { - span.end(timestamp); - return; - } + const timestamp = args[0] || timestampInSeconds(); + const spanEndTimestamp = spanTimeInputToSeconds(timestamp); - const childEndTimestamps = spans - .map(span => spanToJSON(span).timestamp) - .filter(timestamp => !!timestamp) as number[]; - const latestSpanEndTimestamp = childEndTimestamps.length ? Math.max(...childEndTimestamps) : undefined; - - const spanEndTimestamp = spanTimeInputToSeconds(timestamp); - // In reality this should always exist here, but type-wise it may be undefined... - const spanStartTimestamp = spanToJSON(span).start_timestamp; - - // The final endTimestamp should: - // * Never be before the span start timestamp - // * Be the latestSpanEndTimestamp, if there is one, and it is smaller than the passed span end timestamp - // * Otherwise be the passed end timestamp - // Final timestamp can never be after finalTimeout - const endTimestamp = Math.min( - spanStartTimestamp ? spanStartTimestamp + finalTimeout / 1000 : Infinity, - Math.max(spanStartTimestamp || -Infinity, Math.min(spanEndTimestamp, latestSpanEndTimestamp || Infinity)), - ); - - span.end(endTimestamp); - } + // Ensure we end with the last span timestamp, if possible + const spans = getSpanDescendants(span).filter(child => child !== span); + + // If we have no spans, we just end, nothing else to do here + if (!spans.length) { + onIdleSpanEnded(spanEndTimestamp); + return Reflect.apply(target, thisArg, args); + } + + const childEndTimestamps = spans + .map(span => spanToJSON(span).timestamp) + .filter(timestamp => !!timestamp) as number[]; + const latestSpanEndTimestamp = childEndTimestamps.length ? Math.max(...childEndTimestamps) : undefined; + + // In reality this should always exist here, but type-wise it may be undefined... + const spanStartTimestamp = spanToJSON(span).start_timestamp; + + // The final endTimestamp should: + // * Never be before the span start timestamp + // * Be the latestSpanEndTimestamp, if there is one, and it is smaller than the passed span end timestamp + // * Otherwise be the passed end timestamp + // Final timestamp can never be after finalTimeout + const endTimestamp = Math.min( + spanStartTimestamp ? spanStartTimestamp + finalTimeout / 1000 : Infinity, + Math.max(spanStartTimestamp || -Infinity, Math.min(spanEndTimestamp, latestSpanEndTimestamp || Infinity)), + ); + + onIdleSpanEnded(endTimestamp); + return Reflect.apply(target, thisArg, [endTimestamp]); + }, + }); /** * Cancels the existing idle timeout, if there is one. @@ -173,7 +184,7 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti _idleTimeoutID = setTimeout(() => { if (!_finished && activities.size === 0 && _autoFinishAllowed) { _finishReason = FINISH_REASON_IDLE_TIMEOUT; - _endSpan(endTimestamp); + span.end(endTimestamp); } }, idleTimeout); } @@ -186,7 +197,7 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti _idleTimeoutID = setTimeout(() => { if (!_finished && _autoFinishAllowed) { _finishReason = FINISH_REASON_HEARTBEAT_FAILED; - _endSpan(endTimestamp); + span.end(endTimestamp); } }, childSpanTimeout); } @@ -223,21 +234,17 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti } } - function onIdleSpanEnded(): void { + function onIdleSpanEnded(endTimestamp: number): void { _finished = true; activities.clear(); - if (beforeSpanEnd) { - beforeSpanEnd(span); - } - _setSpanForScope(scope, previousActiveSpan); const spanJSON = spanToJSON(span); - const { timestamp: endTimestamp, start_timestamp: startTimestamp } = spanJSON; + const { start_timestamp: startTimestamp } = spanJSON; // This should never happen, but to make TS happy... - if (!endTimestamp || !startTimestamp) { + if (!startTimestamp) { return; } @@ -267,7 +274,7 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti // Add a delta with idle timeout so that we prevent false positives const timeoutWithMarginOfError = (finalTimeout + idleTimeout) / 1000; - const spanEndedBeforeFinalTimeout = childEndTimestamp - childStartTimestamp < timeoutWithMarginOfError; + const spanEndedBeforeFinalTimeout = childEndTimestamp - childStartTimestamp <= timeoutWithMarginOfError; if (DEBUG_BUILD) { const stringifiedSpan = JSON.stringify(childSpan, undefined, 2); @@ -312,10 +319,6 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti } _popActivity(endedSpan.spanContext().spanId); - - if (endedSpan === span) { - onIdleSpanEnded(); - } }); client.on('idleSpanEnableAutoFinish', spanToAllowAutoFinish => { @@ -338,7 +341,7 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti if (!_finished) { span.setStatus({ code: SPAN_STATUS_ERROR, message: 'deadline_exceeded' }); _finishReason = FINISH_REASON_FINAL_TIMEOUT; - _endSpan(); + span.end(); } }, finalTimeout); diff --git a/packages/core/src/tracing/sentrySpan.ts b/packages/core/src/tracing/sentrySpan.ts index 9d9706d4ebce..ad2bfeb7dc34 100644 --- a/packages/core/src/tracing/sentrySpan.ts +++ b/packages/core/src/tracing/sentrySpan.ts @@ -342,7 +342,10 @@ export class SentrySpan implements Span { if (hasMeasurements) { DEBUG_BUILD && - logger.log('[Measurements] Adding measurements to transaction', JSON.stringify(measurements, undefined, 2)); + logger.log( + '[Measurements] Adding measurements to transaction event', + JSON.stringify(measurements, undefined, 2), + ); transaction.measurements = measurements; } diff --git a/packages/core/test/lib/tracing/idleSpan.test.ts b/packages/core/test/lib/tracing/idleSpan.test.ts index 1624160736ea..86d032488229 100644 --- a/packages/core/test/lib/tracing/idleSpan.test.ts +++ b/packages/core/test/lib/tracing/idleSpan.test.ts @@ -122,9 +122,9 @@ describe('startIdleSpan', () => { span.setAttribute('foo', 'bar'); // Try adding a child here - we do this in browser tracing... const inner = startInactiveSpan({ name: 'from beforeSpanEnd', startTime: baseTimeInSeconds }); - inner?.end(baseTimeInSeconds); + inner.end(baseTimeInSeconds + 1); }); - const idleSpan = startIdleSpan({ name: 'idle span 2', startTime: baseTimeInSeconds }, { beforeSpanEnd }); + const idleSpan = startIdleSpan({ name: 'idle span', startTime: baseTimeInSeconds }, { beforeSpanEnd }); expect(idleSpan).toBeDefined(); expect(beforeSpanEnd).not.toHaveBeenCalled(); @@ -141,6 +141,10 @@ describe('startIdleSpan', () => { expect(beforeSendTransaction).toHaveBeenCalledTimes(1); const transaction = transactions[0]; + expect(transaction.start_timestamp).toBe(baseTimeInSeconds); + // It considers the end time of the span we added in beforeSpanEnd + expect(transaction.timestamp).toBe(baseTimeInSeconds + 1); + expect(transaction.contexts?.trace?.data).toEqual( expect.objectContaining({ foo: 'bar', @@ -178,9 +182,9 @@ describe('startIdleSpan', () => { }); // discardedSpan - startTimestamp is too large - const discardedSpan = startInactiveSpan({ name: 'discarded span', startTime: baseTimeInSeconds + 99 }); + const discardedSpan = startInactiveSpan({ name: 'discarded span 1', startTime: baseTimeInSeconds + 99 }); // discardedSpan2 - endTime is too large - const discardedSpan2 = startInactiveSpan({ name: 'discarded span', startTime: baseTimeInSeconds + 3 }); + const discardedSpan2 = startInactiveSpan({ name: 'discarded span 2', startTime: baseTimeInSeconds + 3 }); discardedSpan2.end(baseTimeInSeconds + 99)!; // Should be cancelled - will not finish From da2592278c1d5ee6a793f25126ac1a2367e717f5 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Fri, 31 May 2024 12:00:58 +0200 Subject: [PATCH 06/41] fix(browser): Fix types export path for CJS (#12305) Oops... Fixes https://github.com/getsentry/sentry-javascript/issues/12295 --- packages/browser/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/browser/package.json b/packages/browser/package.json index 3a414f39f68e..9c05730fb0fc 100644 --- a/packages/browser/package.json +++ b/packages/browser/package.json @@ -26,7 +26,7 @@ "default": "./build/npm/esm/index.js" }, "require": { - "types": "./build/npm.types/index.d.ts", + "types": "./build/npm/types/index.d.ts", "default": "./build/npm/cjs/index.js" } } From ba9acbeee8bb4d3abad4f94be63dc223e224512c Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Fri, 31 May 2024 12:02:08 +0200 Subject: [PATCH 07/41] feat(vercel-edge): Export core integrations from Vercel edge SDK (#12308) --- packages/vercel-edge/src/index.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/vercel-edge/src/index.ts b/packages/vercel-edge/src/index.ts index 79c6d77c9d21..6a768627b5d2 100644 --- a/packages/vercel-edge/src/index.ts +++ b/packages/vercel-edge/src/index.ts @@ -67,6 +67,12 @@ export { inboundFiltersIntegration, linkedErrorsIntegration, requestDataIntegration, + extraErrorDataIntegration, + debugIntegration, + dedupeIntegration, + rewriteFramesIntegration, + captureConsoleIntegration, + moduleMetadataIntegration, zodErrorsIntegration, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, From b4505d8f739b4907881452306615c29c25428bbd Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Fri, 31 May 2024 12:22:35 +0200 Subject: [PATCH 08/41] test: Refactor utils into `@sentry-internal/test-utils` (#12277) Re-use this for playwright config in E2E tests. Now, instead of repeating the whole playwright config, we can import the util from `@sentry-internal/test-utils` and pass it some config. I left the places where do not yet use the proxy, because for simplicity I built the util in a way that assumes the proxy (you can override it, but I figured not worth it for stuff that we will refactor soon anyhow). While at it, I also streamlined the playwright version used everywhere to an up-to-date version. --- .github/workflows/canary.yml | 2 +- .../browser-integration-tests/package.json | 2 +- .../test-applications/angular-17/package.json | 7 +- .../angular-17/playwright.config.mjs | 8 + .../angular-17/playwright.config.ts | 72 ----- .../test-applications/angular-17/src/main.ts | 2 +- .../angular-17/start-event-proxy.mjs | 2 +- .../angular-17/tests/errors.test.ts | 2 +- .../angular-17/tests/performance.test.ts | 2 +- .../test-applications/angular-18/package.json | 7 +- .../angular-18/playwright.config.mjs | 8 + .../angular-18/playwright.config.ts | 72 ----- .../test-applications/angular-18/src/main.ts | 2 +- .../angular-18/start-event-proxy.mjs | 2 +- .../angular-18/tests/errors.test.ts | 2 +- .../angular-18/tests/performance.test.ts | 2 +- .../create-next-app/package.json | 2 +- .../package.json | 4 +- .../playwright.config.mjs | 7 + .../playwright.config.ts | 66 ----- .../start-event-proxy.mjs | 2 +- .../tests/behaviour-server.test.ts | 2 +- .../create-remix-app-express/package.json | 7 +- .../playwright.config.mjs | 7 + .../playwright.config.ts | 65 ----- .../start-event-proxy.mjs | 2 +- .../tests/behaviour-server.test.ts | 2 +- .../create-remix-app-v2/package.json | 4 +- .../create-remix-app-v2/playwright.config.mjs | 7 + .../create-remix-app-v2/playwright.config.ts | 66 ----- .../create-remix-app-v2/start-event-proxy.mjs | 2 +- .../tests/behaviour-server.test.ts | 2 +- .../create-remix-app/package.json | 4 +- .../create-remix-app/playwright.config.mjs | 7 + .../create-remix-app/playwright.config.ts | 66 ----- .../create-remix-app/start-event-proxy.mjs | 2 +- .../tests/behaviour-server.test.ts | 2 +- .../test-applications/nextjs-14/package.json | 7 +- .../nextjs-14/playwright.config.ts | 74 +----- .../nextjs-14/start-event-proxy.mjs | 2 +- .../tests/generation-functions.test.ts | 2 +- .../nextjs-14/tests/propagation.test.ts | 2 +- .../tests/request-instrumentation.test.ts | 2 +- .../test-applications/nextjs-15/package.json | 7 +- .../nextjs-15/playwright.config.mjs | 13 + .../nextjs-15/playwright.config.ts | 75 ------ .../nextjs-15/start-event-proxy.mjs | 2 +- .../nextjs-15/tests/pageload-tracing.test.ts | 2 +- .../nextjs-15/tests/ppr-error.test.ts | 2 +- .../nextjs-15/tests/suspense-error.test.ts | 2 +- .../nextjs-app-dir/package.json | 7 +- .../nextjs-app-dir/playwright.config.mjs | 13 + .../nextjs-app-dir/playwright.config.ts | 77 ------ .../nextjs-app-dir/start-event-proxy.mjs | 2 +- .../tests/async-context-edge.test.ts | 2 +- ...client-app-routing-instrumentation.test.ts | 2 +- .../connected-servercomponent-trace.test.ts | 2 +- .../tests/devErrorSymbolification.test.ts | 2 +- .../nextjs-app-dir/tests/edge-route.test.ts | 2 +- .../nextjs-app-dir/tests/edge.test.ts | 2 +- .../nextjs-app-dir/tests/exceptions.test.ts | 2 +- .../nextjs-app-dir/tests/middleware.test.ts | 2 +- .../tests/pages-ssr-errors.test.ts | 2 +- .../tests/request-instrumentation.test.ts | 2 +- .../tests/route-handlers.test.ts | 2 +- .../tests/server-components.test.ts | 2 +- .../nextjs-app-dir/tests/transactions.test.ts | 2 +- .../node-connect/package.json | 4 +- .../node-connect/playwright.config.mjs | 62 +---- .../node-connect/start-event-proxy.mjs | 2 +- .../node-connect/tests/errors.test.ts | 2 +- .../node-connect/tests/transactions.test.ts | 2 +- .../node-express-cjs-preload/package.json | 4 +- .../playwright.config.mjs | 65 +---- .../start-event-proxy.mjs | 2 +- .../tests/server.test.ts | 2 +- .../node-express-esm-loader/package.json | 4 +- .../playwright.config.mjs | 7 + .../playwright.config.ts | 65 ----- .../start-event-proxy.mjs | 2 +- .../tests/server.test.ts | 2 +- .../node-express-esm-preload/package.json | 4 +- .../playwright.config.mjs | 65 +---- .../start-event-proxy.mjs | 2 +- .../tests/server.test.ts | 2 +- .../package.json | 4 +- .../playwright.config.mjs | 7 + .../playwright.config.ts | 65 ----- .../start-event-proxy.mjs | 2 +- .../tests/server.test.ts | 2 +- .../node-express-send-to-sentry/package.json | 2 +- .../playwright.config.mjs | 5 - .../node-express/package.json | 4 +- .../node-express/playwright.config.mjs | 7 + .../node-express/playwright.config.ts | 77 ------ .../test-applications/node-express/src/app.ts | 2 +- .../node-express/start-event-proxy.mjs | 2 +- .../node-express/tests/errors.test.ts | 2 +- .../node-express/tests/transactions.test.ts | 2 +- .../node-express/tests/trpc.test.ts | 2 +- .../node-fastify/package.json | 4 +- .../node-fastify/playwright.config.mjs | 62 +---- .../node-fastify/start-event-proxy.mjs | 2 +- .../node-fastify/tests/errors.test.ts | 2 +- .../node-fastify/tests/propagation.test.ts | 2 +- .../node-fastify/tests/transactions.test.ts | 2 +- .../test-applications/node-hapi/package.json | 8 +- .../node-hapi/playwright.config.mjs | 7 + .../node-hapi/playwright.config.ts | 77 ------ .../test-applications/node-hapi/src/app.js | 2 +- .../node-hapi/start-event-proxy.mjs | 2 +- .../node-hapi/tests/errors.test.ts | 2 +- .../node-hapi/tests/transactions.test.ts | 2 +- .../test-applications/node-hapi/tsconfig.json | 10 - .../test-applications/node-koa/index.js | 2 +- .../test-applications/node-koa/package.json | 4 +- .../node-koa/playwright.config.mjs | 7 + .../node-koa/playwright.config.ts | 77 ------ .../node-koa/start-event-proxy.mjs | 2 +- .../node-koa/tests/errors.test.ts | 2 +- .../node-koa/tests/propagation.test.ts | 2 +- .../node-koa/tests/transactions.test.ts | 2 +- .../node-nestjs/package.json | 4 +- .../node-nestjs/playwright.config.mjs | 7 + .../node-nestjs/playwright.config.ts | 77 ------ .../node-nestjs/start-event-proxy.mjs | 2 +- .../node-nestjs/tests/errors.test.ts | 2 +- .../node-nestjs/tests/propagation.test.ts | 2 +- .../node-nestjs/tests/transactions.test.ts | 2 +- .../test-applications/react-19/package.json | 4 +- .../react-19/playwright.config.mjs | 7 + .../react-19/playwright.config.ts | 82 ------ .../react-19/start-event-proxy.mjs | 2 +- .../react-19/tests/errors.test.ts | 2 +- .../react-create-hash-router/package.json | 7 +- .../playwright.config.mjs | 82 +----- .../react-create-hash-router/src/index.tsx | 2 +- .../start-event-proxy.mjs | 2 +- .../tests/errors.test.ts | 2 +- .../tests/transactions.test.ts | 16 +- .../react-router-5/package.json | 4 +- .../react-router-5/playwright.config.mjs | 7 + .../react-router-5/playwright.config.ts | 82 ------ .../react-router-5/start-event-proxy.mjs | 2 +- .../react-router-5/tests/errors.test.ts | 2 +- .../react-router-5/tests/transactions.test.ts | 2 +- .../react-router-6-use-routes/package.json | 4 +- .../playwright.config.mjs | 7 + .../playwright.config.ts | 82 ------ .../start-event-proxy.mjs | 2 +- .../tests/errors.test.ts | 2 +- .../tests/transactions.test.ts | 2 +- .../react-send-to-sentry/package.json | 3 +- .../tests/fixtures/ReplayRecordingData.ts | 1 + .../tests/send-to-sentry.test.ts | 2 +- .../standard-frontend-react/package.json | 2 +- .../standard-frontend-react/src/index.tsx | 6 - .../tests/behaviour-test.spec.ts | 62 +---- .../tests/fixtures/ReplayRecordingData.ts | 246 ------------------ .../test-applications/svelte-5/package.json | 7 +- .../svelte-5/playwright.config.mjs | 8 + .../svelte-5/playwright.config.ts | 72 ----- .../test-applications/svelte-5/src/main.ts | 2 +- .../svelte-5/start-event-proxy.mjs | 2 +- .../svelte-5/{test => tests}/errors.test.ts | 2 +- .../{test => tests}/performance.test.ts | 2 +- .../sveltekit-2-svelte-5/package.json | 7 +- .../playwright.config.mjs | 8 + .../sveltekit-2-svelte-5/playwright.config.ts | 74 ------ .../sveltekit-2-svelte-5/src/hooks.client.ts | 2 +- .../sveltekit-2-svelte-5/src/hooks.server.ts | 2 +- .../start-event-proxy.mjs | 2 +- .../{test => tests}/errors.client.test.ts | 2 +- .../{test => tests}/errors.server.test.ts | 2 +- .../performance.client.test.ts | 2 +- .../performance.server.test.ts | 2 +- .../{test => tests}/performance.test.ts | 2 +- .../{test => tests}/utils.ts | 2 +- .../sveltekit-2/package.json | 7 +- .../sveltekit-2/playwright.config.mjs | 13 + .../sveltekit-2/playwright.config.ts | 75 ------ .../sveltekit-2/src/hooks.client.ts | 2 +- .../sveltekit-2/src/hooks.server.ts | 2 +- .../sveltekit-2/start-event-proxy.mjs | 2 +- .../{test => tests}/errors.client.test.ts | 2 +- .../{test => tests}/errors.server.test.ts | 2 +- .../performance.client.test.ts | 2 +- .../performance.server.test.ts | 2 +- .../{test => tests}/performance.test.ts | 2 +- .../sveltekit-2/{test => tests}/utils.ts | 2 +- .../test-applications/sveltekit/package.json | 7 +- .../sveltekit/playwright.config.mjs | 14 + .../sveltekit/playwright.config.ts | 73 ------ .../sveltekit/src/hooks.client.ts | 2 +- .../sveltekit/src/hooks.server.ts | 2 +- .../sveltekit/start-event-proxy.mjs | 2 +- .../{test => tests}/errors.client.test.ts | 2 +- .../{test => tests}/errors.server.test.ts | 2 +- .../performance.client.test.ts | 2 +- .../performance.server.test.ts | 2 +- .../{test => tests}/performance.test.ts | 2 +- .../test-applications/sveltekit/utils.ts | 2 +- .../tanstack-router/package.json | 4 +- .../tanstack-router/playwright.config.mjs | 7 + .../tanstack-router/playwright.config.ts | 66 ----- .../tanstack-router/start-event-proxy.mjs | 2 +- .../tests/routing-instrumentation.test.ts | 2 +- .../test-applications/vue-3/package.json | 7 +- .../vue-3/playwright.config.mjs | 8 + .../vue-3/playwright.config.ts | 69 ----- .../test-applications/vue-3/src/main.ts | 1 - .../vue-3/start-event-proxy.mjs | 2 +- .../vue-3/tests/errors.test.ts | 2 +- .../vue-3/tests/performance.test.ts | 2 +- .../vue-3/tsconfig.node.json | 2 +- .../test-applications/webpack-4/package.json | 2 +- .../test-applications/webpack-5/package.json | 2 +- dev-packages/event-proxy-server/tsconfig.json | 5 - .../.eslintrc.js | 0 .../package.json | 6 +- .../rollup.npm.config.mjs | 0 .../src/event-proxy-server.ts | 0 .../src/index.ts | 2 + .../test-utils/src/playwright-config.ts | 95 +++++++ dev-packages/test-utils/tsconfig.json | 8 + .../tsconfig.types.json | 0 package.json | 2 +- yarn.lock | 28 +- 228 files changed, 543 insertions(+), 2636 deletions(-) create mode 100644 dev-packages/e2e-tests/test-applications/angular-17/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/angular-17/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/angular-18/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/angular-18/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-express/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app-v2/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/create-remix-app/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/nextjs-15/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/nextjs-15/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/nextjs-app-dir/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/nextjs-app-dir/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/node-express-esm-loader/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/node-express-esm-loader/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/node-express/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/node-express/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/node-hapi/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/node-hapi/playwright.config.ts delete mode 100644 dev-packages/e2e-tests/test-applications/node-hapi/tsconfig.json create mode 100644 dev-packages/e2e-tests/test-applications/node-koa/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/node-koa/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/node-nestjs/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/node-nestjs/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/react-19/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/react-19/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/react-router-5/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/react-router-5/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/react-router-6-use-routes/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/react-router-6-use-routes/playwright.config.ts delete mode 100644 dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/fixtures/ReplayRecordingData.ts create mode 100644 dev-packages/e2e-tests/test-applications/svelte-5/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/svelte-5/playwright.config.ts rename dev-packages/e2e-tests/test-applications/svelte-5/{test => tests}/errors.test.ts (90%) rename dev-packages/e2e-tests/test-applications/svelte-5/{test => tests}/performance.test.ts (94%) create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/playwright.config.ts rename dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/{test => tests}/errors.client.test.ts (96%) rename dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/{test => tests}/errors.server.test.ts (97%) rename dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/{test => tests}/performance.client.test.ts (98%) rename dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/{test => tests}/performance.server.test.ts (94%) rename dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/{test => tests}/performance.test.ts (99%) rename dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/{test => tests}/utils.ts (95%) create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-2/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-2/playwright.config.ts rename dev-packages/e2e-tests/test-applications/sveltekit-2/{test => tests}/errors.client.test.ts (96%) rename dev-packages/e2e-tests/test-applications/sveltekit-2/{test => tests}/errors.server.test.ts (96%) rename dev-packages/e2e-tests/test-applications/sveltekit-2/{test => tests}/performance.client.test.ts (98%) rename dev-packages/e2e-tests/test-applications/sveltekit-2/{test => tests}/performance.server.test.ts (93%) rename dev-packages/e2e-tests/test-applications/sveltekit-2/{test => tests}/performance.test.ts (99%) rename dev-packages/e2e-tests/test-applications/sveltekit-2/{test => tests}/utils.ts (95%) create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit/playwright.config.ts rename dev-packages/e2e-tests/test-applications/sveltekit/{test => tests}/errors.client.test.ts (96%) rename dev-packages/e2e-tests/test-applications/sveltekit/{test => tests}/errors.server.test.ts (97%) rename dev-packages/e2e-tests/test-applications/sveltekit/{test => tests}/performance.client.test.ts (97%) rename dev-packages/e2e-tests/test-applications/sveltekit/{test => tests}/performance.server.test.ts (94%) rename dev-packages/e2e-tests/test-applications/sveltekit/{test => tests}/performance.test.ts (97%) create mode 100644 dev-packages/e2e-tests/test-applications/tanstack-router/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/tanstack-router/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/vue-3/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/vue-3/playwright.config.ts delete mode 100644 dev-packages/event-proxy-server/tsconfig.json rename dev-packages/{event-proxy-server => test-utils}/.eslintrc.js (100%) rename dev-packages/{event-proxy-server => test-utils}/package.json (89%) rename dev-packages/{event-proxy-server => test-utils}/rollup.npm.config.mjs (100%) rename dev-packages/{event-proxy-server => test-utils}/src/event-proxy-server.ts (100%) rename dev-packages/{event-proxy-server => test-utils}/src/index.ts (70%) create mode 100644 dev-packages/test-utils/src/playwright-config.ts create mode 100644 dev-packages/test-utils/tsconfig.json rename dev-packages/{event-proxy-server => test-utils}/tsconfig.types.json (100%) diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index 2cc7361374cd..152cb275ad13 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -14,7 +14,7 @@ env: CACHED_BUILD_PATHS: | ${{ github.workspace }}/packages/*/*.tgz - ${{ github.workspace }}/dev-packages/event-proxy-server/build + ${{ github.workspace }}/dev-packages/test-utils/build ${{ github.workspace }}/node_modules ${{ github.workspace }}/packages/*/node_modules ${{ github.workspace }}/dev-packages/*/node_modules diff --git a/dev-packages/browser-integration-tests/package.json b/dev-packages/browser-integration-tests/package.json index d64c2b2d1da8..ad80def32d0f 100644 --- a/dev-packages/browser-integration-tests/package.json +++ b/dev-packages/browser-integration-tests/package.json @@ -40,7 +40,7 @@ }, "dependencies": { "@babel/preset-typescript": "^7.16.7", - "@playwright/test": "^1.43.1", + "@playwright/test": "^1.44.1", "@sentry-internal/rrweb": "2.11.0", "@sentry/browser": "8.7.0", "axios": "1.6.7", diff --git a/dev-packages/e2e-tests/test-applications/angular-17/package.json b/dev-packages/e2e-tests/test-applications/angular-17/package.json index 83450dc26987..b7e9b40c2a01 100644 --- a/dev-packages/e2e-tests/test-applications/angular-17/package.json +++ b/dev-packages/e2e-tests/test-applications/angular-17/package.json @@ -29,11 +29,11 @@ "zone.js": "~0.14.3" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@angular-devkit/build-angular": "^17.1.1", "@angular/cli": "^17.1.1", "@angular/compiler-cli": "^17.1.0", - "@playwright/test": "^1.41.1", "@types/jasmine": "~5.1.0", "http-server": "^14.1.1", "jasmine-core": "~5.1.0", @@ -42,8 +42,7 @@ "karma-coverage": "~2.2.0", "karma-jasmine": "~5.1.0", "karma-jasmine-html-reporter": "~2.1.0", - "typescript": "~5.3.2", - "wait-port": "1.0.4" + "typescript": "~5.3.2" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/test-applications/angular-17/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/angular-17/playwright.config.mjs new file mode 100644 index 000000000000..0845325879c9 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/angular-17/playwright.config.mjs @@ -0,0 +1,8 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm preview`, + port: 8080, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/angular-17/playwright.config.ts b/dev-packages/e2e-tests/test-applications/angular-17/playwright.config.ts deleted file mode 100644 index b2ee35fdc4c7..000000000000 --- a/dev-packages/e2e-tests/test-applications/angular-17/playwright.config.ts +++ /dev/null @@ -1,72 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const testEnv = process.env['TEST_ENV'] || 'production'; - -if (!testEnv) { - throw new Error('No test env defined'); -} - -const angularPort = 8080; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 10000, - }, - fullyParallel: false, - workers: 1, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* `next dev` is incredibly buggy with the app dir */ - retries: testEnv === 'development' ? 3 : 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${angularPort}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: - testEnv === 'development' - ? `pnpm wait-port ${eventProxyPort} && pnpm preview -p ${angularPort}` - : `pnpm wait-port ${eventProxyPort} && pnpm preview -p ${angularPort}`, - port: angularPort, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/angular-17/src/main.ts b/dev-packages/e2e-tests/test-applications/angular-17/src/main.ts index 947f40691b05..a0b841afc333 100644 --- a/dev-packages/e2e-tests/test-applications/angular-17/src/main.ts +++ b/dev-packages/e2e-tests/test-applications/angular-17/src/main.ts @@ -5,11 +5,11 @@ import { appConfig } from './app/app.config'; import * as Sentry from '@sentry/angular'; Sentry.init({ + // Cannot use process.env here, so we hardcode the DSN dsn: 'https://3b6c388182fb435097f41d181be2b2ba@o4504321058471936.ingest.sentry.io/4504321066008576', tracesSampleRate: 1.0, integrations: [Sentry.browserTracingIntegration({})], tunnel: `http://localhost:3031/`, // proxy server - debug: true, }); bootstrapApplication(AppComponent, appConfig).catch(err => console.error(err)); diff --git a/dev-packages/e2e-tests/test-applications/angular-17/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/angular-17/start-event-proxy.mjs index 7bf4c4417f3c..d757918ea495 100644 --- a/dev-packages/e2e-tests/test-applications/angular-17/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/angular-17/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/angular-17/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/angular-17/tests/errors.test.ts index 28e07284b435..e6bd5ad180a9 100644 --- a/dev-packages/e2e-tests/test-applications/angular-17/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/angular-17/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('sends an error', async ({ page }) => { const errorPromise = waitForError('angular-17', async errorEvent => { diff --git a/dev-packages/e2e-tests/test-applications/angular-17/tests/performance.test.ts b/dev-packages/e2e-tests/test-applications/angular-17/tests/performance.test.ts index 7873af286315..29c88a6108e2 100644 --- a/dev-packages/e2e-tests/test-applications/angular-17/tests/performance.test.ts +++ b/dev-packages/e2e-tests/test-applications/angular-17/tests/performance.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core'; test('sends a pageload transaction with a parameterized URL', async ({ page }) => { diff --git a/dev-packages/e2e-tests/test-applications/angular-18/package.json b/dev-packages/e2e-tests/test-applications/angular-18/package.json index 1c2bf8b723cb..9b632d69f834 100644 --- a/dev-packages/e2e-tests/test-applications/angular-18/package.json +++ b/dev-packages/e2e-tests/test-applications/angular-18/package.json @@ -29,11 +29,11 @@ "zone.js": "~0.14.3" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@angular-devkit/build-angular": "^18.0.0", "@angular/cli": "^18.0.0", "@angular/compiler-cli": "^18.0.0", - "@playwright/test": "^1.41.1", "@types/jasmine": "~5.1.0", "http-server": "^14.1.1", "jasmine-core": "~5.1.0", @@ -42,8 +42,7 @@ "karma-coverage": "~2.2.0", "karma-jasmine": "~5.1.0", "karma-jasmine-html-reporter": "~2.1.0", - "typescript": "~5.4.5", - "wait-port": "1.0.4" + "typescript": "~5.4.5" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/test-applications/angular-18/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/angular-18/playwright.config.mjs new file mode 100644 index 000000000000..0845325879c9 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/angular-18/playwright.config.mjs @@ -0,0 +1,8 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm preview`, + port: 8080, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/angular-18/playwright.config.ts b/dev-packages/e2e-tests/test-applications/angular-18/playwright.config.ts deleted file mode 100644 index b2ee35fdc4c7..000000000000 --- a/dev-packages/e2e-tests/test-applications/angular-18/playwright.config.ts +++ /dev/null @@ -1,72 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const testEnv = process.env['TEST_ENV'] || 'production'; - -if (!testEnv) { - throw new Error('No test env defined'); -} - -const angularPort = 8080; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 10000, - }, - fullyParallel: false, - workers: 1, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* `next dev` is incredibly buggy with the app dir */ - retries: testEnv === 'development' ? 3 : 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${angularPort}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: - testEnv === 'development' - ? `pnpm wait-port ${eventProxyPort} && pnpm preview -p ${angularPort}` - : `pnpm wait-port ${eventProxyPort} && pnpm preview -p ${angularPort}`, - port: angularPort, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/angular-18/src/main.ts b/dev-packages/e2e-tests/test-applications/angular-18/src/main.ts index 947f40691b05..a0b841afc333 100644 --- a/dev-packages/e2e-tests/test-applications/angular-18/src/main.ts +++ b/dev-packages/e2e-tests/test-applications/angular-18/src/main.ts @@ -5,11 +5,11 @@ import { appConfig } from './app/app.config'; import * as Sentry from '@sentry/angular'; Sentry.init({ + // Cannot use process.env here, so we hardcode the DSN dsn: 'https://3b6c388182fb435097f41d181be2b2ba@o4504321058471936.ingest.sentry.io/4504321066008576', tracesSampleRate: 1.0, integrations: [Sentry.browserTracingIntegration({})], tunnel: `http://localhost:3031/`, // proxy server - debug: true, }); bootstrapApplication(AppComponent, appConfig).catch(err => console.error(err)); diff --git a/dev-packages/e2e-tests/test-applications/angular-18/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/angular-18/start-event-proxy.mjs index 696f1807d8f1..b1b4620866bd 100644 --- a/dev-packages/e2e-tests/test-applications/angular-18/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/angular-18/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/angular-18/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/angular-18/tests/errors.test.ts index a255d2130dda..36d23bd077a5 100644 --- a/dev-packages/e2e-tests/test-applications/angular-18/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/angular-18/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('sends an error', async ({ page }) => { const errorPromise = waitForError('angular-18', async errorEvent => { diff --git a/dev-packages/e2e-tests/test-applications/angular-18/tests/performance.test.ts b/dev-packages/e2e-tests/test-applications/angular-18/tests/performance.test.ts index 12f0fbd41133..af85b8ffc405 100644 --- a/dev-packages/e2e-tests/test-applications/angular-18/tests/performance.test.ts +++ b/dev-packages/e2e-tests/test-applications/angular-18/tests/performance.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core'; test('sends a pageload transaction with a parameterized URL', async ({ page }) => { diff --git a/dev-packages/e2e-tests/test-applications/create-next-app/package.json b/dev-packages/e2e-tests/test-applications/create-next-app/package.json index 74c257558846..330e8b4097ee 100644 --- a/dev-packages/e2e-tests/test-applications/create-next-app/package.json +++ b/dev-packages/e2e-tests/test-applications/create-next-app/package.json @@ -23,7 +23,7 @@ "typescript": "4.9.5" }, "devDependencies": { - "@playwright/test": "^1.27.1" + "@playwright/test": "^1.44.1" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/package.json b/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/package.json index 7fc1d1492746..5ba4b54d8e8f 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/package.json +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/package.json @@ -25,8 +25,8 @@ "react-dom": "^18.2.0" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "^1.36.2", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@remix-run/dev": "^2.7.2", "@sentry/types": "latest || *", "@sentry/utils": "latest || *", diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/playwright.config.mjs new file mode 100644 index 000000000000..e8fa4cd769f5 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm dev`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/playwright.config.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/playwright.config.ts deleted file mode 100644 index 98a4990f1a0a..000000000000 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/playwright.config.ts +++ /dev/null @@ -1,66 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const port = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Opt out of parallel tests on CI. */ - workers: 1, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${port}`, - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: `PORT=${port} pnpm dev`, - port: port, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/start-event-proxy.mjs index b5d188ee00e1..68de708d14e2 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/tests/behaviour-server.test.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/tests/behaviour-server.test.ts index 428dcb6d8668..c2e2873f60c6 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/tests/behaviour-server.test.ts +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-express-vite-dev/tests/behaviour-server.test.ts @@ -1,7 +1,7 @@ import { expect, test } from '@playwright/test'; import { uuid4 } from '@sentry/utils'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('Sends two linked transactions (server & client) to Sentry', async ({ page }) => { // We use this to identify the transactions diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express/package.json b/dev-packages/e2e-tests/test-applications/create-remix-app-express/package.json index abad042bed58..53ccbdff9e7f 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express/package.json +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-express/package.json @@ -28,8 +28,8 @@ "source-map-support": "^0.5.21" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "^1.36.2", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@remix-run/dev": "^2.7.2", "@sentry/types": "latest || *", "@sentry/utils": "latest || *", @@ -49,8 +49,7 @@ "eslint-plugin-react-hooks": "^4.6.0", "tsx": "4.7.2", "typescript": "^5.1.6", - "vite-tsconfig-paths": "^4.2.1", - "wait-port": "1.0.4" + "vite-tsconfig-paths": "^4.2.1" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/create-remix-app-express/playwright.config.mjs new file mode 100644 index 000000000000..31f2b913b58b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-express/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express/playwright.config.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-express/playwright.config.ts deleted file mode 100644 index 2e6c8f7ed757..000000000000 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express/playwright.config.ts +++ /dev/null @@ -1,65 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const remixPort = 3030; -const eventProxyPort = 3031; -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Opt out of parallel tests on CI. */ - workers: 1, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - baseURL: `http://localhost:${remixPort}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - // For now we only test Chrome! - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: `PORT=${remixPort} pnpm start`, - port: remixPort, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/create-remix-app-express/start-event-proxy.mjs index 523be8956871..58e992f8efb6 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-express/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-express/tests/behaviour-server.test.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-express/tests/behaviour-server.test.ts index 83582d68bf39..18825fb95e7b 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-express/tests/behaviour-server.test.ts +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-express/tests/behaviour-server.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; import { uuid4 } from '@sentry/utils'; test('Sends a loader error to Sentry', async ({ page }) => { diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2/package.json b/dev-packages/e2e-tests/test-applications/create-remix-app-v2/package.json index c3c98bd34ab4..a5f932f7cab4 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2/package.json +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-v2/package.json @@ -21,8 +21,8 @@ "react-dom": "^18.2.0" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "^1.36.2", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@remix-run/dev": "2.7.2", "@remix-run/eslint-config": "2.7.2", "@sentry/types": "latest || *", diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/create-remix-app-v2/playwright.config.mjs new file mode 100644 index 000000000000..31f2b913b58b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-v2/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2/playwright.config.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-v2/playwright.config.ts deleted file mode 100644 index d74250f31694..000000000000 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2/playwright.config.ts +++ /dev/null @@ -1,66 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const port = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Opt out of parallel tests on CI. */ - workers: 1, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${port}`, - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: `PORT=${port} pnpm start`, - port: port, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/create-remix-app-v2/start-event-proxy.mjs index 1a25f48c1e07..f48c36f3a495 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-v2/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app-v2/tests/behaviour-server.test.ts b/dev-packages/e2e-tests/test-applications/create-remix-app-v2/tests/behaviour-server.test.ts index 42a5344c5e79..9387cec33752 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app-v2/tests/behaviour-server.test.ts +++ b/dev-packages/e2e-tests/test-applications/create-remix-app-v2/tests/behaviour-server.test.ts @@ -1,7 +1,7 @@ import { expect, test } from '@playwright/test'; import { uuid4 } from '@sentry/utils'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('Sends two linked transactions (server & client) to Sentry', async ({ page }) => { // We use this to identify the transactions diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app/package.json b/dev-packages/e2e-tests/test-applications/create-remix-app/package.json index f794844afe9e..d70c8f824dbc 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app/package.json +++ b/dev-packages/e2e-tests/test-applications/create-remix-app/package.json @@ -21,8 +21,8 @@ "react-dom": "^18.2.0" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "^1.36.2", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@remix-run/dev": "^1.19.3", "@remix-run/eslint-config": "^1.19.3", "@types/react": "^18.0.35", diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/create-remix-app/playwright.config.mjs new file mode 100644 index 000000000000..31f2b913b58b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/create-remix-app/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app/playwright.config.ts b/dev-packages/e2e-tests/test-applications/create-remix-app/playwright.config.ts deleted file mode 100644 index d74250f31694..000000000000 --- a/dev-packages/e2e-tests/test-applications/create-remix-app/playwright.config.ts +++ /dev/null @@ -1,66 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const port = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Opt out of parallel tests on CI. */ - workers: 1, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${port}`, - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: `PORT=${port} pnpm start`, - port: port, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/create-remix-app/start-event-proxy.mjs index b8502df2e077..de34c7e196b6 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/create-remix-app/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/create-remix-app/tests/behaviour-server.test.ts b/dev-packages/e2e-tests/test-applications/create-remix-app/tests/behaviour-server.test.ts index 3001f3c559ff..5107990507e4 100644 --- a/dev-packages/e2e-tests/test-applications/create-remix-app/tests/behaviour-server.test.ts +++ b/dev-packages/e2e-tests/test-applications/create-remix-app/tests/behaviour-server.test.ts @@ -1,7 +1,7 @@ import { expect, test } from '@playwright/test'; import { uuid4 } from '@sentry/utils'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('Sends two linked transactions (server & client) to Sentry', async ({ page }) => { // We use this to identify the transactions diff --git a/dev-packages/e2e-tests/test-applications/nextjs-14/package.json b/dev-packages/e2e-tests/test-applications/nextjs-14/package.json index b5025e7b1232..bbda1b0144cc 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-14/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-14/package.json @@ -13,7 +13,6 @@ "test:assert": "pnpm test:prod && pnpm test:dev" }, "dependencies": { - "@playwright/test": "^1.27.1", "@sentry/nextjs": "latest || *", "@types/node": "18.11.17", "@types/react": "18.0.26", @@ -21,11 +20,11 @@ "next": "14.1.3", "react": "18.2.0", "react-dom": "18.2.0", - "typescript": "4.9.5", - "wait-port": "1.0.4" + "typescript": "4.9.5" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@sentry-internal/feedback": "latest || *", "@sentry-internal/replay-canvas": "latest || *", "@sentry-internal/browser-utils": "latest || *", diff --git a/dev-packages/e2e-tests/test-applications/nextjs-14/playwright.config.ts b/dev-packages/e2e-tests/test-applications/nextjs-14/playwright.config.ts index bf1fc94f4292..c675d003853a 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-14/playwright.config.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-14/playwright.config.ts @@ -1,77 +1,13 @@ -import os from 'os'; -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; const testEnv = process.env.TEST_ENV; if (!testEnv) { throw new Error('No test env defined'); } -const nextPort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 30_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 10000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Defaults to half the number of CPUs. The tests are not really CPU-bound but rather I/O-bound with all the polling we do so we increase the concurrency to the CPU count. */ - workers: os.cpus().length, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* `next dev` is incredibly buggy with the app dir */ - retries: testEnv === 'development' ? 3 : 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${nextPort}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: - testEnv === 'development' - ? `pnpm wait-port ${eventProxyPort} && pnpm next dev -p ${nextPort}` - : `pnpm wait-port ${eventProxyPort} && pnpm next start -p ${nextPort}`, - port: nextPort, - stdout: 'pipe', - stderr: 'pipe', - }, - ], -}; +const config = getPlaywrightConfig({ + startCommand: testEnv === 'development' ? 'pnpm next dev -p 3030' : 'pnpm next start -p 3030', + port: 3030, +}); export default config; diff --git a/dev-packages/e2e-tests/test-applications/nextjs-14/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/nextjs-14/start-event-proxy.mjs index 476672c34359..39babfb19b2a 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-14/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/nextjs-14/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/nextjs-14/tests/generation-functions.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-14/tests/generation-functions.test.ts index 93eba1fb7537..7739e9ac17de 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-14/tests/generation-functions.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-14/tests/generation-functions.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('Should send a transaction event for a generateMetadata() function invokation', async ({ page }) => { const testTitle = 'foobarasdf'; diff --git a/dev-packages/e2e-tests/test-applications/nextjs-14/tests/propagation.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-14/tests/propagation.test.ts index 2653d57ca179..26395d6e0145 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-14/tests/propagation.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-14/tests/propagation.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('Propagates trace for outgoing http requests', async ({ baseURL, request }) => { const inboundTransactionPromise = waitForTransaction('nextjs-14', transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/nextjs-14/tests/request-instrumentation.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-14/tests/request-instrumentation.test.ts index 6beb6f531d11..be6bfab11b84 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-14/tests/request-instrumentation.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-14/tests/request-instrumentation.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('Should send a transaction with a fetch span', async ({ page }) => { const transactionPromise = waitForTransaction('nextjs-14', async transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15/package.json b/dev-packages/e2e-tests/test-applications/nextjs-15/package.json index dc1d111ee393..3c39c0331b50 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-15/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-15/package.json @@ -13,7 +13,6 @@ "test:assert": "pnpm test:prod && pnpm test:dev" }, "dependencies": { - "@playwright/test": "^1.27.1", "@sentry/nextjs": "latest || *", "@types/node": "18.11.17", "@types/react": "18.0.26", @@ -21,11 +20,11 @@ "next": "14.3.0-canary.73", "react": "beta", "react-dom": "beta", - "typescript": "4.9.5", - "wait-port": "1.0.4" + "typescript": "4.9.5" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@sentry-internal/feedback": "latest || *", "@sentry-internal/replay-canvas": "latest || *", "@sentry-internal/browser-utils": "latest || *", diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/nextjs-15/playwright.config.mjs new file mode 100644 index 000000000000..c675d003853a --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/nextjs-15/playwright.config.mjs @@ -0,0 +1,13 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; +const testEnv = process.env.TEST_ENV; + +if (!testEnv) { + throw new Error('No test env defined'); +} + +const config = getPlaywrightConfig({ + startCommand: testEnv === 'development' ? 'pnpm next dev -p 3030' : 'pnpm next start -p 3030', + port: 3030, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15/playwright.config.ts b/dev-packages/e2e-tests/test-applications/nextjs-15/playwright.config.ts deleted file mode 100644 index ab02599b8f4f..000000000000 --- a/dev-packages/e2e-tests/test-applications/nextjs-15/playwright.config.ts +++ /dev/null @@ -1,75 +0,0 @@ -import os from 'os'; -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const testEnv = process.env.TEST_ENV; - -if (!testEnv) { - throw new Error('No test env defined'); -} - -const nextPort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 30_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 10000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Defaults to half the number of CPUs. The tests are not really CPU-bound but rather I/O-bound with all the polling we do so we increase the concurrency to the CPU count. */ - workers: os.cpus().length, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* `next dev` is incredibly buggy with the app dir */ - retries: testEnv === 'development' ? 3 : 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${nextPort}`, - trace: 'retain-on-failure', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: - testEnv === 'development' - ? `pnpm wait-port ${eventProxyPort} && pnpm next dev -p ${nextPort}` - : `pnpm wait-port ${eventProxyPort} && pnpm next start -p ${nextPort}`, - port: nextPort, - stdout: 'pipe', - stderr: 'pipe', - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/nextjs-15/start-event-proxy.mjs index 56744b35c7e6..90d736790faa 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-15/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/nextjs-15/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15/tests/pageload-tracing.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-15/tests/pageload-tracing.test.ts index 7893633d3b48..38325fa6a0e0 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-15/tests/pageload-tracing.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-15/tests/pageload-tracing.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('all server component transactions should be attached to the pageload request span', async ({ page }) => { const pageServerComponentTransactionPromise = waitForTransaction('nextjs-15', async transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15/tests/ppr-error.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-15/tests/ppr-error.test.ts index 1e266fa02541..6fc1a6716127 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-15/tests/ppr-error.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-15/tests/ppr-error.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('should not capture React-internal errors for PPR rendering', async ({ page }) => { const pageServerComponentTransactionPromise = waitForTransaction('nextjs-15', async transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15/tests/suspense-error.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-15/tests/suspense-error.test.ts index ddbc4a9edee3..6c9a58dab4f3 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-15/tests/suspense-error.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-15/tests/suspense-error.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('should not capture serverside suspense errors', async ({ page }) => { const pageServerComponentTransactionPromise = waitForTransaction('nextjs-15', async transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/package.json b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/package.json index 925ee97e79f7..4e47e84efc8b 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/package.json +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/package.json @@ -23,12 +23,11 @@ "next": "14.0.2", "react": "18.2.0", "react-dom": "18.2.0", - "typescript": "4.9.5", - "wait-port": "1.0.4", - "@playwright/test": "^1.27.1" + "typescript": "4.9.5" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@sentry-internal/feedback": "latest || *", "@sentry-internal/replay-canvas": "latest || *", "@sentry-internal/browser-utils": "latest || *", diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/playwright.config.mjs new file mode 100644 index 000000000000..c675d003853a --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/playwright.config.mjs @@ -0,0 +1,13 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; +const testEnv = process.env.TEST_ENV; + +if (!testEnv) { + throw new Error('No test env defined'); +} + +const config = getPlaywrightConfig({ + startCommand: testEnv === 'development' ? 'pnpm next dev -p 3030' : 'pnpm next start -p 3030', + port: 3030, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/playwright.config.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/playwright.config.ts deleted file mode 100644 index a6fbfdc882cf..000000000000 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/playwright.config.ts +++ /dev/null @@ -1,77 +0,0 @@ -import os from 'os'; -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const testEnv = process.env.TEST_ENV; - -if (!testEnv) { - throw new Error('No test env defined'); -} - -const nextPort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 10000, - }, - /* Defaults to half the number of CPUs. The tests are not really CPU-bound but rather I/O-bound with all the polling we do so we increase the concurrency to the CPU count. */ - workers: os.cpus().length, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* `next dev` is incredibly buggy with the app dir */ - retries: testEnv === 'development' ? 3 : 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${nextPort}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: - testEnv === 'development' - ? `pnpm wait-port ${eventProxyPort} && pnpm next dev -p ${nextPort}` - : `pnpm wait-port ${eventProxyPort} && pnpm next start -p ${nextPort}`, - port: nextPort, - stdout: 'pipe', - stderr: 'pipe', - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/start-event-proxy.mjs index d908b1d1c737..4d029c3b87be 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/async-context-edge.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/async-context-edge.test.ts index 4696534e1733..e5fea269e322 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/async-context-edge.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/async-context-edge.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('Should allow for async context isolation in the edge SDK', async ({ request }) => { // test.skip(process.env.TEST_ENV === 'development', "Doesn't work in dev mode."); diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/client-app-routing-instrumentation.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/client-app-routing-instrumentation.test.ts index 6fd69315b264..5e8e89eec3d8 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/client-app-routing-instrumentation.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/client-app-routing-instrumentation.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('Creates a pageload transaction for app router routes', async ({ page }) => { const randomRoute = String(Math.random()); diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/connected-servercomponent-trace.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/connected-servercomponent-trace.test.ts index c63348304cda..09a18791db1f 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/connected-servercomponent-trace.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/connected-servercomponent-trace.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('Will capture a connected trace for all server components and generation functions when visiting a page', async ({ page, diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/devErrorSymbolification.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/devErrorSymbolification.test.ts index cb2612c09403..e4b122521c2d 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/devErrorSymbolification.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/devErrorSymbolification.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; test.describe('dev mode error symbolification', () => { if (process.env.TEST_ENV !== 'development') { diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/edge-route.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/edge-route.test.ts index 4b9c807f082c..df0dda64c4ba 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/edge-route.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/edge-route.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('Should create a transaction for edge routes', async ({ request }) => { const edgerouteTransactionPromise = waitForTransaction('nextjs-13-app-dir', async transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/edge.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/edge.test.ts index e8070ea64b20..f6c0e7f5bad4 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/edge.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/edge.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('Should record exceptions for faulty edge server components', async ({ page }) => { const errorEventPromise = waitForError('nextjs-13-app-dir', errorEvent => { diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/exceptions.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/exceptions.test.ts index 17262be631c2..4f0f4a6abfce 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/exceptions.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/exceptions.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/middleware.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/middleware.test.ts index b457b4bcbdee..2a7b2deab27c 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/middleware.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/middleware.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('Should create a transaction for middleware', async ({ request }) => { const middlewareTransactionPromise = waitForTransaction('nextjs-13-app-dir', async transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/pages-ssr-errors.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/pages-ssr-errors.test.ts index 3e6396c4a618..9cd49e58990f 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/pages-ssr-errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/pages-ssr-errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('Will capture error for SSR rendering error with a connected trace (Class Component)', async ({ page }) => { const errorEventPromise = waitForError('nextjs-13-app-dir', errorEvent => { diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/request-instrumentation.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/request-instrumentation.test.ts index bd6a27cecced..8d07d0192f44 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/request-instrumentation.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/request-instrumentation.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; // Note(lforst): I officially declare bancruptcy on this test. I tried a million ways to make it work but it kept flaking. // Sometimes the request span was included in the handler span, more often it wasn't. I have no idea why. Maybe one day we will diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/route-handlers.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/route-handlers.test.ts index d47d0adaea74..d10f402c0c17 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/route-handlers.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/route-handlers.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('Should create a transaction for route handlers', async ({ request }) => { const routehandlerTransactionPromise = waitForTransaction('nextjs-13-app-dir', async transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/server-components.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/server-components.test.ts index d33a5b535508..9c28f78510da 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/server-components.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/server-components.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/transactions.test.ts index 4e5415db657d..4d0f71ac9d97 100644 --- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/transactions.test.ts +++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/transactions.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; const packageJson = require('../package.json'); diff --git a/dev-packages/e2e-tests/test-applications/node-connect/package.json b/dev-packages/e2e-tests/test-applications/node-connect/package.json index 24ecbcea1b02..e13c082ef646 100644 --- a/dev-packages/e2e-tests/test-applications/node-connect/package.json +++ b/dev-packages/e2e-tests/test-applications/node-connect/package.json @@ -22,8 +22,8 @@ "ts-node": "10.9.1" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "^1.38.1" + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/test-applications/node-connect/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/node-connect/playwright.config.mjs index ba0e0c6eb001..31f2b913b58b 100644 --- a/dev-packages/e2e-tests/test-applications/node-connect/playwright.config.mjs +++ b/dev-packages/e2e-tests/test-applications/node-connect/playwright.config.mjs @@ -1,61 +1,7 @@ -import { devices } from '@playwright/test'; +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; -const connectPort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 10000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - retries: 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${connectPort}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: 'pnpm start', - port: connectPort, - }, - ], -}; +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); export default config; diff --git a/dev-packages/e2e-tests/test-applications/node-connect/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/node-connect/start-event-proxy.mjs index cac2f8db1f82..9ae7c07950d4 100644 --- a/dev-packages/e2e-tests/test-applications/node-connect/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/node-connect/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/node-connect/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/node-connect/tests/errors.test.ts index 0ae0b8c017e2..e0b39ed16bc5 100644 --- a/dev-packages/e2e-tests/test-applications/node-connect/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-connect/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; test('Sends correct error event', async ({ baseURL }) => { const errorEventPromise = waitForError('node-connect', event => { diff --git a/dev-packages/e2e-tests/test-applications/node-connect/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/node-connect/tests/transactions.test.ts index 8a95f4b12c6f..aa868ceab291 100644 --- a/dev-packages/e2e-tests/test-applications/node-connect/tests/transactions.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-connect/tests/transactions.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; diff --git a/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/package.json b/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/package.json index 660d5147bb27..5a3074df94eb 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/package.json +++ b/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/package.json @@ -14,8 +14,8 @@ "express": "4.19.2" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "^1.27.1" + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/playwright.config.mjs index 847f270e5f32..31f2b913b58b 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/playwright.config.mjs +++ b/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/playwright.config.mjs @@ -1,64 +1,7 @@ -import { devices } from '@playwright/test'; +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; -const eventProxyPort = 3031; -const expressPort = 3030; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${expressPort}`, - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - stdout: 'pipe', - stderr: 'pipe', - }, - { - command: 'pnpm start', - port: expressPort, - stdout: 'pipe', - stderr: 'pipe', - }, - ], -}; +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); export default config; diff --git a/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/start-event-proxy.mjs index e2b0f5436f3d..ae2ce096fdba 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/tests/server.test.ts b/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/tests/server.test.ts index 3ca97ad0b207..5b8fd26f1647 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/tests/server.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-express-cjs-preload/tests/server.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('Should record exceptions captured inside handlers', async ({ request }) => { const errorEventPromise = waitForError('node-express-cjs-preload', errorEvent => { diff --git a/dev-packages/e2e-tests/test-applications/node-express-esm-loader/package.json b/dev-packages/e2e-tests/test-applications/node-express-esm-loader/package.json index e05d8711ff33..61fc40619560 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-esm-loader/package.json +++ b/dev-packages/e2e-tests/test-applications/node-express-esm-loader/package.json @@ -14,8 +14,8 @@ "express": "4.19.2" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "^1.27.1" + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/test-applications/node-express-esm-loader/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/node-express-esm-loader/playwright.config.mjs new file mode 100644 index 000000000000..31f2b913b58b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/node-express-esm-loader/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/node-express-esm-loader/playwright.config.ts b/dev-packages/e2e-tests/test-applications/node-express-esm-loader/playwright.config.ts deleted file mode 100644 index c13cac26ba9a..000000000000 --- a/dev-packages/e2e-tests/test-applications/node-express-esm-loader/playwright.config.ts +++ /dev/null @@ -1,65 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const eventProxyPort = 3031; -const expressPort = 3030; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${expressPort}`, - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - stdout: 'pipe', - stderr: 'pipe', - }, - { - command: 'pnpm start', - port: expressPort, - stdout: 'pipe', - stderr: 'pipe', - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/node-express-esm-loader/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/node-express-esm-loader/start-event-proxy.mjs index ae508f6ea13c..fae085c1cc86 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-esm-loader/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/node-express-esm-loader/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/node-express-esm-loader/tests/server.test.ts b/dev-packages/e2e-tests/test-applications/node-express-esm-loader/tests/server.test.ts index 410ff414f908..3b65819e2c29 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-esm-loader/tests/server.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-express-esm-loader/tests/server.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('Should record exceptions captured inside handlers', async ({ request }) => { const errorEventPromise = waitForError('node-express-esm-loader', errorEvent => { diff --git a/dev-packages/e2e-tests/test-applications/node-express-esm-preload/package.json b/dev-packages/e2e-tests/test-applications/node-express-esm-preload/package.json index 3f2310549513..df6fcaf29adc 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-esm-preload/package.json +++ b/dev-packages/e2e-tests/test-applications/node-express-esm-preload/package.json @@ -14,8 +14,8 @@ "express": "4.19.2" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "^1.27.1" + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/test-applications/node-express-esm-preload/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/node-express-esm-preload/playwright.config.mjs index 847f270e5f32..31f2b913b58b 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-esm-preload/playwright.config.mjs +++ b/dev-packages/e2e-tests/test-applications/node-express-esm-preload/playwright.config.mjs @@ -1,64 +1,7 @@ -import { devices } from '@playwright/test'; +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; -const eventProxyPort = 3031; -const expressPort = 3030; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${expressPort}`, - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - stdout: 'pipe', - stderr: 'pipe', - }, - { - command: 'pnpm start', - port: expressPort, - stdout: 'pipe', - stderr: 'pipe', - }, - ], -}; +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); export default config; diff --git a/dev-packages/e2e-tests/test-applications/node-express-esm-preload/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/node-express-esm-preload/start-event-proxy.mjs index 6b5d011dcb03..152218840a7a 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-esm-preload/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/node-express-esm-preload/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/node-express-esm-preload/tests/server.test.ts b/dev-packages/e2e-tests/test-applications/node-express-esm-preload/tests/server.test.ts index 19803d7b3a7f..f1b06f9d0304 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-esm-preload/tests/server.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-express-esm-preload/tests/server.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('Should record exceptions captured inside handlers', async ({ request }) => { const errorEventPromise = waitForError('node-express-esm-preload', errorEvent => { diff --git a/dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/package.json b/dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/package.json index 8b8a34966174..7939cf85a7ca 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/package.json +++ b/dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/package.json @@ -14,8 +14,8 @@ "express": "4.19.2" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "^1.27.1" + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/playwright.config.mjs new file mode 100644 index 000000000000..31f2b913b58b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/playwright.config.ts b/dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/playwright.config.ts deleted file mode 100644 index c13cac26ba9a..000000000000 --- a/dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/playwright.config.ts +++ /dev/null @@ -1,65 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const eventProxyPort = 3031; -const expressPort = 3030; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${expressPort}`, - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - stdout: 'pipe', - stderr: 'pipe', - }, - { - command: 'pnpm start', - port: expressPort, - stdout: 'pipe', - stderr: 'pipe', - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/start-event-proxy.mjs index df0fdb65c929..b36c9d280735 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/tests/server.test.ts b/dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/tests/server.test.ts index eeeb033a42df..377015070b45 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/tests/server.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-express-esm-without-loader/tests/server.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; test('Should record exceptions captured inside handlers', async ({ request }) => { const errorEventPromise = waitForError('node-express-esm-without-loader', errorEvent => { diff --git a/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/package.json b/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/package.json index 1a10d88b0bb8..96f61837c597 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/package.json +++ b/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/package.json @@ -20,7 +20,7 @@ "typescript": "4.9.5" }, "devDependencies": { - "@playwright/test": "^1.27.1" + "@playwright/test": "^1.44.1" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/playwright.config.mjs index 4f4aacb2c47e..9340e7e9436a 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/playwright.config.mjs +++ b/dev-packages/e2e-tests/test-applications/node-express-send-to-sentry/playwright.config.mjs @@ -1,10 +1,5 @@ import { devices } from '@playwright/test'; -// Fix urls not resolving to localhost on Node v17+ -// See: https://github.com/axios/axios/issues/3821#issuecomment-1413727575 -import { setDefaultResultOrder } from 'dns'; -setDefaultResultOrder('ipv4first'); - const expressPort = 3030; /** diff --git a/dev-packages/e2e-tests/test-applications/node-express/package.json b/dev-packages/e2e-tests/test-applications/node-express/package.json index c59865a69266..34643b63553e 100644 --- a/dev-packages/e2e-tests/test-applications/node-express/package.json +++ b/dev-packages/e2e-tests/test-applications/node-express/package.json @@ -23,8 +23,8 @@ "zod": "~3.22.4" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "^1.27.1" + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/test-applications/node-express/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/node-express/playwright.config.mjs new file mode 100644 index 000000000000..31f2b913b58b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/node-express/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/node-express/playwright.config.ts b/dev-packages/e2e-tests/test-applications/node-express/playwright.config.ts deleted file mode 100644 index 5edd64b3c768..000000000000 --- a/dev-packages/e2e-tests/test-applications/node-express/playwright.config.ts +++ /dev/null @@ -1,77 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const eventProxyPort = 3031; -const expressPort = 3030; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${expressPort}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - // For now we only test Chrome! - // { - // name: 'firefox', - // use: { - // ...devices['Desktop Firefox'], - // }, - // }, - // { - // name: 'webkit', - // use: { - // ...devices['Desktop Safari'], - // }, - // }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: 'pnpm start', - port: expressPort, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/node-express/src/app.ts b/dev-packages/e2e-tests/test-applications/node-express/src/app.ts index 45cf88c5f212..de240b761df0 100644 --- a/dev-packages/e2e-tests/test-applications/node-express/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/node-express/src/app.ts @@ -10,7 +10,7 @@ Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions dsn: process.env.E2E_TEST_DSN, includeLocalVariables: true, - debug: true, + debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, }); diff --git a/dev-packages/e2e-tests/test-applications/node-express/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/node-express/start-event-proxy.mjs index a31586dd09fc..3276781a442a 100644 --- a/dev-packages/e2e-tests/test-applications/node-express/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/node-express/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/node-express/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/node-express/tests/errors.test.ts index 4b7c3c71edc6..0a61c8665e30 100644 --- a/dev-packages/e2e-tests/test-applications/node-express/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-express/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; test('Sends correct error event', async ({ baseURL }) => { const errorEventPromise = waitForError('node-express', event => { diff --git a/dev-packages/e2e-tests/test-applications/node-express/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/node-express/tests/transactions.test.ts index ec28035f0d38..8e7fb9fce515 100644 --- a/dev-packages/e2e-tests/test-applications/node-express/tests/transactions.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-express/tests/transactions.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('Sends an API route transaction', async ({ baseURL }) => { const pageloadTransactionEventPromise = waitForTransaction('node-express', transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/node-express/tests/trpc.test.ts b/dev-packages/e2e-tests/test-applications/node-express/tests/trpc.test.ts index 368f14bd43ee..4f274fdc16ae 100644 --- a/dev-packages/e2e-tests/test-applications/node-express/tests/trpc.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-express/tests/trpc.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; import { createTRPCProxyClient, httpBatchLink } from '@trpc/client'; import type { AppRouter } from '../src/app'; diff --git a/dev-packages/e2e-tests/test-applications/node-fastify/package.json b/dev-packages/e2e-tests/test-applications/node-fastify/package.json index 1a35474e1bba..c862a9b7037b 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify/package.json +++ b/dev-packages/e2e-tests/test-applications/node-fastify/package.json @@ -22,8 +22,8 @@ "ts-node": "10.9.1" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "^1.44.0" + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/test-applications/node-fastify/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/node-fastify/playwright.config.mjs index 858e6aec7ef2..31f2b913b58b 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify/playwright.config.mjs +++ b/dev-packages/e2e-tests/test-applications/node-fastify/playwright.config.mjs @@ -1,61 +1,7 @@ -import { devices } from '@playwright/test'; +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; -const fastifyPort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 10000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - retries: 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${fastifyPort}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: 'pnpm start', - port: fastifyPort, - }, - ], -}; +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); export default config; diff --git a/dev-packages/e2e-tests/test-applications/node-fastify/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/node-fastify/start-event-proxy.mjs index e627ce9a8bef..814357a4d413 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/node-fastify/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/node-fastify/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/node-fastify/tests/errors.test.ts index 3bd2584c6b22..eb1a9eb869e0 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-fastify/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; test('Sends correct error event', async ({ baseURL }) => { const errorEventPromise = waitForError('node-fastify', event => { diff --git a/dev-packages/e2e-tests/test-applications/node-fastify/tests/propagation.test.ts b/dev-packages/e2e-tests/test-applications/node-fastify/tests/propagation.test.ts index 6900e4d09cd2..d2e9a188da9f 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify/tests/propagation.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-fastify/tests/propagation.test.ts @@ -1,6 +1,6 @@ import crypto from 'crypto'; import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; import { SpanJSON } from '@sentry/types'; test('Propagates trace for outgoing http requests', async ({ baseURL }) => { diff --git a/dev-packages/e2e-tests/test-applications/node-fastify/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/node-fastify/tests/transactions.test.ts index ee1e6effbc71..aa4704a1d950 100644 --- a/dev-packages/e2e-tests/test-applications/node-fastify/tests/transactions.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-fastify/tests/transactions.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('Sends an API route transaction', async ({ baseURL }) => { const pageloadTransactionEventPromise = waitForTransaction('node-fastify', transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/node-hapi/package.json b/dev-packages/e2e-tests/test-applications/node-hapi/package.json index 017d55438ab1..a6092edbc5ce 100644 --- a/dev-packages/e2e-tests/test-applications/node-hapi/package.json +++ b/dev-packages/e2e-tests/test-applications/node-hapi/package.json @@ -13,13 +13,11 @@ "dependencies": { "@hapi/hapi": "21.3.2", "@sentry/node": "latest || *", - "@sentry/types": "latest || *", - "@types/node": "18.15.1", - "typescript": "4.9.5" + "@sentry/types": "latest || *" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "^1.27.1" + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/test-applications/node-hapi/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/node-hapi/playwright.config.mjs new file mode 100644 index 000000000000..31f2b913b58b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/node-hapi/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/node-hapi/playwright.config.ts b/dev-packages/e2e-tests/test-applications/node-hapi/playwright.config.ts deleted file mode 100644 index 79d19e845ab0..000000000000 --- a/dev-packages/e2e-tests/test-applications/node-hapi/playwright.config.ts +++ /dev/null @@ -1,77 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const hapiPort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${hapiPort}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - // For now we only test Chrome! - // { - // name: 'firefox', - // use: { - // ...devices['Desktop Firefox'], - // }, - // }, - // { - // name: 'webkit', - // use: { - // ...devices['Desktop Safari'], - // }, - // }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: 'pnpm start', - port: hapiPort, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/node-hapi/src/app.js b/dev-packages/e2e-tests/test-applications/node-hapi/src/app.js index 772847392e43..273cb2f09471 100644 --- a/dev-packages/e2e-tests/test-applications/node-hapi/src/app.js +++ b/dev-packages/e2e-tests/test-applications/node-hapi/src/app.js @@ -4,7 +4,7 @@ Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions dsn: process.env.E2E_TEST_DSN, includeLocalVariables: true, - debug: true, + debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, }); diff --git a/dev-packages/e2e-tests/test-applications/node-hapi/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/node-hapi/start-event-proxy.mjs index 25464165b311..0677757f657f 100644 --- a/dev-packages/e2e-tests/test-applications/node-hapi/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/node-hapi/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/node-hapi/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/node-hapi/tests/errors.test.ts index c46265579a99..4fb76c1df687 100644 --- a/dev-packages/e2e-tests/test-applications/node-hapi/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-hapi/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('Sends thrown error to Sentry', async ({ baseURL }) => { const errorEventPromise = waitForError('node-hapi', errorEvent => { diff --git a/dev-packages/e2e-tests/test-applications/node-hapi/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/node-hapi/tests/transactions.test.ts index 936861ce8f18..64e98f8e75d8 100644 --- a/dev-packages/e2e-tests/test-applications/node-hapi/tests/transactions.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-hapi/tests/transactions.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('Sends successful transaction', async ({ baseURL }) => { const pageloadTransactionEventPromise = waitForTransaction('node-hapi', transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/node-hapi/tsconfig.json b/dev-packages/e2e-tests/test-applications/node-hapi/tsconfig.json deleted file mode 100644 index 17bd2c1f4c00..000000000000 --- a/dev-packages/e2e-tests/test-applications/node-hapi/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "types": ["node"], - "esModuleInterop": true, - "lib": ["dom", "dom.iterable", "esnext"], - "strict": true, - "outDir": "dist" - }, - "include": ["*.ts"] -} diff --git a/dev-packages/e2e-tests/test-applications/node-koa/index.js b/dev-packages/e2e-tests/test-applications/node-koa/index.js index 9d58bd6ca3b6..08ddc231ffb3 100644 --- a/dev-packages/e2e-tests/test-applications/node-koa/index.js +++ b/dev-packages/e2e-tests/test-applications/node-koa/index.js @@ -4,7 +4,7 @@ Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions dsn: process.env.E2E_TEST_DSN, includeLocalVariables: true, - debug: true, + debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, tracePropagationTargets: ['http://localhost:3030', 'external-allowed'], diff --git a/dev-packages/e2e-tests/test-applications/node-koa/package.json b/dev-packages/e2e-tests/test-applications/node-koa/package.json index 8050820d28ea..79a4e540c089 100644 --- a/dev-packages/e2e-tests/test-applications/node-koa/package.json +++ b/dev-packages/e2e-tests/test-applications/node-koa/package.json @@ -18,8 +18,8 @@ "typescript": "4.9.5" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "^1.27.1" + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/test-applications/node-koa/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/node-koa/playwright.config.mjs new file mode 100644 index 000000000000..31f2b913b58b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/node-koa/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/node-koa/playwright.config.ts b/dev-packages/e2e-tests/test-applications/node-koa/playwright.config.ts deleted file mode 100644 index 9ebe391bb0bd..000000000000 --- a/dev-packages/e2e-tests/test-applications/node-koa/playwright.config.ts +++ /dev/null @@ -1,77 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const koaPort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${koaPort}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - // For now we only test Chrome! - // { - // name: 'firefox', - // use: { - // ...devices['Desktop Firefox'], - // }, - // }, - // { - // name: 'webkit', - // use: { - // ...devices['Desktop Safari'], - // }, - // }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: 'pnpm start', - port: koaPort, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/node-koa/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/node-koa/start-event-proxy.mjs index 969f745f2d7a..75bd72e8c7d3 100644 --- a/dev-packages/e2e-tests/test-applications/node-koa/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/node-koa/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/node-koa/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/node-koa/tests/errors.test.ts index 1838d66580e6..aca04522f8fc 100644 --- a/dev-packages/e2e-tests/test-applications/node-koa/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-koa/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; test('Sends correct error event', async ({ baseURL }) => { const errorEventPromise = waitForError('node-koa', event => { diff --git a/dev-packages/e2e-tests/test-applications/node-koa/tests/propagation.test.ts b/dev-packages/e2e-tests/test-applications/node-koa/tests/propagation.test.ts index 6e3abf414ba3..1f5413af0cbe 100644 --- a/dev-packages/e2e-tests/test-applications/node-koa/tests/propagation.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-koa/tests/propagation.test.ts @@ -1,6 +1,6 @@ import crypto from 'crypto'; import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; import { SpanJSON } from '@sentry/types'; test('Propagates trace for outgoing http requests', async ({ baseURL }) => { diff --git a/dev-packages/e2e-tests/test-applications/node-koa/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/node-koa/tests/transactions.test.ts index d2db2aa54ae6..fd57b23cb8bb 100644 --- a/dev-packages/e2e-tests/test-applications/node-koa/tests/transactions.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-koa/tests/transactions.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('Sends an API route transaction', async ({ baseURL }) => { const pageloadTransactionEventPromise = waitForTransaction('node-koa', transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/node-nestjs/package.json b/dev-packages/e2e-tests/test-applications/node-nestjs/package.json index 51fb770cbb83..c21b312d1c13 100644 --- a/dev-packages/e2e-tests/test-applications/node-nestjs/package.json +++ b/dev-packages/e2e-tests/test-applications/node-nestjs/package.json @@ -24,11 +24,11 @@ "rxjs": "^7.8.1" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@nestjs/cli": "^10.0.0", "@nestjs/schematics": "^10.0.0", "@nestjs/testing": "^10.0.0", - "@playwright/test": "^1.27.1", "@types/express": "^4.17.17", "@types/node": "18.15.1", "@types/supertest": "^6.0.0", diff --git a/dev-packages/e2e-tests/test-applications/node-nestjs/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/node-nestjs/playwright.config.mjs new file mode 100644 index 000000000000..31f2b913b58b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/node-nestjs/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/node-nestjs/playwright.config.ts b/dev-packages/e2e-tests/test-applications/node-nestjs/playwright.config.ts deleted file mode 100644 index 141dc4baf830..000000000000 --- a/dev-packages/e2e-tests/test-applications/node-nestjs/playwright.config.ts +++ /dev/null @@ -1,77 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const nestjsPort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${nestjsPort}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - // For now we only test Chrome! - // { - // name: 'firefox', - // use: { - // ...devices['Desktop Firefox'], - // }, - // }, - // { - // name: 'webkit', - // use: { - // ...devices['Desktop Safari'], - // }, - // }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: 'pnpm start', - port: nestjsPort, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/node-nestjs/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/node-nestjs/start-event-proxy.mjs index 583769c59a92..3714932358a5 100644 --- a/dev-packages/e2e-tests/test-applications/node-nestjs/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/node-nestjs/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/node-nestjs/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/node-nestjs/tests/errors.test.ts index f57d656068df..40ed8e49718a 100644 --- a/dev-packages/e2e-tests/test-applications/node-nestjs/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-nestjs/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; test('Sends exception to Sentry', async ({ baseURL }) => { const errorEventPromise = waitForError('node-nestjs', event => { diff --git a/dev-packages/e2e-tests/test-applications/node-nestjs/tests/propagation.test.ts b/dev-packages/e2e-tests/test-applications/node-nestjs/tests/propagation.test.ts index b1a80710a4df..d100b725283f 100644 --- a/dev-packages/e2e-tests/test-applications/node-nestjs/tests/propagation.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-nestjs/tests/propagation.test.ts @@ -1,6 +1,6 @@ import crypto from 'crypto'; import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; import { SpanJSON } from '@sentry/types'; test('Propagates trace for outgoing http requests', async ({ baseURL }) => { diff --git a/dev-packages/e2e-tests/test-applications/node-nestjs/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/node-nestjs/tests/transactions.test.ts index 5b48b1854afa..593c5e383f2b 100644 --- a/dev-packages/e2e-tests/test-applications/node-nestjs/tests/transactions.test.ts +++ b/dev-packages/e2e-tests/test-applications/node-nestjs/tests/transactions.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('Sends an API route transaction', async ({ baseURL }) => { const pageloadTransactionEventPromise = waitForTransaction('node-nestjs', transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/react-19/package.json b/dev-packages/e2e-tests/test-applications/react-19/package.json index 4c2f7d0df36e..d83bd81d6c3e 100644 --- a/dev-packages/e2e-tests/test-applications/react-19/package.json +++ b/dev-packages/e2e-tests/test-applications/react-19/package.json @@ -47,8 +47,8 @@ ] }, "devDependencies": { - "@playwright/test": "^1.43.1", - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "serve": "14.0.1" }, "volta": { diff --git a/dev-packages/e2e-tests/test-applications/react-19/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/react-19/playwright.config.mjs new file mode 100644 index 000000000000..31f2b913b58b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/react-19/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/react-19/playwright.config.ts b/dev-packages/e2e-tests/test-applications/react-19/playwright.config.ts deleted file mode 100644 index 3d7268ce5dc1..000000000000 --- a/dev-packages/e2e-tests/test-applications/react-19/playwright.config.ts +++ /dev/null @@ -1,82 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const reactPort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Opt out of parallel tests on CI. */ - workers: 1, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - - baseURL: `http://localhost:${reactPort}`, - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - // For now we only test Chrome! - // { - // name: 'firefox', - // use: { - // ...devices['Desktop Firefox'], - // }, - // }, - // { - // name: 'webkit', - // use: { - // ...devices['Desktop Safari'], - // }, - // }, - ], - - /* Run your local dev server before starting the tests */ - - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: 'pnpm start', - port: reactPort, - env: { - PORT: `${reactPort}`, - }, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/react-19/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/react-19/start-event-proxy.mjs index e0102436fdd0..bf80522a3d7e 100644 --- a/dev-packages/e2e-tests/test-applications/react-19/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/react-19/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/react-19/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/react-19/tests/errors.test.ts index 9040d217d1bb..46e19b11a2ac 100644 --- a/dev-packages/e2e-tests/test-applications/react-19/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-19/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; test('Catches errors caught by error boundary', async ({ page }) => { page.on('console', message => { diff --git a/dev-packages/e2e-tests/test-applications/react-create-hash-router/package.json b/dev-packages/e2e-tests/test-applications/react-create-hash-router/package.json index f028794e9830..c289c76af506 100644 --- a/dev-packages/e2e-tests/test-applications/react-create-hash-router/package.json +++ b/dev-packages/e2e-tests/test-applications/react-create-hash-router/package.json @@ -15,8 +15,7 @@ "react-dom": "18.2.0", "react-router-dom": "^6.4.1", "react-scripts": "5.0.1", - "typescript": "4.4.2", - "web-vitals": "2.1.0" + "typescript": "4.4.2" }, "scripts": { "build": "react-scripts build", @@ -46,8 +45,8 @@ ] }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "1.26.1", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "serve": "14.0.1" }, "volta": { diff --git a/dev-packages/e2e-tests/test-applications/react-create-hash-router/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/react-create-hash-router/playwright.config.mjs index 4ac124380c0d..31f2b913b58b 100644 --- a/dev-packages/e2e-tests/test-applications/react-create-hash-router/playwright.config.mjs +++ b/dev-packages/e2e-tests/test-applications/react-create-hash-router/playwright.config.mjs @@ -1,81 +1,7 @@ -import { devices } from '@playwright/test'; +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; -const serverPort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Opt out of parallel tests on CI. */ - workers: 1, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${serverPort}`, - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - // For now we only test Chrome! - // { - // name: 'firefox', - // use: { - // ...devices['Desktop Firefox'], - // }, - // }, - // { - // name: 'webkit', - // use: { - // ...devices['Desktop Safari'], - // }, - // }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: 'pnpm start', - port: serverPort, - env: { - PORT: '3030', - }, - }, - ], -}; +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); export default config; diff --git a/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/index.tsx b/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/index.tsx index dc27c8fb9ac1..638f38e2a3c4 100644 --- a/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/index.tsx +++ b/dev-packages/e2e-tests/test-applications/react-create-hash-router/src/index.tsx @@ -38,7 +38,7 @@ Sentry.init({ replaysSessionSampleRate: 1.0, replaysOnErrorSampleRate: 0.0, - debug: true, + debug: !!process.env.DEBUG, }); const sentryCreateHashRouter = Sentry.wrapCreateBrowserRouter(createHashRouter); diff --git a/dev-packages/e2e-tests/test-applications/react-create-hash-router/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/react-create-hash-router/start-event-proxy.mjs index 0a802ff33b16..f99a31fa19cf 100644 --- a/dev-packages/e2e-tests/test-applications/react-create-hash-router/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/react-create-hash-router/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/react-create-hash-router/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/react-create-hash-router/tests/errors.test.ts index 80dab4ba949c..1602f10c3e3e 100644 --- a/dev-packages/e2e-tests/test-applications/react-create-hash-router/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-create-hash-router/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; test('Captures exception correctly', async ({ page }) => { const errorEventPromise = waitForError('react-create-hash-router', event => { diff --git a/dev-packages/e2e-tests/test-applications/react-create-hash-router/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/react-create-hash-router/tests/transactions.test.ts index 24548324985a..e39db36ea6cb 100644 --- a/dev-packages/e2e-tests/test-applications/react-create-hash-router/tests/transactions.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-create-hash-router/tests/transactions.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('Captures a pageload transaction', async ({ page }) => { const transactionEventPromise = waitForTransaction('react-create-hash-router', event => { @@ -50,20 +50,6 @@ test('Captures a pageload transaction', async ({ page }) => { trace_id: expect.any(String), origin: 'auto.ui.browser.metrics', }); - expect(transactionEvent.spans).toContainEqual({ - data: { - 'sentry.origin': 'auto.ui.browser.metrics', - 'sentry.op': 'browser', - }, - description: 'loadEvent', - op: 'browser', - parent_span_id: expect.any(String), - span_id: expect.any(String), - start_timestamp: expect.any(Number), - timestamp: expect.any(Number), - trace_id: expect.any(String), - origin: 'auto.ui.browser.metrics', - }); expect(transactionEvent.spans).toContainEqual({ data: { 'sentry.origin': 'auto.ui.browser.metrics', diff --git a/dev-packages/e2e-tests/test-applications/react-router-5/package.json b/dev-packages/e2e-tests/test-applications/react-router-5/package.json index 93f13f25ae6f..e60c3e7f346b 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-5/package.json +++ b/dev-packages/e2e-tests/test-applications/react-router-5/package.json @@ -49,8 +49,8 @@ ] }, "devDependencies": { - "@playwright/test": "^1.43.1", - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "serve": "14.0.1" }, "volta": { diff --git a/dev-packages/e2e-tests/test-applications/react-router-5/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/react-router-5/playwright.config.mjs new file mode 100644 index 000000000000..31f2b913b58b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/react-router-5/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/react-router-5/playwright.config.ts b/dev-packages/e2e-tests/test-applications/react-router-5/playwright.config.ts deleted file mode 100644 index 3d7268ce5dc1..000000000000 --- a/dev-packages/e2e-tests/test-applications/react-router-5/playwright.config.ts +++ /dev/null @@ -1,82 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const reactPort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Opt out of parallel tests on CI. */ - workers: 1, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - - baseURL: `http://localhost:${reactPort}`, - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - // For now we only test Chrome! - // { - // name: 'firefox', - // use: { - // ...devices['Desktop Firefox'], - // }, - // }, - // { - // name: 'webkit', - // use: { - // ...devices['Desktop Safari'], - // }, - // }, - ], - - /* Run your local dev server before starting the tests */ - - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: 'pnpm start', - port: reactPort, - env: { - PORT: `${reactPort}`, - }, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/react-router-5/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/react-router-5/start-event-proxy.mjs index 4b18df9aacaf..1866a59e318d 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-5/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/react-router-5/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/react-router-5/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/react-router-5/tests/errors.test.ts index bcfafe8b6624..11ba3f8df5d5 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-5/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-router-5/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('Sends correct error event', async ({ page }) => { const errorEventPromise = waitForError('react-router-5', event => { diff --git a/dev-packages/e2e-tests/test-applications/react-router-5/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/react-router-5/tests/transactions.test.ts index e13c4702dc55..71808851a290 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-5/tests/transactions.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-router-5/tests/transactions.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('sends a pageload transaction with a parameterized URL', async ({ page }) => { const transactionPromise = waitForTransaction('react-router-5', async transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/package.json b/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/package.json index 88ebe78043ba..3ce8af8b1d59 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/package.json +++ b/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/package.json @@ -47,8 +47,8 @@ ] }, "devDependencies": { - "@playwright/test": "^1.43.1", - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "serve": "14.0.1" }, "volta": { diff --git a/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/playwright.config.mjs new file mode 100644 index 000000000000..31f2b913b58b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/playwright.config.ts b/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/playwright.config.ts deleted file mode 100644 index 3d7268ce5dc1..000000000000 --- a/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/playwright.config.ts +++ /dev/null @@ -1,82 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const reactPort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Opt out of parallel tests on CI. */ - workers: 1, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - - baseURL: `http://localhost:${reactPort}`, - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - // For now we only test Chrome! - // { - // name: 'firefox', - // use: { - // ...devices['Desktop Firefox'], - // }, - // }, - // { - // name: 'webkit', - // use: { - // ...devices['Desktop Safari'], - // }, - // }, - ], - - /* Run your local dev server before starting the tests */ - - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: 'pnpm start', - port: reactPort, - env: { - PORT: `${reactPort}`, - }, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/start-event-proxy.mjs index a836ebb7baa6..1265777dc613 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/errors.test.ts index baecddb9b96d..10fea8625a51 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('Sends correct error event', async ({ page }) => { const errorEventPromise = waitForError('react-router-6-use-routes', event => { diff --git a/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/transactions.test.ts index 75b42ebe6c0a..b8d2c9865e25 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/transactions.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/transactions.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('sends a pageload transaction with a parameterized URL', async ({ page }) => { const transactionPromise = waitForTransaction('react-router-6-use-routes', async transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/package.json b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/package.json index 092a5c0ac221..cfe6db496351 100644 --- a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/package.json +++ b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/package.json @@ -47,8 +47,7 @@ ] }, "devDependencies": { - "@playwright/test": "1.26.1", - "axios": "1.6.0", + "@playwright/test": "^1.44.1", "serve": "14.0.1" }, "volta": { diff --git a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts index 96e180351044..e7fd943c0f08 100644 --- a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts +++ b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts @@ -175,6 +175,7 @@ export const ReplayRecordingData = [ decodedBodySize: expect.any(Number), encodedBodySize: expect.any(Number), size: expect.any(Number), + statusCode: 200, }, }, }, diff --git a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts index 9c820e2157de..d9c3e09f2ad2 100644 --- a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts @@ -90,7 +90,7 @@ test('Sends a navigation transaction to Sentry', async ({ page }) => { await page.goto('/'); // Give pageload transaction time to finish - page.waitForTimeout(4000); + await page.waitForTimeout(4000); const linkElement = page.locator('id=navigation'); await linkElement.click(); diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/package.json b/dev-packages/e2e-tests/test-applications/standard-frontend-react/package.json index 072a856a29da..bf1cd59a0a77 100644 --- a/dev-packages/e2e-tests/test-applications/standard-frontend-react/package.json +++ b/dev-packages/e2e-tests/test-applications/standard-frontend-react/package.json @@ -47,7 +47,7 @@ ] }, "devDependencies": { - "@playwright/test": "1.26.1", + "@playwright/test": "^1.44.1", "serve": "14.0.1" }, "volta": { diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/src/index.tsx b/dev-packages/e2e-tests/test-applications/standard-frontend-react/src/index.tsx index 3a87a53ffdfa..5980df0ff8dd 100644 --- a/dev-packages/e2e-tests/test-applications/standard-frontend-react/src/index.tsx +++ b/dev-packages/e2e-tests/test-applications/standard-frontend-react/src/index.tsx @@ -38,12 +38,6 @@ Sentry.init({ replaysOnErrorSampleRate: 0.0, }); -Object.defineProperty(window, 'sentryReplayId', { - get() { - return replay['_replay'].session.id; - }, -}); - Sentry.addEventProcessor(event => { if ( event.type === 'transaction' && diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/behaviour-test.spec.ts b/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/behaviour-test.spec.ts index fabdd40e588f..5e9b5ed0cdd6 100644 --- a/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/behaviour-test.spec.ts +++ b/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/behaviour-test.spec.ts @@ -1,5 +1,4 @@ import { expect, test } from '@playwright/test'; -import { ReplayRecordingData } from './fixtures/ReplayRecordingData'; const EVENT_POLLING_TIMEOUT = 90_000; @@ -88,7 +87,7 @@ test('Sends a navigation transaction to Sentry', async ({ page }) => { await page.goto('/'); // Give pageload transaction time to finish - page.waitForTimeout(4000); + await page.waitForTimeout(4000); const linkElement = page.locator('id=navigation'); await linkElement.click(); @@ -139,62 +138,3 @@ test('Sends a navigation transaction to Sentry', async ({ page }) => { expect(hadPageNavigationTransaction).toBe(true); }); - -test('Sends a Replay recording to Sentry', async ({ browser }) => { - const context = await browser.newContext(); - const page = await context.newPage(); - - await page.goto('/'); - - const replayId = await page.waitForFunction(() => { - return window.sentryReplayId; - }); - - // Keypress event ensures LCP is finished - await page.type('body', 'Y'); - - // Wait for replay to be sent - - if (replayId === undefined) { - throw new Error("Application didn't set a replayId"); - } - - console.log(`Polling for replay with ID: ${replayId}`); - - await expect - .poll( - async () => { - const response = await fetch( - `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/replays/${replayId}/`, - { headers: { Authorization: `Bearer ${authToken}` } }, - ); - return response.status; - }, - { - timeout: EVENT_POLLING_TIMEOUT, - }, - ) - .toBe(200); - - // now fetch the first recording segment - await expect - .poll( - async () => { - const response = await fetch( - `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/replays/${replayId}/recording-segments/?cursor=100%3A0%3A1`, - { headers: { Authorization: `Bearer ${authToken}` } }, - ); - - if (response.ok) { - const data = await response.json(); - return data[0]; - } - - return response.status; - }, - { - timeout: EVENT_POLLING_TIMEOUT, - }, - ) - .toEqual(ReplayRecordingData); -}); diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/fixtures/ReplayRecordingData.ts b/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/fixtures/ReplayRecordingData.ts deleted file mode 100644 index 96e180351044..000000000000 --- a/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/fixtures/ReplayRecordingData.ts +++ /dev/null @@ -1,246 +0,0 @@ -import { expect } from '@playwright/test'; - -export const ReplayRecordingData = [ - { - type: 4, - data: { href: expect.stringMatching(/http:\/\/localhost:\d+\//), width: 1280, height: 720 }, - timestamp: expect.any(Number), - }, - { - data: { - payload: { - blockAllMedia: true, - errorSampleRate: 0, - maskAllInputs: true, - maskAllText: true, - networkCaptureBodies: true, - networkDetailHasUrls: false, - networkRequestHasHeaders: true, - networkResponseHasHeaders: true, - sessionSampleRate: 1, - shouldRecordCanvas: false, - useCompression: false, - useCompressionOption: true, - }, - tag: 'options', - }, - timestamp: expect.any(Number), - type: 5, - }, - { - type: 2, - data: { - node: { - type: 0, - childNodes: [ - { type: 1, name: 'html', publicId: '', systemId: '', id: 2 }, - { - type: 2, - tagName: 'html', - attributes: { lang: 'en' }, - childNodes: [ - { - type: 2, - tagName: 'head', - attributes: {}, - childNodes: [ - { type: 2, tagName: 'meta', attributes: { charset: 'utf-8' }, childNodes: [], id: 5 }, - { - type: 2, - tagName: 'meta', - attributes: { name: 'viewport', content: 'width=device-width,initial-scale=1' }, - childNodes: [], - id: 6, - }, - { - type: 2, - tagName: 'meta', - attributes: { name: 'theme-color', content: '#000000' }, - childNodes: [], - id: 7, - }, - { - type: 2, - tagName: 'title', - attributes: {}, - childNodes: [{ type: 3, textContent: '***** ***', id: 9 }], - id: 8, - }, - ], - id: 4, - }, - { - type: 2, - tagName: 'body', - attributes: {}, - childNodes: [ - { - type: 2, - tagName: 'noscript', - attributes: {}, - childNodes: [{ type: 3, textContent: '*** **** ** ****** ********** ** *** **** ****', id: 12 }], - id: 11, - }, - { type: 2, tagName: 'div', attributes: { id: 'root' }, childNodes: [], id: 13 }, - ], - id: 10, - }, - ], - id: 3, - }, - ], - id: 1, - }, - initialOffset: { left: 0, top: 0 }, - }, - timestamp: expect.any(Number), - }, - { - type: 3, - data: { - source: 0, - texts: [], - attributes: [], - removes: [], - adds: [ - { - parentId: 13, - nextId: null, - node: { - type: 2, - tagName: 'a', - attributes: { id: 'navigation', href: expect.stringMatching(/http:\/\/localhost:\d+\/user\/5/) }, - childNodes: [], - id: 14, - }, - }, - { parentId: 14, nextId: null, node: { type: 3, textContent: '********', id: 15 } }, - { - parentId: 13, - nextId: 14, - node: { - type: 2, - tagName: 'input', - attributes: { type: 'button', id: 'exception-button', value: '******* *********' }, - childNodes: [], - id: 16, - }, - }, - ], - }, - timestamp: expect.any(Number), - }, - { - type: 3, - data: { source: 5, text: 'Capture Exception', isChecked: false, id: 16 }, - timestamp: expect.any(Number), - }, - { - type: 5, - timestamp: expect.any(Number), - data: { - tag: 'performanceSpan', - payload: { - op: 'navigation.navigate', - description: expect.stringMatching(/http:\/\/localhost:\d+\//), - startTimestamp: expect.any(Number), - endTimestamp: expect.any(Number), - data: { - decodedBodySize: expect.any(Number), - encodedBodySize: expect.any(Number), - duration: expect.any(Number), - domInteractive: expect.any(Number), - domContentLoadedEventEnd: expect.any(Number), - domContentLoadedEventStart: expect.any(Number), - loadEventStart: expect.any(Number), - loadEventEnd: expect.any(Number), - domComplete: expect.any(Number), - redirectCount: expect.any(Number), - size: expect.any(Number), - }, - }, - }, - }, - { - type: 5, - timestamp: expect.any(Number), - data: { - tag: 'performanceSpan', - payload: { - op: 'resource.script', - description: expect.stringMatching(/http:\/\/localhost:\d+\/static\/js\/main.(\w+).js/), - startTimestamp: expect.any(Number), - endTimestamp: expect.any(Number), - data: { - decodedBodySize: expect.any(Number), - encodedBodySize: expect.any(Number), - size: expect.any(Number), - }, - }, - }, - }, - { - type: 5, - timestamp: expect.any(Number), - data: { - tag: 'performanceSpan', - payload: { - op: 'paint', - description: 'first-paint', - startTimestamp: expect.any(Number), - endTimestamp: expect.any(Number), - }, - }, - }, - { - type: 5, - timestamp: expect.any(Number), - data: { - tag: 'performanceSpan', - payload: { - op: 'paint', - description: 'first-contentful-paint', - startTimestamp: expect.any(Number), - endTimestamp: expect.any(Number), - }, - }, - }, - { - type: 5, - timestamp: expect.any(Number), - data: { - tag: 'performanceSpan', - payload: { - op: 'web-vital', - description: 'largest-contentful-paint', - startTimestamp: expect.any(Number), - endTimestamp: expect.any(Number), - data: { - value: expect.any(Number), - size: expect.any(Number), - nodeId: 16, - }, - }, - }, - }, - { - type: 5, - timestamp: expect.any(Number), - data: { - tag: 'performanceSpan', - payload: { - op: 'memory', - description: 'memory', - startTimestamp: expect.any(Number), - endTimestamp: expect.any(Number), - data: { - memory: { - jsHeapSizeLimit: expect.any(Number), - totalJSHeapSize: expect.any(Number), - usedJSHeapSize: expect.any(Number), - }, - }, - }, - }, - }, -]; diff --git a/dev-packages/e2e-tests/test-applications/svelte-5/package.json b/dev-packages/e2e-tests/test-applications/svelte-5/package.json index d95aa579e9a6..82c256519a36 100644 --- a/dev-packages/e2e-tests/test-applications/svelte-5/package.json +++ b/dev-packages/e2e-tests/test-applications/svelte-5/package.json @@ -13,8 +13,8 @@ "test:assert": "pnpm test:prod" }, "devDependencies": { - "@playwright/test": "^1.43.1", - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@sentry/types": "latest || *", "@sentry/utils": "latest || *", "@sveltejs/vite-plugin-svelte": "^3.0.2", @@ -23,8 +23,7 @@ "svelte-check": "^3.6.7", "tslib": "^2.6.2", "typescript": "^5.2.2", - "vite": "^5.2.0", - "wait-port": "1.0.4" + "vite": "^5.2.0" }, "dependencies": { "@sentry/svelte": "latest || *" diff --git a/dev-packages/e2e-tests/test-applications/svelte-5/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/svelte-5/playwright.config.mjs new file mode 100644 index 000000000000..0c468af7d879 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/svelte-5/playwright.config.mjs @@ -0,0 +1,8 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: 'pnpm preview --port 3030', + port: 3030, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/svelte-5/playwright.config.ts b/dev-packages/e2e-tests/test-applications/svelte-5/playwright.config.ts deleted file mode 100644 index 37a5c8726a36..000000000000 --- a/dev-packages/e2e-tests/test-applications/svelte-5/playwright.config.ts +++ /dev/null @@ -1,72 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const testEnv = process.env.TEST_ENV; - -if (!testEnv) { - throw new Error('No test env defined'); -} - -const sveltePort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './test', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 10000, - }, - /* Run tests in files in parallel */ - fullyParallel: false, - workers: 1, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* `next dev` is incredibly buggy with the app dir */ - retries: testEnv === 'development' ? 3 : 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${sveltePort}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node ./start-event-proxy.mjs', - port: eventProxyPort, - reuseExistingServer: false, - }, - { - command: `pnpm wait-port ${eventProxyPort} && pnpm preview --port ${sveltePort}`, - port: sveltePort, - reuseExistingServer: false, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/svelte-5/src/main.ts b/dev-packages/e2e-tests/test-applications/svelte-5/src/main.ts index e42063fb9183..9f5fb70cea94 100644 --- a/dev-packages/e2e-tests/test-applications/svelte-5/src/main.ts +++ b/dev-packages/e2e-tests/test-applications/svelte-5/src/main.ts @@ -10,7 +10,7 @@ Sentry.init({ tracesSampleRate: 1.0, integrations: [Sentry.browserTracingIntegration(), Sentry.replayIntegration()], tunnel: 'http://localhost:3031/', // proxy server - debug: true, + debug: !!process.env.DEBUG, }); const target = document.getElementById('app'); diff --git a/dev-packages/e2e-tests/test-applications/svelte-5/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/svelte-5/start-event-proxy.mjs index 51f34487945c..cd37498da887 100644 --- a/dev-packages/e2e-tests/test-applications/svelte-5/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/svelte-5/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/svelte-5/test/errors.test.ts b/dev-packages/e2e-tests/test-applications/svelte-5/tests/errors.test.ts similarity index 90% rename from dev-packages/e2e-tests/test-applications/svelte-5/test/errors.test.ts rename to dev-packages/e2e-tests/test-applications/svelte-5/tests/errors.test.ts index 803e49e24fd0..6e3267eab2ed 100644 --- a/dev-packages/e2e-tests/test-applications/svelte-5/test/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/svelte-5/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; test('sends an error', async ({ page }) => { const errorPromise = waitForError('svelte-5', async errorEvent => { diff --git a/dev-packages/e2e-tests/test-applications/svelte-5/test/performance.test.ts b/dev-packages/e2e-tests/test-applications/svelte-5/tests/performance.test.ts similarity index 94% rename from dev-packages/e2e-tests/test-applications/svelte-5/test/performance.test.ts rename to dev-packages/e2e-tests/test-applications/svelte-5/tests/performance.test.ts index 5e4e52d597b4..05391ed88042 100644 --- a/dev-packages/e2e-tests/test-applications/svelte-5/test/performance.test.ts +++ b/dev-packages/e2e-tests/test-applications/svelte-5/tests/performance.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('sends a pageload transaction with component tracking init spans', async ({ page }) => { const transactionPromise = waitForTransaction('svelte-5', async transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/package.json b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/package.json index 1e3b02d5d4b1..ef59fc456b5f 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/package.json +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/package.json @@ -19,8 +19,8 @@ "@spotlightjs/spotlight": "2.0.0-alpha.1" }, "devDependencies": { - "@playwright/test": "^1.36.2", - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@sentry/types": "latest || *", "@sentry/utils": "latest || *", "@sveltejs/adapter-auto": "^3.0.0", @@ -30,8 +30,7 @@ "svelte-check": "^3.6.0", "tslib": "^2.4.1", "typescript": "^5.0.0", - "vite": "^5.0.3", - "wait-port": "1.0.4" + "vite": "^5.0.3" }, "type": "module" } diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/playwright.config.mjs new file mode 100644 index 000000000000..0c468af7d879 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/playwright.config.mjs @@ -0,0 +1,8 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: 'pnpm preview --port 3030', + port: 3030, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/playwright.config.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/playwright.config.ts deleted file mode 100644 index 87f7ec8bbe32..000000000000 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/playwright.config.ts +++ /dev/null @@ -1,74 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const testEnv = process.env.TEST_ENV; - -if (!testEnv) { - throw new Error('No test env defined'); -} - -const svelteKitPort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './test', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 10000, - }, - /* Run tests in files in parallel */ - fullyParallel: false, - workers: 1, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* `next dev` is incredibly buggy with the app dir */ - retries: testEnv === 'development' ? 3 : 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${svelteKitPort}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - reuseExistingServer: false, - }, - { - command: `pnpm wait-port ${eventProxyPort} && pnpm preview --port ${svelteKitPort}`, - port: svelteKitPort, - reuseExistingServer: false, - }, - ], -}; - -export default config; - -`node --require @sentry/node/require my-app.js`; diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.client.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.client.ts index 606379b59760..91592e7ab932 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.client.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.client.ts @@ -5,7 +5,7 @@ import * as Spotlight from '@spotlightjs/spotlight'; Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions dsn: env.PUBLIC_E2E_TEST_DSN, - debug: true, + debug: !!env.PUBLIC_DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, }); diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.server.ts index 3fedded42858..99bf4a17aa96 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.server.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/src/hooks.server.ts @@ -5,7 +5,7 @@ import { setupSidecar } from '@spotlightjs/spotlight/sidecar'; Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions dsn: E2E_TEST_DSN, - debug: true, + debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, spotlight: import.meta.env.DEV, diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/start-event-proxy.mjs index 537e4f60abe2..087080644ebb 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/errors.client.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/errors.client.test.ts similarity index 96% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/errors.client.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/errors.client.test.ts index c70b9a93dbbb..1984a0db9603 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/errors.client.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/errors.client.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; import { waitForInitialPageload } from './utils'; test.describe('client-side errors', () => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/errors.server.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/errors.server.test.ts similarity index 97% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/errors.server.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/errors.server.test.ts index bbd87a5366a6..0764d26e05a5 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/errors.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/errors.server.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; test.describe('server-side errors', () => { test('captures universal load error', async ({ page }) => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/performance.client.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.client.test.ts similarity index 98% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/performance.client.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.client.test.ts index 324b83977ba1..c31e51bf9e99 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/performance.client.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.client.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; import { waitForInitialPageload } from './utils'; test.describe('client-specific performance events', () => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/performance.server.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.server.test.ts similarity index 94% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/performance.server.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.server.test.ts index 10d0690e70b8..8c23996c9a37 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/performance.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.server.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('server pageload request span has nested request span for sub request', async ({ page }) => { const serverTxnEventPromise = waitForTransaction('sveltekit-2-svelte-5', txnEvent => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/performance.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.test.ts similarity index 99% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/performance.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.test.ts index 83932a4ac362..2e5c4eb63e48 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/performance.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; import { waitForInitialPageload } from './utils'; test.describe('performance events', () => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/utils.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/utils.ts similarity index 95% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/utils.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/utils.ts index 5dcc01bbe7f8..e77e2eb742e2 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/test/utils.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/utils.ts @@ -1,5 +1,5 @@ import { Page } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; /** * Helper function that waits for the initial pageload to complete. diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/package.json b/dev-packages/e2e-tests/test-applications/sveltekit-2/package.json index ae18e7e34017..738f4a51bb3d 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/package.json +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/package.json @@ -18,8 +18,8 @@ "@sentry/sveltekit": "latest || *" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "^1.36.2", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@sentry/types": "latest || *", "@sentry/utils": "latest || *", "@sveltejs/adapter-auto": "^3.0.0", @@ -29,8 +29,7 @@ "svelte": "^4.2.8", "svelte-check": "^3.6.0", "typescript": "^5.0.0", - "vite": "^5.0.3", - "wait-port": "1.0.4" + "vite": "^5.0.3" }, "type": "module" } diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/sveltekit-2/playwright.config.mjs new file mode 100644 index 000000000000..71d97e4da2fd --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/playwright.config.mjs @@ -0,0 +1,13 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const testEnv = process.env.TEST_ENV; + +if (!testEnv) { + throw new Error('No test env defined'); +} + +const config = getPlaywrightConfig({ + startCommand: testEnv === 'development' ? `pnpm dev --port 3030` : `node build`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/playwright.config.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/playwright.config.ts deleted file mode 100644 index fe5a219c8e3d..000000000000 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/playwright.config.ts +++ /dev/null @@ -1,75 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const testEnv = process.env.TEST_ENV; - -if (!testEnv) { - throw new Error('No test env defined'); -} - -const svelteKitPort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './test', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 10000, - }, - /* Run tests in files in parallel */ - fullyParallel: false, - workers: 1, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* `next dev` is incredibly buggy with the app dir */ - retries: testEnv === 'development' ? 3 : 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${svelteKitPort}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - reuseExistingServer: false, - }, - { - command: - testEnv === 'development' - ? `pnpm wait-port ${eventProxyPort} && pnpm dev --port ${svelteKitPort}` - : `pnpm wait-port ${eventProxyPort} && PORT=${svelteKitPort} node build`, - port: svelteKitPort, - reuseExistingServer: false, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.client.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.client.ts index bfe90b150886..b174e9671b8d 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.client.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.client.ts @@ -4,7 +4,7 @@ import * as Sentry from '@sentry/sveltekit'; Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions dsn: env.PUBLIC_E2E_TEST_DSN, - debug: true, + debug: !!env.PUBLIC_DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, }); diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.server.ts index 2a2abbb870dd..92909c53a24c 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.server.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/src/hooks.server.ts @@ -4,7 +4,7 @@ import * as Sentry from '@sentry/sveltekit'; Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions dsn: E2E_TEST_DSN, - debug: true, + debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, }); diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/sveltekit-2/start-event-proxy.mjs index fcf2c0b9addc..7ebb1c1d4d68 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/errors.client.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/errors.client.test.ts similarity index 96% rename from dev-packages/e2e-tests/test-applications/sveltekit-2/test/errors.client.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2/tests/errors.client.test.ts index eb83566a475d..eecd5e00fae0 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/errors.client.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/errors.client.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; import { waitForInitialPageload } from './utils'; test.describe('client-side errors', () => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/errors.server.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/errors.server.test.ts similarity index 96% rename from dev-packages/e2e-tests/test-applications/sveltekit-2/test/errors.server.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2/tests/errors.server.test.ts index 51488b103107..64a0b2e3c855 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/errors.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/errors.server.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; test.describe('server-side errors', () => { test('captures universal load error', async ({ page }) => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/performance.client.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.client.test.ts similarity index 98% rename from dev-packages/e2e-tests/test-applications/sveltekit-2/test/performance.client.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.client.test.ts index 403701a075be..b53a881252a0 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/performance.client.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.client.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; import { waitForInitialPageload } from './utils'; test.describe('client-specific performance events', () => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/performance.server.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.server.test.ts similarity index 93% rename from dev-packages/e2e-tests/test-applications/sveltekit-2/test/performance.server.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.server.test.ts index e04a056ca875..6f11fd17cd5b 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/performance.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.server.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('server pageload request span has nested request span for sub request', async ({ page }) => { const serverTxnEventPromise = waitForTransaction('sveltekit-2', txnEvent => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/performance.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.test.ts similarity index 99% rename from dev-packages/e2e-tests/test-applications/sveltekit-2/test/performance.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.test.ts index e2966f23fb8b..44d9dbdf5f01 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/performance.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; import { waitForInitialPageload } from './utils'; test.describe('performance events', () => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/utils.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/utils.ts similarity index 95% rename from dev-packages/e2e-tests/test-applications/sveltekit-2/test/utils.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2/tests/utils.ts index 2fa35d9ae874..84a7e5605a1d 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/test/utils.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/utils.ts @@ -1,5 +1,5 @@ import { Page } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; /** * Helper function that waits for the initial pageload to complete. diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/package.json b/dev-packages/e2e-tests/test-applications/sveltekit/package.json index 84fef7db3923..e6b109c437dc 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/package.json +++ b/dev-packages/e2e-tests/test-applications/sveltekit/package.json @@ -17,8 +17,8 @@ "@sentry/sveltekit": "latest || *" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "^1.41.1", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@sentry/types": "latest || *", "@sentry/utils": "latest || *", "@sveltejs/adapter-auto": "^2.0.0", @@ -27,8 +27,7 @@ "svelte": "^3.54.0", "svelte-check": "^3.0.1", "typescript": "^5.0.0", - "vite": "^4.2.0", - "wait-port": "1.0.4" + "vite": "^4.2.0" }, "type": "module" } diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/sveltekit/playwright.config.mjs new file mode 100644 index 000000000000..222c54f87389 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/sveltekit/playwright.config.mjs @@ -0,0 +1,14 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const testEnv = process.env.TEST_ENV; + +if (!testEnv) { + throw new Error('No test env defined'); +} + +const config = getPlaywrightConfig({ + startCommand: testEnv === 'development' ? `pnpm dev --port 3030` : `pnpm preview --port 3030`, + port: 3030, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/playwright.config.ts b/dev-packages/e2e-tests/test-applications/sveltekit/playwright.config.ts deleted file mode 100644 index 18d60ca75ba3..000000000000 --- a/dev-packages/e2e-tests/test-applications/sveltekit/playwright.config.ts +++ /dev/null @@ -1,73 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const testEnv = process.env.TEST_ENV; - -if (!testEnv) { - throw new Error('No test env defined'); -} - -const port = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './test', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 10000, - }, - workers: 1, - /* Run tests in files in parallel */ - fullyParallel: false, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* `next dev` is incredibly buggy with the app dir */ - retries: testEnv === 'development' ? 3 : 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${port}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: 3031, - }, - { - command: - testEnv === 'development' - ? `pnpm wait-port ${eventProxyPort} && pnpm dev --port ${port}` - : `pnpm wait-port ${eventProxyPort} && pnpm preview --port ${port}`, - port, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/src/hooks.client.ts b/dev-packages/e2e-tests/test-applications/sveltekit/src/hooks.client.ts index bfe90b150886..b174e9671b8d 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/src/hooks.client.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit/src/hooks.client.ts @@ -4,7 +4,7 @@ import * as Sentry from '@sentry/sveltekit'; Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions dsn: env.PUBLIC_E2E_TEST_DSN, - debug: true, + debug: !!env.PUBLIC_DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, }); diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/src/hooks.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit/src/hooks.server.ts index 375b8d2c170a..aca7e1b75139 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/src/hooks.server.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit/src/hooks.server.ts @@ -4,7 +4,7 @@ import * as Sentry from '@sentry/sveltekit'; Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions dsn: env.E2E_TEST_DSN, - debug: true, + debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, }); diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/sveltekit/start-event-proxy.mjs index cb0fd75c1530..db60ac582eb7 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/sveltekit/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/test/errors.client.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit/tests/errors.client.test.ts similarity index 96% rename from dev-packages/e2e-tests/test-applications/sveltekit/test/errors.client.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit/tests/errors.client.test.ts index 7f0a5c50faa0..b149496514c4 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/test/errors.client.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit/tests/errors.client.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; import { waitForInitialPageload } from '../utils'; test.describe('client-side errors', () => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/test/errors.server.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit/tests/errors.server.test.ts similarity index 97% rename from dev-packages/e2e-tests/test-applications/sveltekit/test/errors.server.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit/tests/errors.server.test.ts index 5a3940a213b5..22b6bb9d340c 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/test/errors.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit/tests/errors.server.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; test.describe('server-side errors', () => { test('captures universal load error', async ({ page }) => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/test/performance.client.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit/tests/performance.client.test.ts similarity index 97% rename from dev-packages/e2e-tests/test-applications/sveltekit/test/performance.client.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit/tests/performance.client.test.ts index d7107d5e7744..33515a950d3c 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/test/performance.client.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit/tests/performance.client.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; import { waitForInitialPageload } from '../utils.js'; test('records manually added component tracking spans', async ({ page }) => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/test/performance.server.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit/tests/performance.server.test.ts similarity index 94% rename from dev-packages/e2e-tests/test-applications/sveltekit/test/performance.server.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit/tests/performance.server.test.ts index e462d08ddeeb..42ad638676f7 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/test/performance.server.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit/tests/performance.server.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('server pageload request span has nested request span for sub request', async ({ page }) => { const serverTxnEventPromise = waitForTransaction('sveltekit', txnEvent => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/test/performance.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit/tests/performance.test.ts similarity index 97% rename from dev-packages/e2e-tests/test-applications/sveltekit/test/performance.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit/tests/performance.test.ts index cb2ac4446a49..42d4ef82a589 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/test/performance.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit/tests/performance.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; import { waitForInitialPageload } from '../utils.js'; test('sends a pageload transaction', async ({ page }) => { diff --git a/dev-packages/e2e-tests/test-applications/sveltekit/utils.ts b/dev-packages/e2e-tests/test-applications/sveltekit/utils.ts index c919c1d72e95..320d41aba389 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit/utils.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit/utils.ts @@ -1,5 +1,5 @@ import { Page } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; /** * Helper function that waits for the initial pageload to complete. diff --git a/dev-packages/e2e-tests/test-applications/tanstack-router/package.json b/dev-packages/e2e-tests/test-applications/tanstack-router/package.json index 2f761c7d3e71..7bee3d4ba828 100644 --- a/dev-packages/e2e-tests/test-applications/tanstack-router/package.json +++ b/dev-packages/e2e-tests/test-applications/tanstack-router/package.json @@ -25,8 +25,8 @@ "@vitejs/plugin-react-swc": "^3.5.0", "typescript": "^5.2.2", "vite": "^5.2.0", - "@playwright/test": "^1.41.1", - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server" + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/test-applications/tanstack-router/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/tanstack-router/playwright.config.mjs new file mode 100644 index 000000000000..31f2b913b58b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/tanstack-router/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/tanstack-router/playwright.config.ts b/dev-packages/e2e-tests/test-applications/tanstack-router/playwright.config.ts deleted file mode 100644 index 2167da6d754e..000000000000 --- a/dev-packages/e2e-tests/test-applications/tanstack-router/playwright.config.ts +++ /dev/null @@ -1,66 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const appPort = 3030; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Opt out of parallel tests on CI. */ - workers: 1, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - - baseURL: `http://localhost:${appPort}`, - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: 'pnpm start', - port: appPort, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/tanstack-router/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/tanstack-router/start-event-proxy.mjs index d65ca64f1e59..f2ab6289d317 100644 --- a/dev-packages/e2e-tests/test-applications/tanstack-router/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/tanstack-router/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/tanstack-router/tests/routing-instrumentation.test.ts b/dev-packages/e2e-tests/test-applications/tanstack-router/tests/routing-instrumentation.test.ts index 3201b436faba..59d15b989dd4 100644 --- a/dev-packages/e2e-tests/test-applications/tanstack-router/tests/routing-instrumentation.test.ts +++ b/dev-packages/e2e-tests/test-applications/tanstack-router/tests/routing-instrumentation.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('sends a pageload transaction with a parameterized URL', async ({ page }) => { const transactionPromise = waitForTransaction('tanstack-router', async transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/vue-3/package.json b/dev-packages/e2e-tests/test-applications/vue-3/package.json index 95288dc0e52f..f356285a79d9 100644 --- a/dev-packages/e2e-tests/test-applications/vue-3/package.json +++ b/dev-packages/e2e-tests/test-applications/vue-3/package.json @@ -20,8 +20,8 @@ "vue-router": "^4.2.5" }, "devDependencies": { - "@sentry-internal/event-proxy-server": "link:../../../event-proxy-server", - "@playwright/test": "^1.41.1", + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@sentry/types": "latest || *", "@sentry/utils": "latest || *", "@tsconfig/node20": "^20.1.2", @@ -33,8 +33,7 @@ "npm-run-all2": "^6.1.1", "typescript": "~5.3.0", "vite": "^5.0.11", - "vue-tsc": "^1.8.27", - "wait-port": "1.0.4" + "vue-tsc": "^1.8.27" }, "volta": { "extends": "../../package.json" diff --git a/dev-packages/e2e-tests/test-applications/vue-3/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/vue-3/playwright.config.mjs new file mode 100644 index 000000000000..94f38d88ad70 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/vue-3/playwright.config.mjs @@ -0,0 +1,8 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: 'pnpm preview --port 4173', + port: 4173, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/vue-3/playwright.config.ts b/dev-packages/e2e-tests/test-applications/vue-3/playwright.config.ts deleted file mode 100644 index 63c2b137a9d7..000000000000 --- a/dev-packages/e2e-tests/test-applications/vue-3/playwright.config.ts +++ /dev/null @@ -1,69 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -const testEnv = process.env['TEST_ENV'] || 'production'; - -if (!testEnv) { - throw new Error('No test env defined'); -} - -const vuePort = 4173; -const eventProxyPort = 3031; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 10000, - }, - fullyParallel: false, - workers: 1, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* `next dev` is incredibly buggy with the app dir */ - retries: testEnv === 'development' ? 3 : 0, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - /* Base URL to use in actions like `await page.goto('/')`. */ - baseURL: `http://localhost:${vuePort}`, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - ], - - /* Run your local dev server before starting the tests */ - webServer: [ - { - command: 'node start-event-proxy.mjs', - port: eventProxyPort, - }, - { - command: `pnpm wait-port ${eventProxyPort} && pnpm preview --port ${vuePort}`, - port: vuePort, - }, - ], -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/vue-3/src/main.ts b/dev-packages/e2e-tests/test-applications/vue-3/src/main.ts index 997c74fa0740..f4a01d4285c5 100644 --- a/dev-packages/e2e-tests/test-applications/vue-3/src/main.ts +++ b/dev-packages/e2e-tests/test-applications/vue-3/src/main.ts @@ -19,7 +19,6 @@ Sentry.init({ }), ], tunnel: `http://localhost:3031/`, // proxy server - debug: true, }); app.use(router); diff --git a/dev-packages/e2e-tests/test-applications/vue-3/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/vue-3/start-event-proxy.mjs index e8c8fdf3cd46..75992f4b5206 100644 --- a/dev-packages/e2e-tests/test-applications/vue-3/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/vue-3/start-event-proxy.mjs @@ -1,4 +1,4 @@ -import { startEventProxyServer } from '@sentry-internal/event-proxy-server'; +import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, diff --git a/dev-packages/e2e-tests/test-applications/vue-3/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/vue-3/tests/errors.test.ts index 14ab59ad7570..262cda11b366 100644 --- a/dev-packages/e2e-tests/test-applications/vue-3/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/vue-3/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/event-proxy-server'; +import { waitForError } from '@sentry-internal/test-utils'; test('sends an error', async ({ page }) => { const errorPromise = waitForError('vue-3', async errorEvent => { diff --git a/dev-packages/e2e-tests/test-applications/vue-3/tests/performance.test.ts b/dev-packages/e2e-tests/test-applications/vue-3/tests/performance.test.ts index aded68211784..bdf7b5b8e1fe 100644 --- a/dev-packages/e2e-tests/test-applications/vue-3/tests/performance.test.ts +++ b/dev-packages/e2e-tests/test-applications/vue-3/tests/performance.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForTransaction } from '@sentry-internal/event-proxy-server'; +import { waitForTransaction } from '@sentry-internal/test-utils'; test('sends a pageload transaction with a parameterized URL', async ({ page }) => { const transactionPromise = waitForTransaction('vue-3', async transactionEvent => { diff --git a/dev-packages/e2e-tests/test-applications/vue-3/tsconfig.node.json b/dev-packages/e2e-tests/test-applications/vue-3/tsconfig.node.json index 2c669eeb8e8a..280d8ca857df 100644 --- a/dev-packages/e2e-tests/test-applications/vue-3/tsconfig.node.json +++ b/dev-packages/e2e-tests/test-applications/vue-3/tsconfig.node.json @@ -1,6 +1,6 @@ { "extends": "@tsconfig/node20/tsconfig.json", - "include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "nightwatch.conf.*", "playwright.config.*"], + "include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "nightwatch.conf.*"], "compilerOptions": { "composite": true, "noEmit": true, diff --git a/dev-packages/e2e-tests/test-applications/webpack-4/package.json b/dev-packages/e2e-tests/test-applications/webpack-4/package.json index ee99ff43128e..8787fccf253c 100644 --- a/dev-packages/e2e-tests/test-applications/webpack-4/package.json +++ b/dev-packages/e2e-tests/test-applications/webpack-4/package.json @@ -8,7 +8,7 @@ "test:assert": "playwright test" }, "devDependencies": { - "@playwright/test": "^1.42.1", + "@playwright/test": "^1.44.1", "@sentry/browser": "latest || *", "webpack": "^4.47.0", "terser-webpack-plugin": "^4.2.3", diff --git a/dev-packages/e2e-tests/test-applications/webpack-5/package.json b/dev-packages/e2e-tests/test-applications/webpack-5/package.json index 871e43589971..bae94797b9bb 100644 --- a/dev-packages/e2e-tests/test-applications/webpack-5/package.json +++ b/dev-packages/e2e-tests/test-applications/webpack-5/package.json @@ -8,7 +8,7 @@ "test:assert": "playwright test" }, "devDependencies": { - "@playwright/test": "^1.42.1", + "@playwright/test": "^1.44.1", "@sentry/browser": "latest || *", "webpack": "^5.91.0", "terser-webpack-plugin": "^5.3.10", diff --git a/dev-packages/event-proxy-server/tsconfig.json b/dev-packages/event-proxy-server/tsconfig.json deleted file mode 100644 index 825380109ceb..000000000000 --- a/dev-packages/event-proxy-server/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": {}, - "include": ["src/**/*.ts"] -} diff --git a/dev-packages/event-proxy-server/.eslintrc.js b/dev-packages/test-utils/.eslintrc.js similarity index 100% rename from dev-packages/event-proxy-server/.eslintrc.js rename to dev-packages/test-utils/.eslintrc.js diff --git a/dev-packages/event-proxy-server/package.json b/dev-packages/test-utils/package.json similarity index 89% rename from dev-packages/event-proxy-server/package.json rename to dev-packages/test-utils/package.json index 2823c007e717..a03c8de0e99e 100644 --- a/dev-packages/event-proxy-server/package.json +++ b/dev-packages/test-utils/package.json @@ -1,7 +1,7 @@ { "private": true, "version": "8.7.0", - "name": "@sentry-internal/event-proxy-server", + "name": "@sentry-internal/test-utils", "author": "Sentry", "license": "MIT", "main": "build/cjs/index.js", @@ -40,7 +40,11 @@ "build:types": "tsc -p tsconfig.types.json", "clean": "rimraf -g ./node_modules ./build" }, + "peerDependencies": { + "@playwright/test": "^1.44.1" + }, "devDependencies": { + "@playwright/test": "^1.44.1", "@sentry/types": "8.7.0", "@sentry/utils": "8.7.0" }, diff --git a/dev-packages/event-proxy-server/rollup.npm.config.mjs b/dev-packages/test-utils/rollup.npm.config.mjs similarity index 100% rename from dev-packages/event-proxy-server/rollup.npm.config.mjs rename to dev-packages/test-utils/rollup.npm.config.mjs diff --git a/dev-packages/event-proxy-server/src/event-proxy-server.ts b/dev-packages/test-utils/src/event-proxy-server.ts similarity index 100% rename from dev-packages/event-proxy-server/src/event-proxy-server.ts rename to dev-packages/test-utils/src/event-proxy-server.ts diff --git a/dev-packages/event-proxy-server/src/index.ts b/dev-packages/test-utils/src/index.ts similarity index 70% rename from dev-packages/event-proxy-server/src/index.ts rename to dev-packages/test-utils/src/index.ts index 9ee4dfc54520..4425d2688800 100644 --- a/dev-packages/event-proxy-server/src/index.ts +++ b/dev-packages/test-utils/src/index.ts @@ -5,3 +5,5 @@ export { waitForRequest, waitForTransaction, } from './event-proxy-server'; + +export { getPlaywrightConfig } from './playwright-config'; diff --git a/dev-packages/test-utils/src/playwright-config.ts b/dev-packages/test-utils/src/playwright-config.ts new file mode 100644 index 000000000000..4f2ea54bc3b4 --- /dev/null +++ b/dev-packages/test-utils/src/playwright-config.ts @@ -0,0 +1,95 @@ +import type { PlaywrightTestConfig } from '@playwright/test'; + +/** Get a playwright config to use in an E2E test app. */ +export function getPlaywrightConfig( + options: { + startCommand: string; + port?: number; + eventProxyPort?: number; + eventProxyFile?: string; + }, + overwriteConfig?: Partial, +): PlaywrightTestConfig { + const testEnv = process.env['TEST_ENV'] || 'production'; + const appPort = options.port || 3030; + const eventProxyPort = options.eventProxyPort || 3031; + const eventProxyFile = options.eventProxyFile || 'start-event-proxy.mjs'; + const { startCommand } = options; + + /** + * See https://playwright.dev/docs/test-configuration. + */ + const config: PlaywrightTestConfig = { + testDir: './tests', + /* Maximum time one test can run for. */ + timeout: 150_000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 10000, + }, + fullyParallel: false, + workers: 1, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* In dev mode some apps are flaky, so we allow retry there... */ + retries: testEnv === 'development' ? 3 : 0, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'list', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: `http://localhost:${appPort}`, + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + // This comes from `devices["Desktop Chrome"] + // We inline this instead of importing this, + // because playwright otherwise complains that it was imported twice :( + userAgent: + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.6422.26 Safari/537.36', + viewport: { width: 1280, height: 720 }, + deviceScaleFactor: 1, + isMobile: false, + hasTouch: false, + defaultBrowserType: 'chromium', + }, + }, + ], + + /* Run your local dev server before starting the tests */ + webServer: [ + { + command: `node ${eventProxyFile}`, + port: eventProxyPort, + stdout: 'pipe', + stderr: 'pipe', + }, + { + command: startCommand, + port: appPort, + stdout: 'pipe', + stderr: 'pipe', + env: { + PORT: appPort.toString(), + }, + }, + ], + }; + + return { + ...config, + ...overwriteConfig, + }; +} diff --git a/dev-packages/test-utils/tsconfig.json b/dev-packages/test-utils/tsconfig.json new file mode 100644 index 000000000000..7b0fa87fc45b --- /dev/null +++ b/dev-packages/test-utils/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "target": "ES2022", + "module": "ES2022" + }, + "include": ["src/**/*.ts"] +} diff --git a/dev-packages/event-proxy-server/tsconfig.types.json b/dev-packages/test-utils/tsconfig.types.json similarity index 100% rename from dev-packages/event-proxy-server/tsconfig.types.json rename to dev-packages/test-utils/tsconfig.types.json diff --git a/package.json b/package.json index b7ac85b844e9..42a1b6cd0b89 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "dev-packages/e2e-tests", "dev-packages/node-integration-tests", "dev-packages/overhead-metrics", - "dev-packages/event-proxy-server", + "dev-packages/test-utils", "dev-packages/size-limit-gh-action", "dev-packages/rollup-utils" ], diff --git a/yarn.lock b/yarn.lock index e054994642fc..51f4ec587e73 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6571,12 +6571,12 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== -"@playwright/test@^1.43.1": - version "1.43.1" - resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.43.1.tgz#16728a59eb8ce0f60472f98d8886d6cab0fa3e42" - integrity sha512-HgtQzFgNEEo4TE22K/X7sYTYNqEMMTZmFS8kTq6m8hXj+m1D8TgwgIbumHddJa9h4yl4GkKb8/bgAl2+g7eDgA== +"@playwright/test@^1.44.1": + version "1.44.1" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.44.1.tgz#cc874ec31342479ad99838040e99b5f604299bcb" + integrity sha512-1hZ4TNvD5z9VuhNJ/walIjvMVvYkZKf71axoF/uiAqpntQJXpG64dlXhoDXE3OczPuTuvjf/M5KWFg5VAVUS3Q== dependencies: - playwright "1.43.1" + playwright "1.44.1" "@polka/url@^1.0.0-next.20": version "1.0.0-next.21" @@ -24951,17 +24951,17 @@ playwright-core@1.40.1, playwright-core@^1.29.1: resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.40.1.tgz#442d15e86866a87d90d07af528e0afabe4c75c05" integrity sha512-+hkOycxPiV534c4HhpfX6yrlawqVUzITRKwHAmYfmsVreltEl6fAZJ3DPfLMOODw0H3s1Itd6MDCWmP1fl/QvQ== -playwright-core@1.43.1: - version "1.43.1" - resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.43.1.tgz#0eafef9994c69c02a1a3825a4343e56c99c03b02" - integrity sha512-EI36Mto2Vrx6VF7rm708qSnesVQKbxEWvPrfA1IPY6HgczBplDx7ENtx+K2n4kJ41sLLkuGfmb0ZLSSXlDhqPg== +playwright-core@1.44.1: + version "1.44.1" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.44.1.tgz#53ec975503b763af6fc1a7aa995f34bc09ff447c" + integrity sha512-wh0JWtYTrhv1+OSsLPgFzGzt67Y7BE/ZS3jEqgGBlp2ppp1ZDj8c+9IARNW4dwf1poq5MgHreEM2KV/GuR4cFA== -playwright@1.43.1: - version "1.43.1" - resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.43.1.tgz#8ad08984ac66c9ef3d0db035be54dd7ec9f1c7d9" - integrity sha512-V7SoH0ai2kNt1Md9E3Gwas5B9m8KR2GVvwZnAI6Pg0m3sh7UvgiYhRrhsziCmqMJNouPckiOhk8T+9bSAK0VIA== +playwright@1.44.1: + version "1.44.1" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.44.1.tgz#5634369d777111c1eea9180430b7a184028e7892" + integrity sha512-qr/0UJ5CFAtloI3avF95Y0L1xQo6r3LQArLIg/z/PoGJ6xa+EwzrwO5lpNr/09STxdHuUoP2mvuELJS+hLdtgg== dependencies: - playwright-core "1.43.1" + playwright-core "1.44.1" optionalDependencies: fsevents "2.3.2" From 4772147fb5d3dc5ab1de5def47ce97fa8f47d137 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Fri, 31 May 2024 14:17:10 +0200 Subject: [PATCH 09/41] test: Refactor webpack E2E tests to avoid sending to Sentry (#12312) Part of https://github.com/getsentry/sentry-javascript/issues/11910 --- .../test-applications/webpack-4/entry.js | 6 +- .../test-applications/webpack-4/package.json | 1 + .../webpack-4/playwright.config.mjs | 7 ++ .../webpack-4/playwright.config.ts | 70 ------------------- .../webpack-4/start-event-proxy.mjs | 6 ++ .../webpack-4/tests/behaviour-test.spec.ts | 31 -------- .../webpack-4/tests/errors.test.ts | 14 ++++ .../test-applications/webpack-5/entry.js | 6 +- .../test-applications/webpack-5/package.json | 1 + .../webpack-5/playwright.config.mjs | 7 ++ .../webpack-5/playwright.config.ts | 70 ------------------- .../webpack-5/start-event-proxy.mjs | 6 ++ .../webpack-5/tests/behaviour-test.spec.ts | 31 -------- .../webpack-5/tests/errors.test.ts | 14 ++++ 14 files changed, 62 insertions(+), 208 deletions(-) create mode 100644 dev-packages/e2e-tests/test-applications/webpack-4/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/webpack-4/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/webpack-4/start-event-proxy.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/webpack-4/tests/behaviour-test.spec.ts create mode 100644 dev-packages/e2e-tests/test-applications/webpack-4/tests/errors.test.ts create mode 100644 dev-packages/e2e-tests/test-applications/webpack-5/playwright.config.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/webpack-5/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/webpack-5/start-event-proxy.mjs delete mode 100644 dev-packages/e2e-tests/test-applications/webpack-5/tests/behaviour-test.spec.ts create mode 100644 dev-packages/e2e-tests/test-applications/webpack-5/tests/errors.test.ts diff --git a/dev-packages/e2e-tests/test-applications/webpack-4/entry.js b/dev-packages/e2e-tests/test-applications/webpack-4/entry.js index 4fd9cd67e7e3..69877184b91a 100644 --- a/dev-packages/e2e-tests/test-applications/webpack-4/entry.js +++ b/dev-packages/e2e-tests/test-applications/webpack-4/entry.js @@ -1,11 +1,11 @@ -import { browserTracingIntegration, captureException, init } from '@sentry/browser'; +import { browserTracingIntegration, init } from '@sentry/browser'; init({ dsn: process.env.E2E_TEST_DSN, integrations: [browserTracingIntegration()], + tunnel: 'http://localhost:3031', }); setTimeout(() => { - const eventId = captureException(new Error('I am an error!')); - window.capturedExceptionId = eventId; + throw new Error('I am an error!'); }, 2000); diff --git a/dev-packages/e2e-tests/test-applications/webpack-4/package.json b/dev-packages/e2e-tests/test-applications/webpack-4/package.json index 8787fccf253c..311c2dcc468c 100644 --- a/dev-packages/e2e-tests/test-applications/webpack-4/package.json +++ b/dev-packages/e2e-tests/test-applications/webpack-4/package.json @@ -9,6 +9,7 @@ }, "devDependencies": { "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@sentry/browser": "latest || *", "webpack": "^4.47.0", "terser-webpack-plugin": "^4.2.3", diff --git a/dev-packages/e2e-tests/test-applications/webpack-4/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/webpack-4/playwright.config.mjs new file mode 100644 index 000000000000..4248d8d94297 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/webpack-4/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: 'pnpm start', +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/webpack-4/playwright.config.ts b/dev-packages/e2e-tests/test-applications/webpack-4/playwright.config.ts deleted file mode 100644 index 5f93f826ebf0..000000000000 --- a/dev-packages/e2e-tests/test-applications/webpack-4/playwright.config.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Opt out of parallel tests on CI. */ - workers: 1, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - // For now we only test Chrome! - // { - // name: 'firefox', - // use: { - // ...devices['Desktop Firefox'], - // }, - // }, - // { - // name: 'webkit', - // use: { - // ...devices['Desktop Safari'], - // }, - // }, - ], - - /* Run your local dev server before starting the tests */ - webServer: { - command: 'pnpm start', - port: 3030, - env: { - PORT: '3030', - }, - }, -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/webpack-4/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/webpack-4/start-event-proxy.mjs new file mode 100644 index 000000000000..5805ae9bca52 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/webpack-4/start-event-proxy.mjs @@ -0,0 +1,6 @@ +import { startEventProxyServer } from '@sentry-internal/test-utils'; + +startEventProxyServer({ + port: 3031, + proxyServerName: 'webpack-4', +}); diff --git a/dev-packages/e2e-tests/test-applications/webpack-4/tests/behaviour-test.spec.ts b/dev-packages/e2e-tests/test-applications/webpack-4/tests/behaviour-test.spec.ts deleted file mode 100644 index 7b824ef26579..000000000000 --- a/dev-packages/e2e-tests/test-applications/webpack-4/tests/behaviour-test.spec.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { expect, test } from '@playwright/test'; - -const EVENT_POLLING_TIMEOUT = 90_000; - -const authToken = process.env.E2E_TEST_AUTH_TOKEN; -const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; - -test('Sends an exception to Sentry', async ({ page }) => { - await page.goto('/'); - - const exceptionIdHandle = await page.waitForFunction(() => window.capturedExceptionId); - const exceptionEventId = await exceptionIdHandle.jsonValue(); - - console.log(`Polling for error eventId: ${exceptionEventId}`); - - await expect - .poll( - async () => { - const response = await fetch( - `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${exceptionEventId}/`, - { headers: { Authorization: `Bearer ${authToken}` } }, - ); - return response.status; - }, - { - timeout: EVENT_POLLING_TIMEOUT, - }, - ) - .toBe(200); -}); diff --git a/dev-packages/e2e-tests/test-applications/webpack-4/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/webpack-4/tests/errors.test.ts new file mode 100644 index 000000000000..2c2ca2dbb952 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/webpack-4/tests/errors.test.ts @@ -0,0 +1,14 @@ +import { expect, test } from '@playwright/test'; +import { waitForError } from '@sentry-internal/test-utils'; + +test('Captures an exception', async ({ page }) => { + const eventPromise = waitForError('webpack-4', event => { + return event.exception?.values?.[0].value === 'I am an error!'; + }); + await page.goto('/'); + + const errorEvent = await eventPromise; + + expect(errorEvent.exception?.values?.[0].value).toBe('I am an error!'); + expect(errorEvent.transaction).toBe('/'); +}); diff --git a/dev-packages/e2e-tests/test-applications/webpack-5/entry.js b/dev-packages/e2e-tests/test-applications/webpack-5/entry.js index 4fd9cd67e7e3..69877184b91a 100644 --- a/dev-packages/e2e-tests/test-applications/webpack-5/entry.js +++ b/dev-packages/e2e-tests/test-applications/webpack-5/entry.js @@ -1,11 +1,11 @@ -import { browserTracingIntegration, captureException, init } from '@sentry/browser'; +import { browserTracingIntegration, init } from '@sentry/browser'; init({ dsn: process.env.E2E_TEST_DSN, integrations: [browserTracingIntegration()], + tunnel: 'http://localhost:3031', }); setTimeout(() => { - const eventId = captureException(new Error('I am an error!')); - window.capturedExceptionId = eventId; + throw new Error('I am an error!'); }, 2000); diff --git a/dev-packages/e2e-tests/test-applications/webpack-5/package.json b/dev-packages/e2e-tests/test-applications/webpack-5/package.json index bae94797b9bb..996b4f240b74 100644 --- a/dev-packages/e2e-tests/test-applications/webpack-5/package.json +++ b/dev-packages/e2e-tests/test-applications/webpack-5/package.json @@ -9,6 +9,7 @@ }, "devDependencies": { "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "@sentry/browser": "latest || *", "webpack": "^5.91.0", "terser-webpack-plugin": "^5.3.10", diff --git a/dev-packages/e2e-tests/test-applications/webpack-5/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/webpack-5/playwright.config.mjs new file mode 100644 index 000000000000..4248d8d94297 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/webpack-5/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: 'pnpm start', +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/webpack-5/playwright.config.ts b/dev-packages/e2e-tests/test-applications/webpack-5/playwright.config.ts deleted file mode 100644 index 5f93f826ebf0..000000000000 --- a/dev-packages/e2e-tests/test-applications/webpack-5/playwright.config.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Opt out of parallel tests on CI. */ - workers: 1, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - // For now we only test Chrome! - // { - // name: 'firefox', - // use: { - // ...devices['Desktop Firefox'], - // }, - // }, - // { - // name: 'webkit', - // use: { - // ...devices['Desktop Safari'], - // }, - // }, - ], - - /* Run your local dev server before starting the tests */ - webServer: { - command: 'pnpm start', - port: 3030, - env: { - PORT: '3030', - }, - }, -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/webpack-5/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/webpack-5/start-event-proxy.mjs new file mode 100644 index 000000000000..8ee10bade2f8 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/webpack-5/start-event-proxy.mjs @@ -0,0 +1,6 @@ +import { startEventProxyServer } from '@sentry-internal/test-utils'; + +startEventProxyServer({ + port: 3031, + proxyServerName: 'webpack-5', +}); diff --git a/dev-packages/e2e-tests/test-applications/webpack-5/tests/behaviour-test.spec.ts b/dev-packages/e2e-tests/test-applications/webpack-5/tests/behaviour-test.spec.ts deleted file mode 100644 index 7b824ef26579..000000000000 --- a/dev-packages/e2e-tests/test-applications/webpack-5/tests/behaviour-test.spec.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { expect, test } from '@playwright/test'; - -const EVENT_POLLING_TIMEOUT = 90_000; - -const authToken = process.env.E2E_TEST_AUTH_TOKEN; -const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; - -test('Sends an exception to Sentry', async ({ page }) => { - await page.goto('/'); - - const exceptionIdHandle = await page.waitForFunction(() => window.capturedExceptionId); - const exceptionEventId = await exceptionIdHandle.jsonValue(); - - console.log(`Polling for error eventId: ${exceptionEventId}`); - - await expect - .poll( - async () => { - const response = await fetch( - `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${exceptionEventId}/`, - { headers: { Authorization: `Bearer ${authToken}` } }, - ); - return response.status; - }, - { - timeout: EVENT_POLLING_TIMEOUT, - }, - ) - .toBe(200); -}); diff --git a/dev-packages/e2e-tests/test-applications/webpack-5/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/webpack-5/tests/errors.test.ts new file mode 100644 index 000000000000..c899613aafc2 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/webpack-5/tests/errors.test.ts @@ -0,0 +1,14 @@ +import { expect, test } from '@playwright/test'; +import { waitForError } from '@sentry-internal/test-utils'; + +test('Captures an exception', async ({ page }) => { + const eventPromise = waitForError('webpack-5', event => { + return event.exception?.values?.[0].value === 'I am an error!'; + }); + await page.goto('/'); + + const errorEvent = await eventPromise; + + expect(errorEvent.exception?.values?.[0].value).toBe('I am an error!'); + expect(errorEvent.transaction).toBe('/'); +}); From 2cb52152ff726ff1129d9e238e7be9e7872ecfec Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Fri, 31 May 2024 14:32:04 +0200 Subject: [PATCH 10/41] fix(replay): Avoid infinite loop of logs (#12309) When using `_experiments.traceInternals`, this could lead to an infinite loop, as we run this check when a breadcrumb is added, and we add this breadcrumb in the check, ... Fixes https://github.com/getsentry/sentry-javascript/issues/12283 --- packages/replay-internal/src/util/addEvent.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/replay-internal/src/util/addEvent.ts b/packages/replay-internal/src/util/addEvent.ts index 893c6b7d01a4..b2a011687428 100644 --- a/packages/replay-internal/src/util/addEvent.ts +++ b/packages/replay-internal/src/util/addEvent.ts @@ -5,7 +5,7 @@ import { logger } from '@sentry/utils'; import { DEBUG_BUILD } from '../debug-build'; import { EventBufferSizeExceededError } from '../eventBuffer/error'; import type { AddEventResult, RecordingEvent, ReplayContainer, ReplayFrameEvent, ReplayPluginOptions } from '../types'; -import { logInfo } from './log'; +import { logInfoNextTick } from './log'; import { timestampToMs } from './timestamp'; function isCustomEvent(event: RecordingEvent): event is ReplayFrameEvent { @@ -109,7 +109,7 @@ export function shouldAddEvent(replay: ReplayContainer, event: RecordingEvent): // Throw out events that are +60min from the initial timestamp if (timestampInMs > replay.getContext().initialTimestamp + replay.getOptions().maxReplayDuration) { - logInfo( + logInfoNextTick( `[Replay] Skipping event with timestamp ${timestampInMs} because it is after maxReplayDuration`, replay.getOptions()._experiments.traceInternals, ); From 66a8cf99c36b2610110d7723ba94c9cf5ab68b6b Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Fri, 31 May 2024 14:53:50 +0200 Subject: [PATCH 11/41] test(e2e): Streamline react-router-6-use-routes test (#12315) Part of https://github.com/getsentry/sentry-javascript/issues/11910 - we already have error & transaction tests there, so we can just delete the sending tests. --- .../react-router-6-use-routes/package.json | 8 +- .../tests/behaviour-test.test.ts | 200 ------------------ 2 files changed, 1 insertion(+), 207 deletions(-) delete mode 100644 dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/behaviour-test.test.ts diff --git a/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/package.json b/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/package.json index 3ce8af8b1d59..540f16e84a21 100644 --- a/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/package.json +++ b/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/package.json @@ -4,19 +4,13 @@ "private": true, "dependencies": { "@sentry/react": "latest || *", - "@testing-library/jest-dom": "5.14.1", - "@testing-library/react": "13.0.0", - "@testing-library/user-event": "13.2.1", - "@types/jest": "27.0.1", - "@types/node": "16.7.13", "@types/react": "18.0.0", "@types/react-dom": "18.0.0", "react": "18.2.0", "react-dom": "18.2.0", "react-router-dom": "^6.4.1", "react-scripts": "5.0.1", - "typescript": "4.9.5", - "web-vitals": "2.1.0" + "typescript": "4.9.5" }, "scripts": { "build": "react-scripts build", diff --git a/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/behaviour-test.test.ts b/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/behaviour-test.test.ts deleted file mode 100644 index eaf790f99ceb..000000000000 --- a/dev-packages/e2e-tests/test-applications/react-router-6-use-routes/tests/behaviour-test.test.ts +++ /dev/null @@ -1,200 +0,0 @@ -import { expect, test } from '@playwright/test'; -import { ReplayRecordingData } from './fixtures/ReplayRecordingData'; - -const EVENT_POLLING_TIMEOUT = 90_000; - -const authToken = process.env.E2E_TEST_AUTH_TOKEN; -const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; - -test('Sends an exception to Sentry', async ({ page }) => { - await page.goto('/'); - - const exceptionButton = page.locator('id=exception-button'); - await exceptionButton.click(); - - const exceptionIdHandle = await page.waitForFunction(() => window.capturedExceptionId); - const exceptionEventId = await exceptionIdHandle.jsonValue(); - - console.log(`Polling for error eventId: ${exceptionEventId}`); - - await expect - .poll( - async () => { - const response = await fetch( - `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${exceptionEventId}/`, - { headers: { Authorization: `Bearer ${authToken}` } }, - ); - return response.status; - }, - { - timeout: EVENT_POLLING_TIMEOUT, - }, - ) - .toBe(200); -}); - -test('Sends a pageload transaction to Sentry', async ({ page }) => { - await page.goto('/'); - - const recordedTransactionsHandle = await page.waitForFunction(() => { - if (window.recordedTransactions && window.recordedTransactions?.length >= 1) { - return window.recordedTransactions; - } else { - return undefined; - } - }); - const recordedTransactionEventIds = await recordedTransactionsHandle.jsonValue(); - - if (recordedTransactionEventIds === undefined) { - throw new Error("Application didn't record any transaction event IDs."); - } - - let hadPageLoadTransaction = false; - - console.log(`Polling for transaction eventIds: ${JSON.stringify(recordedTransactionEventIds)}`); - - await Promise.all( - recordedTransactionEventIds.map(async transactionEventId => { - await expect - .poll( - async () => { - const response = await fetch( - `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${transactionEventId}/`, - { headers: { Authorization: `Bearer ${authToken}` } }, - ); - - if (response.ok) { - const data = await response.json(); - if (data.contexts.trace.op === 'pageload') { - hadPageLoadTransaction = true; - } - } - - return response.status; - }, - { - timeout: EVENT_POLLING_TIMEOUT, - }, - ) - .toBe(200); - }), - ); - - expect(hadPageLoadTransaction).toBe(true); -}); - -test('Sends a navigation transaction to Sentry', async ({ page }) => { - await page.goto('/'); - - // Give pageload transaction time to finish - await page.waitForTimeout(4000); - - const linkElement = page.locator('id=navigation'); - await linkElement.click(); - - const recordedTransactionsHandle = await page.waitForFunction(() => { - if (window.recordedTransactions && window.recordedTransactions?.length >= 2) { - return window.recordedTransactions; - } else { - return undefined; - } - }); - const recordedTransactionEventIds = await recordedTransactionsHandle.jsonValue(); - - if (recordedTransactionEventIds === undefined) { - throw new Error("Application didn't record any transaction event IDs."); - } - - let hadPageNavigationTransaction = false; - - console.log(`Polling for transaction eventIds: ${JSON.stringify(recordedTransactionEventIds)}`); - - await Promise.all( - recordedTransactionEventIds.map(async transactionEventId => { - await expect - .poll( - async () => { - const response = await fetch( - `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${transactionEventId}/`, - { headers: { Authorization: `Bearer ${authToken}` } }, - ); - - if (response.ok) { - const data = await response.json(); - if (data.contexts.trace.op === 'navigation') { - hadPageNavigationTransaction = true; - } - } - - return response.status; - }, - { - timeout: EVENT_POLLING_TIMEOUT, - }, - ) - .toBe(200); - }), - ); - - expect(hadPageNavigationTransaction).toBe(true); -}); - -test('Sends a Replay recording to Sentry', async ({ browser }) => { - const context = await browser.newContext(); - const page = await context.newPage(); - - await page.goto('/'); - - const replayId = await page.waitForFunction(() => { - return window.sentryReplayId; - }); - - // Keypress event ensures LCP is finished - await page.type('body', 'Y'); - - // Wait for replay to be sent - - if (replayId === undefined) { - throw new Error("Application didn't set a replayId"); - } - - console.log(`Polling for replay with ID: ${replayId}`); - - await expect - .poll( - async () => { - const response = await fetch( - `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/replays/${replayId}/`, - { headers: { Authorization: `Bearer ${authToken}` } }, - ); - return response.status; - }, - { - timeout: EVENT_POLLING_TIMEOUT, - }, - ) - .toBe(200); - - // now fetch the first recording segment - await expect - .poll( - async () => { - const response = await fetch( - `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/replays/${replayId}/recording-segments/?cursor=100%3A0%3A1`, - { headers: { Authorization: `Bearer ${authToken}` } }, - ); - - if (response.ok) { - const data = await response.json(); - return data[0]; - } - - return response.status; - }, - { - timeout: EVENT_POLLING_TIMEOUT, - }, - ) - .toEqual(ReplayRecordingData); -}); From 18803166b2ceb5ac24c3c5576117c5cd526e1c5e Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Fri, 31 May 2024 15:05:34 +0200 Subject: [PATCH 12/41] test(e2e): Update `react-router-6` test to avoid sending to Sentry (#12313) Part of https://github.com/getsentry/sentry-javascript/issues/11910 I renamed `standard-frontend-react` to `react-router-6` as this is more descriptive (what does standard frontend even mean?). This test now also uses the event proxy. --- .github/workflows/build.yml | 6 +- .github/workflows/canary.yml | 4 +- .../.gitignore | 0 .../.npmrc | 0 .../package.json | 11 +- .../react-router-6/playwright.config.mjs | 7 + .../public/index.html | 0 .../src/globals.d.ts | 0 .../src/index.tsx | 15 +- .../src/pages/Index.tsx | 4 +- .../src/pages/User.tsx | 0 .../src/react-app-env.d.ts | 0 .../react-router-6/start-event-proxy.mjs | 6 + .../react-router-6/tests/errors.test.ts | 59 ++++++++ .../react-router-6/tests/transactions.test.ts | 56 +++++++ .../tsconfig.json | 0 .../playwright.config.ts | 70 --------- .../tests/behaviour-test.spec.ts | 140 ------------------ 18 files changed, 138 insertions(+), 240 deletions(-) rename dev-packages/e2e-tests/test-applications/{standard-frontend-react => react-router-6}/.gitignore (100%) rename dev-packages/e2e-tests/test-applications/{standard-frontend-react => react-router-6}/.npmrc (100%) rename dev-packages/e2e-tests/test-applications/{standard-frontend-react => react-router-6}/package.json (81%) create mode 100644 dev-packages/e2e-tests/test-applications/react-router-6/playwright.config.mjs rename dev-packages/e2e-tests/test-applications/{standard-frontend-react => react-router-6}/public/index.html (100%) rename dev-packages/e2e-tests/test-applications/{standard-frontend-react => react-router-6}/src/globals.d.ts (100%) rename dev-packages/e2e-tests/test-applications/{standard-frontend-react => react-router-6}/src/index.tsx (77%) rename dev-packages/e2e-tests/test-applications/{standard-frontend-react => react-router-6}/src/pages/Index.tsx (72%) rename dev-packages/e2e-tests/test-applications/{standard-frontend-react => react-router-6}/src/pages/User.tsx (100%) rename dev-packages/e2e-tests/test-applications/{standard-frontend-react => react-router-6}/src/react-app-env.d.ts (100%) create mode 100644 dev-packages/e2e-tests/test-applications/react-router-6/start-event-proxy.mjs create mode 100644 dev-packages/e2e-tests/test-applications/react-router-6/tests/errors.test.ts create mode 100644 dev-packages/e2e-tests/test-applications/react-router-6/tests/transactions.test.ts rename dev-packages/e2e-tests/test-applications/{standard-frontend-react => react-router-6}/tsconfig.json (100%) delete mode 100644 dev-packages/e2e-tests/test-applications/standard-frontend-react/playwright.config.ts delete mode 100644 dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/behaviour-test.spec.ts diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6c2974d4313e..bd63ed8d46b5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1012,7 +1012,7 @@ jobs: 'react-create-hash-router', 'react-router-6-use-routes', 'react-router-5', - 'standard-frontend-react', + 'react-router-6', 'svelte-5', 'sveltekit', 'sveltekit-2', @@ -1039,9 +1039,9 @@ jobs: - test-application: 'create-react-app' build-command: 'test:build-ts3.8' label: 'create-react-app (TS 3.8)' - - test-application: 'standard-frontend-react' + - test-application: 'react-router-6' build-command: 'test:build-ts3.8' - label: 'standard-frontend-react (TS 3.8)' + label: 'react-router-6 (TS 3.8)' - test-application: 'create-next-app' build-command: 'test:build-13' label: 'create-next-app (next@13)' diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index 152cb275ad13..5d2214a850ca 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -92,9 +92,9 @@ jobs: - test-application: 'react-create-hash-router' build-command: 'test:build-canary' label: 'react-create-hash-router (canary)' - - test-application: 'standard-frontend-react' + - test-application: 'react-router-6' build-command: 'test:build-canary' - label: 'standard-frontend-react (canary)' + label: 'react-router-6 (canary)' steps: - name: Check out current commit diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/.gitignore b/dev-packages/e2e-tests/test-applications/react-router-6/.gitignore similarity index 100% rename from dev-packages/e2e-tests/test-applications/standard-frontend-react/.gitignore rename to dev-packages/e2e-tests/test-applications/react-router-6/.gitignore diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/.npmrc b/dev-packages/e2e-tests/test-applications/react-router-6/.npmrc similarity index 100% rename from dev-packages/e2e-tests/test-applications/standard-frontend-react/.npmrc rename to dev-packages/e2e-tests/test-applications/react-router-6/.npmrc diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/package.json b/dev-packages/e2e-tests/test-applications/react-router-6/package.json similarity index 81% rename from dev-packages/e2e-tests/test-applications/standard-frontend-react/package.json rename to dev-packages/e2e-tests/test-applications/react-router-6/package.json index bf1cd59a0a77..3053b0a7c137 100644 --- a/dev-packages/e2e-tests/test-applications/standard-frontend-react/package.json +++ b/dev-packages/e2e-tests/test-applications/react-router-6/package.json @@ -1,22 +1,16 @@ { - "name": "standard-frontend-react-test", + "name": "react-router-6-test", "version": "0.1.0", "private": true, "dependencies": { "@sentry/react": "latest || *", - "@testing-library/jest-dom": "5.14.1", - "@testing-library/react": "13.0.0", - "@testing-library/user-event": "13.2.1", - "@types/jest": "27.0.1", - "@types/node": "16.7.13", "@types/react": "18.0.0", "@types/react-dom": "18.0.0", "react": "18.2.0", "react-dom": "18.2.0", "react-router-dom": "^6.4.1", "react-scripts": "5.0.1", - "typescript": "4.9.5", - "web-vitals": "2.1.0" + "typescript": "4.9.5" }, "scripts": { "build": "react-scripts build", @@ -48,6 +42,7 @@ }, "devDependencies": { "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", "serve": "14.0.1" }, "volta": { diff --git a/dev-packages/e2e-tests/test-applications/react-router-6/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/react-router-6/playwright.config.mjs new file mode 100644 index 000000000000..31f2b913b58b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/react-router-6/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/public/index.html b/dev-packages/e2e-tests/test-applications/react-router-6/public/index.html similarity index 100% rename from dev-packages/e2e-tests/test-applications/standard-frontend-react/public/index.html rename to dev-packages/e2e-tests/test-applications/react-router-6/public/index.html diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/src/globals.d.ts b/dev-packages/e2e-tests/test-applications/react-router-6/src/globals.d.ts similarity index 100% rename from dev-packages/e2e-tests/test-applications/standard-frontend-react/src/globals.d.ts rename to dev-packages/e2e-tests/test-applications/react-router-6/src/globals.d.ts diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/src/index.tsx b/dev-packages/e2e-tests/test-applications/react-router-6/src/index.tsx similarity index 77% rename from dev-packages/e2e-tests/test-applications/standard-frontend-react/src/index.tsx rename to dev-packages/e2e-tests/test-applications/react-router-6/src/index.tsx index 5980df0ff8dd..601ac10a084b 100644 --- a/dev-packages/e2e-tests/test-applications/standard-frontend-react/src/index.tsx +++ b/dev-packages/e2e-tests/test-applications/react-router-6/src/index.tsx @@ -36,21 +36,8 @@ Sentry.init({ // Always capture replays, so we can test this properly replaysSessionSampleRate: 1.0, replaysOnErrorSampleRate: 0.0, -}); - -Sentry.addEventProcessor(event => { - if ( - event.type === 'transaction' && - (event.contexts?.trace?.op === 'pageload' || event.contexts?.trace?.op === 'navigation') - ) { - const eventId = event.event_id; - if (eventId) { - window.recordedTransactions = window.recordedTransactions || []; - window.recordedTransactions.push(eventId); - } - } - return event; + tunnel: 'http://localhost:3031', }); const SentryRoutes = Sentry.withSentryReactRouterV6Routing(Routes); diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/src/pages/Index.tsx b/dev-packages/e2e-tests/test-applications/react-router-6/src/pages/Index.tsx similarity index 72% rename from dev-packages/e2e-tests/test-applications/standard-frontend-react/src/pages/Index.tsx rename to dev-packages/e2e-tests/test-applications/react-router-6/src/pages/Index.tsx index 7789a2773224..d6b71a1d1279 100644 --- a/dev-packages/e2e-tests/test-applications/standard-frontend-react/src/pages/Index.tsx +++ b/dev-packages/e2e-tests/test-applications/react-router-6/src/pages/Index.tsx @@ -1,4 +1,3 @@ -import * as Sentry from '@sentry/react'; // biome-ignore lint/nursery/noUnusedImports: Need React import for JSX import * as React from 'react'; import { Link } from 'react-router-dom'; @@ -11,8 +10,7 @@ const Index = () => { value="Capture Exception" id="exception-button" onClick={() => { - const eventId = Sentry.captureException(new Error('I am an error!')); - window.capturedExceptionId = eventId; + throw new Error('I am an error!'); }} /> diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/src/pages/User.tsx b/dev-packages/e2e-tests/test-applications/react-router-6/src/pages/User.tsx similarity index 100% rename from dev-packages/e2e-tests/test-applications/standard-frontend-react/src/pages/User.tsx rename to dev-packages/e2e-tests/test-applications/react-router-6/src/pages/User.tsx diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/src/react-app-env.d.ts b/dev-packages/e2e-tests/test-applications/react-router-6/src/react-app-env.d.ts similarity index 100% rename from dev-packages/e2e-tests/test-applications/standard-frontend-react/src/react-app-env.d.ts rename to dev-packages/e2e-tests/test-applications/react-router-6/src/react-app-env.d.ts diff --git a/dev-packages/e2e-tests/test-applications/react-router-6/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/react-router-6/start-event-proxy.mjs new file mode 100644 index 000000000000..5f4dfa2d0d9f --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/react-router-6/start-event-proxy.mjs @@ -0,0 +1,6 @@ +import { startEventProxyServer } from '@sentry-internal/test-utils'; + +startEventProxyServer({ + port: 3031, + proxyServerName: 'react-router-6', +}); diff --git a/dev-packages/e2e-tests/test-applications/react-router-6/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/react-router-6/tests/errors.test.ts new file mode 100644 index 000000000000..8ffbfcae282a --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/react-router-6/tests/errors.test.ts @@ -0,0 +1,59 @@ +import { expect, test } from '@playwright/test'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; + +test('Sends correct error event', async ({ page }) => { + const errorEventPromise = waitForError('react-router-6', event => { + return !event.type && event.exception?.values?.[0]?.value === 'I am an error!'; + }); + + await page.goto('/'); + + const exceptionButton = page.locator('id=exception-button'); + await exceptionButton.click(); + + const errorEvent = await errorEventPromise; + + expect(errorEvent.exception?.values).toHaveLength(1); + expect(errorEvent.exception?.values?.[0]?.value).toBe('I am an error!'); + + expect(errorEvent.request).toEqual({ + headers: expect.any(Object), + url: 'http://localhost:3030/', + }); + + expect(errorEvent.transaction).toEqual('/'); + + expect(errorEvent.contexts?.trace).toEqual({ + trace_id: expect.any(String), + span_id: expect.any(String), + }); +}); + +test('Sets correct transactionName', async ({ page }) => { + const transactionPromise = waitForTransaction('react-router-6', async transactionEvent => { + return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload'; + }); + + const errorEventPromise = waitForError('react-router-6', event => { + return !event.type && event.exception?.values?.[0]?.value === 'I am an error!'; + }); + + await page.goto('/'); + const transactionEvent = await transactionPromise; + + // Only capture error once transaction was sent + const exceptionButton = page.locator('id=exception-button'); + await exceptionButton.click(); + + const errorEvent = await errorEventPromise; + + expect(errorEvent.exception?.values).toHaveLength(1); + expect(errorEvent.exception?.values?.[0]?.value).toBe('I am an error!'); + + expect(errorEvent.transaction).toEqual('/'); + + expect(errorEvent.contexts?.trace).toEqual({ + trace_id: transactionEvent.contexts?.trace?.trace_id, + span_id: expect.not.stringContaining(transactionEvent.contexts?.trace?.span_id || ''), + }); +}); diff --git a/dev-packages/e2e-tests/test-applications/react-router-6/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/react-router-6/tests/transactions.test.ts new file mode 100644 index 000000000000..c554c47d8dde --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/react-router-6/tests/transactions.test.ts @@ -0,0 +1,56 @@ +import { expect, test } from '@playwright/test'; +import { waitForTransaction } from '@sentry-internal/test-utils'; + +test('sends a pageload transaction with a parameterized URL', async ({ page }) => { + const transactionPromise = waitForTransaction('react-router-6', async transactionEvent => { + return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload'; + }); + + await page.goto(`/`); + + const rootSpan = await transactionPromise; + + expect(rootSpan).toMatchObject({ + contexts: { + trace: { + op: 'pageload', + origin: 'auto.pageload.react.reactrouter_v6', + }, + }, + transaction: '/', + transaction_info: { + source: 'route', + }, + }); +}); + +test('sends a navigation transaction with a parameterized URL', async ({ page }) => { + page.on('console', msg => console.log(msg.text())); + const pageloadTxnPromise = waitForTransaction('react-router-6', async transactionEvent => { + return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload'; + }); + + const navigationTxnPromise = waitForTransaction('react-router-6', async transactionEvent => { + return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'navigation'; + }); + + await page.goto(`/`); + await pageloadTxnPromise; + + const linkElement = page.locator('id=navigation'); + + const [_, navigationTxn] = await Promise.all([linkElement.click(), navigationTxnPromise]); + + expect(navigationTxn).toMatchObject({ + contexts: { + trace: { + op: 'navigation', + origin: 'auto.navigation.react.reactrouter_v6', + }, + }, + transaction: '/user/:id', + transaction_info: { + source: 'route', + }, + }); +}); diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/tsconfig.json b/dev-packages/e2e-tests/test-applications/react-router-6/tsconfig.json similarity index 100% rename from dev-packages/e2e-tests/test-applications/standard-frontend-react/tsconfig.json rename to dev-packages/e2e-tests/test-applications/react-router-6/tsconfig.json diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/playwright.config.ts b/dev-packages/e2e-tests/test-applications/standard-frontend-react/playwright.config.ts deleted file mode 100644 index 5f93f826ebf0..000000000000 --- a/dev-packages/e2e-tests/test-applications/standard-frontend-react/playwright.config.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { PlaywrightTestConfig } from '@playwright/test'; -import { devices } from '@playwright/test'; - -/** - * See https://playwright.dev/docs/test-configuration. - */ -const config: PlaywrightTestConfig = { - testDir: './tests', - /* Maximum time one test can run for. */ - timeout: 150_000, - expect: { - /** - * Maximum time expect() should wait for the condition to be met. - * For example in `await expect(locator).toHaveText();` - */ - timeout: 5000, - }, - /* Run tests in files in parallel */ - fullyParallel: true, - /* Fail the build on CI if you accidentally left test.only in the source code. */ - forbidOnly: !!process.env.CI, - /* Retry on CI only */ - retries: 0, - /* Opt out of parallel tests on CI. */ - workers: 1, - /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'list', - /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ - use: { - /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ - actionTimeout: 0, - - /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - trace: 'on-first-retry', - }, - - /* Configure projects for major browsers */ - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - }, - }, - // For now we only test Chrome! - // { - // name: 'firefox', - // use: { - // ...devices['Desktop Firefox'], - // }, - // }, - // { - // name: 'webkit', - // use: { - // ...devices['Desktop Safari'], - // }, - // }, - ], - - /* Run your local dev server before starting the tests */ - webServer: { - command: 'pnpm start', - port: 3030, - env: { - PORT: '3030', - }, - }, -}; - -export default config; diff --git a/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/behaviour-test.spec.ts b/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/behaviour-test.spec.ts deleted file mode 100644 index 5e9b5ed0cdd6..000000000000 --- a/dev-packages/e2e-tests/test-applications/standard-frontend-react/tests/behaviour-test.spec.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { expect, test } from '@playwright/test'; - -const EVENT_POLLING_TIMEOUT = 90_000; - -const authToken = process.env.E2E_TEST_AUTH_TOKEN; -const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; -const sentryTestProject = process.env.E2E_TEST_SENTRY_PROJECT; - -test('Sends an exception to Sentry', async ({ page }) => { - await page.goto('/'); - - const exceptionButton = page.locator('id=exception-button'); - await exceptionButton.click(); - - const exceptionIdHandle = await page.waitForFunction(() => window.capturedExceptionId); - const exceptionEventId = await exceptionIdHandle.jsonValue(); - - console.log(`Polling for error eventId: ${exceptionEventId}`); - - await expect - .poll( - async () => { - const response = await fetch( - `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${exceptionEventId}/`, - { headers: { Authorization: `Bearer ${authToken}` } }, - ); - return response.status; - }, - { - timeout: EVENT_POLLING_TIMEOUT, - }, - ) - .toBe(200); -}); - -test('Sends a pageload transaction to Sentry', async ({ page }) => { - await page.goto('/'); - - const recordedTransactionsHandle = await page.waitForFunction(() => { - if (window.recordedTransactions && window.recordedTransactions?.length >= 1) { - return window.recordedTransactions; - } else { - return undefined; - } - }); - const recordedTransactionEventIds = await recordedTransactionsHandle.jsonValue(); - - if (recordedTransactionEventIds === undefined) { - throw new Error("Application didn't record any transaction event IDs."); - } - - let hadPageLoadTransaction = false; - - console.log(`Polling for transaction eventIds: ${JSON.stringify(recordedTransactionEventIds)}`); - - await Promise.all( - recordedTransactionEventIds.map(async transactionEventId => { - await expect - .poll( - async () => { - const response = await fetch( - `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${transactionEventId}/`, - { headers: { Authorization: `Bearer ${authToken}` } }, - ); - - if (response.ok) { - const data = await response.json(); - if (data.contexts.trace.op === 'pageload') { - hadPageLoadTransaction = true; - } - } - - return response.status; - }, - { - timeout: EVENT_POLLING_TIMEOUT, - }, - ) - .toBe(200); - }), - ); - - expect(hadPageLoadTransaction).toBe(true); -}); - -test('Sends a navigation transaction to Sentry', async ({ page }) => { - await page.goto('/'); - - // Give pageload transaction time to finish - await page.waitForTimeout(4000); - - const linkElement = page.locator('id=navigation'); - await linkElement.click(); - - const recordedTransactionsHandle = await page.waitForFunction(() => { - if (window.recordedTransactions && window.recordedTransactions?.length >= 2) { - return window.recordedTransactions; - } else { - return undefined; - } - }); - const recordedTransactionEventIds = await recordedTransactionsHandle.jsonValue(); - - if (recordedTransactionEventIds === undefined) { - throw new Error("Application didn't record any transaction event IDs."); - } - - let hadPageNavigationTransaction = false; - - console.log(`Polling for transaction eventIds: ${JSON.stringify(recordedTransactionEventIds)}`); - - await Promise.all( - recordedTransactionEventIds.map(async transactionEventId => { - await expect - .poll( - async () => { - const response = await fetch( - `https://sentry.io/api/0/projects/${sentryTestOrgSlug}/${sentryTestProject}/events/${transactionEventId}/`, - { headers: { Authorization: `Bearer ${authToken}` } }, - ); - - if (response.ok) { - const data = await response.json(); - if (data.contexts.trace.op === 'navigation') { - hadPageNavigationTransaction = true; - } - } - - return response.status; - }, - { - timeout: EVENT_POLLING_TIMEOUT, - }, - ) - .toBe(200); - }), - ); - - expect(hadPageNavigationTransaction).toBe(true); -}); From 0ec8f8259917510962f12eb005585ca2a74ef31d Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Fri, 31 May 2024 15:41:21 +0200 Subject: [PATCH 13/41] test(aws-lambda): Add basic lambda layer e2e test (#12279) Add an e2e (or rather integration) test for our AWS lambda layer bundle. The motivation for this test is that we broke the layer during the initial v8 releases (multiple times for different reasons) without us noticing this in tests. Simply because we never tested the bundled SDK code that we create and publish for the lambda layer. --- .github/workflows/build.yml | 1 + .../test-applications/aws-lambda-layer/.npmrc | 2 + .../aws-lambda-layer/package.json | 23 ++++++ .../aws-lambda-layer/playwright.config.ts | 79 +++++++++++++++++++ .../aws-lambda-layer/src/lambda-function.js | 19 +++++ .../aws-lambda-layer/src/run-lambda.js | 2 + .../aws-lambda-layer/src/run.js | 16 ++++ .../aws-lambda-layer/start-event-proxy.mjs | 7 ++ .../aws-lambda-layer/tests/basic.test.ts | 36 +++++++++ .../test-utils/src/event-proxy-server.ts | 38 ++++++++- packages/aws-serverless/package.json | 5 +- 11 files changed, 222 insertions(+), 6 deletions(-) create mode 100644 dev-packages/e2e-tests/test-applications/aws-lambda-layer/.npmrc create mode 100644 dev-packages/e2e-tests/test-applications/aws-lambda-layer/package.json create mode 100644 dev-packages/e2e-tests/test-applications/aws-lambda-layer/playwright.config.ts create mode 100644 dev-packages/e2e-tests/test-applications/aws-lambda-layer/src/lambda-function.js create mode 100644 dev-packages/e2e-tests/test-applications/aws-lambda-layer/src/run-lambda.js create mode 100644 dev-packages/e2e-tests/test-applications/aws-lambda-layer/src/run.js create mode 100644 dev-packages/e2e-tests/test-applications/aws-lambda-layer/start-event-proxy.mjs create mode 100644 dev-packages/e2e-tests/test-applications/aws-lambda-layer/tests/basic.test.ts diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bd63ed8d46b5..2180ddbf3b9b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -993,6 +993,7 @@ jobs: [ 'angular-17', 'angular-18', + 'aws-lambda-layer', 'cloudflare-astro', 'node-express', 'create-react-app', diff --git a/dev-packages/e2e-tests/test-applications/aws-lambda-layer/.npmrc b/dev-packages/e2e-tests/test-applications/aws-lambda-layer/.npmrc new file mode 100644 index 000000000000..070f80f05092 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/aws-lambda-layer/.npmrc @@ -0,0 +1,2 @@ +@sentry:registry=http://127.0.0.1:4873 +@sentry-internal:registry=http://127.0.0.1:4873 diff --git a/dev-packages/e2e-tests/test-applications/aws-lambda-layer/package.json b/dev-packages/e2e-tests/test-applications/aws-lambda-layer/package.json new file mode 100644 index 000000000000..4d41ba051e4b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/aws-lambda-layer/package.json @@ -0,0 +1,23 @@ +{ + "name": "node-express-app", + "version": "1.0.0", + "private": true, + "scripts": { + "copy:layer": "cp -r ./../../../../packages/aws-serverless/build/aws/dist-serverless/nodejs/node_modules/ ./node_modules", + "start": "node src/run.js", + "test": "playwright test", + "clean": "npx rimraf node_modules pnpm-lock.yaml", + "test:build": "pnpm install && pnpm copy:layer", + "test:assert": "pnpm test" + }, + "dependencies": { + }, + "devDependencies": { + "@sentry-internal/test-utils": "link:../../../test-utils", + "@playwright/test": "^1.41.1", + "wait-port": "1.0.4" + }, + "volta": { + "extends": "../../package.json" + } +} diff --git a/dev-packages/e2e-tests/test-applications/aws-lambda-layer/playwright.config.ts b/dev-packages/e2e-tests/test-applications/aws-lambda-layer/playwright.config.ts new file mode 100644 index 000000000000..7b14daadc6d1 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/aws-lambda-layer/playwright.config.ts @@ -0,0 +1,79 @@ +import type { PlaywrightTestConfig } from '@playwright/test'; +import { devices } from '@playwright/test'; + +// Fix urls not resolving to localhost on Node v17+ +// See: https://github.com/axios/axios/issues/3821#issuecomment-1413727575 +import { setDefaultResultOrder } from 'dns'; +setDefaultResultOrder('ipv4first'); + +const eventProxyPort = 3031; +const lambdaPort = 3030; + +/** + * See https://playwright.dev/docs/test-configuration. + */ +const config: PlaywrightTestConfig = { + testDir: './tests', + /* Maximum time one test can run for. */ + timeout: 150_000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000, + }, + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: 0, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'list', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: `http://localhost:${lambdaPort}`, + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + }, + }, + // For now we only test Chrome! + // { + // name: 'firefox', + // use: { + // ...devices['Desktop Firefox'], + // }, + // }, + // { + // name: 'webkit', + // use: { + // ...devices['Desktop Safari'], + // }, + // }, + ], + + /* Run your local dev server before starting the tests */ + webServer: [ + { + command: `node start-event-proxy.mjs && pnpm wait-port ${eventProxyPort}`, + port: eventProxyPort, + stdout: 'pipe', + }, + ], +}; + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/aws-lambda-layer/src/lambda-function.js b/dev-packages/e2e-tests/test-applications/aws-lambda-layer/src/lambda-function.js new file mode 100644 index 000000000000..aa8f236b742d --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/aws-lambda-layer/src/lambda-function.js @@ -0,0 +1,19 @@ +const Sentry = require('@sentry/aws-serverless'); + +const http = require('http'); + +function handle() { + Sentry.startSpanManual({ name: 'aws-lambda-layer-test-txn', op: 'test' }, span => { + http.get('http://example.com', res => { + res.on('data', d => { + process.stdout.write(d); + }); + + res.on('end', () => { + span.end(); + }); + }); + }); +} + +module.exports = { handle }; diff --git a/dev-packages/e2e-tests/test-applications/aws-lambda-layer/src/run-lambda.js b/dev-packages/e2e-tests/test-applications/aws-lambda-layer/src/run-lambda.js new file mode 100644 index 000000000000..5e573c484637 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/aws-lambda-layer/src/run-lambda.js @@ -0,0 +1,2 @@ +const { handle } = require('./lambda-function'); +handle(); diff --git a/dev-packages/e2e-tests/test-applications/aws-lambda-layer/src/run.js b/dev-packages/e2e-tests/test-applications/aws-lambda-layer/src/run.js new file mode 100644 index 000000000000..2a99cff2d48e --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/aws-lambda-layer/src/run.js @@ -0,0 +1,16 @@ +const child_process = require('child_process'); + +child_process.execSync('node ./src/run-lambda.js', { + stdio: 'inherit', + env: { + ...process.env, + LAMBDA_TASK_ROOT: '.', + _HANDLER: 'handle', + + NODE_OPTIONS: '--require @sentry/aws-serverless/dist/awslambda-auto', + SENTRY_DSN: 'http://public@localhost:3031/1337', + SENTRY_TRACES_SAMPLE_RATE: '1.0', + SENTRY_DEBUG: 'true', + }, + cwd: process.cwd(), +}); diff --git a/dev-packages/e2e-tests/test-applications/aws-lambda-layer/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/aws-lambda-layer/start-event-proxy.mjs new file mode 100644 index 000000000000..e64e99cda75b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/aws-lambda-layer/start-event-proxy.mjs @@ -0,0 +1,7 @@ +import { startEventProxyServer } from '@sentry-internal/test-utils'; + +startEventProxyServer({ + port: 3031, + proxyServerName: 'aws-serverless-lambda-layer', + forwardToSentry: false, +}); diff --git a/dev-packages/e2e-tests/test-applications/aws-lambda-layer/tests/basic.test.ts b/dev-packages/e2e-tests/test-applications/aws-lambda-layer/tests/basic.test.ts new file mode 100644 index 000000000000..7f7f5ec1854c --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/aws-lambda-layer/tests/basic.test.ts @@ -0,0 +1,36 @@ +import * as child_process from 'child_process'; +import { expect, test } from '@playwright/test'; +import { waitForTransaction } from '@sentry-internal/test-utils'; + +test('Lambda layer SDK bundle sends events', async ({ request }) => { + const transactionEventPromise = waitForTransaction('aws-serverless-lambda-layer', transactionEvent => { + return transactionEvent?.transaction === 'aws-lambda-layer-test-txn'; + }); + + await new Promise(resolve => + setTimeout(() => { + resolve(); + }, 1000), + ); + + child_process.execSync('pnpm start', { + stdio: 'ignore', + }); + + const transactionEvent = await transactionEventPromise; + + // shows the SDK sent a transaction + expect(transactionEvent.transaction).toEqual('aws-lambda-layer-test-txn'); + + // shows that the Otel Http instrumentation is working + expect(transactionEvent.spans).toHaveLength(1); + expect(transactionEvent.spans![0]).toMatchObject({ + data: expect.objectContaining({ + 'sentry.op': 'http.client', + 'sentry.origin': 'auto.http.otel.http', + url: 'http://example.com/', + }), + description: 'GET http://example.com/', + op: 'http.client', + }); +}); diff --git a/dev-packages/test-utils/src/event-proxy-server.ts b/dev-packages/test-utils/src/event-proxy-server.ts index bb3eda188176..1274f77062bd 100644 --- a/dev-packages/test-utils/src/event-proxy-server.ts +++ b/dev-packages/test-utils/src/event-proxy-server.ts @@ -17,6 +17,11 @@ interface EventProxyServerOptions { port: number; /** The name for the proxy server used for referencing it with listener functions */ proxyServerName: string; + /** + * Whether or not to forward the event to sentry. @default `true` + * This is helpful when you can't register a tunnel in the SDK setup (e.g. lambda layer without Sentry.init call) + */ + forwardToSentry?: boolean; } interface SentryRequestCallbackData { @@ -56,7 +61,9 @@ export async function startEventProxyServer(options: EventProxyServerOptions): P const envelopeHeader: EnvelopeItem[0] = JSON.parse(proxyRequestBody.split('\n')[0]); - if (!envelopeHeader.dsn) { + const shouldForwardEventToSentry = options.forwardToSentry != null ? options.forwardToSentry : true; + + if (!envelopeHeader.dsn && shouldForwardEventToSentry) { // eslint-disable-next-line no-console console.log( '[event-proxy-server] Warn: No dsn on envelope header. Maybe a client-report was received. Proxy request body:', @@ -69,6 +76,23 @@ export async function startEventProxyServer(options: EventProxyServerOptions): P return; } + if (!shouldForwardEventToSentry) { + const data: SentryRequestCallbackData = { + envelope: parseEnvelope(proxyRequestBody), + rawProxyRequestBody: proxyRequestBody, + rawSentryResponseBody: '', + sentryResponseStatusCode: 200, + }; + eventCallbackListeners.forEach(listener => { + listener(Buffer.from(JSON.stringify(data)).toString('base64')); + }); + + proxyResponse.writeHead(200); + proxyResponse.write('{}', 'utf-8'); + proxyResponse.end(); + return; + } + const { origin, pathname, host } = new URL(envelopeHeader.dsn as string); const projectId = pathname.substring(1); @@ -269,7 +293,13 @@ async function registerCallbackServerPort(serverName: string, port: string): Pro await writeFile(tmpFilePath, port, { encoding: 'utf8' }); } -function retrieveCallbackServerPort(serverName: string): Promise { - const tmpFilePath = path.join(os.tmpdir(), `${TEMP_FILE_PREFIX}${serverName}`); - return readFile(tmpFilePath, 'utf8'); +async function retrieveCallbackServerPort(serverName: string): Promise { + try { + const tmpFilePath = path.join(os.tmpdir(), `${TEMP_FILE_PREFIX}${serverName}`); + return await readFile(tmpFilePath, 'utf8'); + } catch (e) { + // eslint-disable-next-line no-console + console.log('Could not read callback server port', e); + throw e; + } } diff --git a/packages/aws-serverless/package.json b/packages/aws-serverless/package.json index 81c6a0a34c01..765f523b7c5c 100644 --- a/packages/aws-serverless/package.json +++ b/packages/aws-serverless/package.json @@ -76,9 +76,10 @@ }, "scripts": { "build": "run-p build:transpile build:types build:bundle", - "build:bundle": "yarn ts-node scripts/buildLambdaLayer.ts", + "build:bundle": "yarn build:layer", + "build:layer": "yarn ts-node scripts/buildLambdaLayer.ts", "build:dev": "run-p build:transpile build:types", - "build:transpile": "rollup -c rollup.npm.config.mjs", + "build:transpile": "rollup -c rollup.npm.config.mjs && yarn build:layer", "build:types": "run-s build:types:core build:types:downlevel", "build:types:core": "tsc -p tsconfig.types.json", "build:types:downlevel": "yarn downlevel-dts build/npm/types build/npm/types-ts3.8 --to ts3.8", From 9ce85f7a92eed115c33998249bd00663c8ac1ba1 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Fri, 31 May 2024 10:56:56 -0400 Subject: [PATCH 14/41] fix(feedback): Override TriggerLabel Option (#12316) Fixes https://github.com/getsentry/sentry-javascript/issues/12229 --- packages/feedback/src/core/integration.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/feedback/src/core/integration.ts b/packages/feedback/src/core/integration.ts index 652151fa8a89..11609cd35f89 100644 --- a/packages/feedback/src/core/integration.ts +++ b/packages/feedback/src/core/integration.ts @@ -251,10 +251,11 @@ export const buildFeedbackIntegration = ({ }; const _createActor = (optionOverrides: OverrideFeedbackConfiguration = {}): ActorComponent => { - const shadow = _createShadow(_options); - const actor = Actor({ triggerLabel: _options.triggerLabel, shadow }); - const mergedOptions = mergeOptions(_options, { - ...optionOverrides, + const mergedOptions = mergeOptions(_options, optionOverrides); + const shadow = _createShadow(mergedOptions); + const actor = Actor({ triggerLabel: mergedOptions.triggerLabel, shadow }); + _attachTo(actor.el, { + ...mergedOptions, onFormOpen() { actor.hide(); }, @@ -265,7 +266,6 @@ export const buildFeedbackIntegration = ({ actor.show(); }, }); - _attachTo(actor.el, mergedOptions); return actor; }; From 84886c7a03907997eab355ca93421b550fed9486 Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Mon, 3 Jun 2024 14:48:55 +0900 Subject: [PATCH 15/41] fix(nextjs): Fix version detection and option insertion logic for `clientTraceMetadata` option (#12323) Co-authored-by: Luca Forstner --- packages/nextjs/src/config/withSentryConfig.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/nextjs/src/config/withSentryConfig.ts b/packages/nextjs/src/config/withSentryConfig.ts index 32a4a885f9d7..ec9115b4ce3e 100644 --- a/packages/nextjs/src/config/withSentryConfig.ts +++ b/packages/nextjs/src/config/withSentryConfig.ts @@ -89,11 +89,13 @@ function getFinalConfigObject( const nextJsVersion = getNextjsVersion(); if (nextJsVersion) { const { major, minor } = parseSemver(nextJsVersion); - if (major && minor && (major >= 15 || (major === 14 && minor >= 3))) { - incomingUserNextConfigObject.experimental = { - clientTraceMetadata: ['baggage', 'sentry-trace'], - ...incomingUserNextConfigObject.experimental, - }; + if (major !== undefined && minor !== undefined && (major >= 15 || (major === 14 && minor >= 3))) { + incomingUserNextConfigObject.experimental = incomingUserNextConfigObject.experimental || {}; + incomingUserNextConfigObject.experimental.clientTraceMetadata = [ + 'baggage', + 'sentry-trace', + ...(incomingUserNextConfigObject.experimental?.clientTraceMetadata || []), + ]; } } else { // eslint-disable-next-line no-console From 119a923c6d2f57c31f5d0f155db186d5a7806940 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 11:45:29 +0200 Subject: [PATCH 16/41] ci(deps): bump pnpm/action-setup from 2 to 4 (#12320) Bumps [pnpm/action-setup](https://github.com/pnpm/action-setup) from 2 to 4.
Release notes

Sourced from pnpm/action-setup's releases.

v4.0.0

An error is thrown if one version of pnpm is specified in the packageManager field of package.json and a different version is specified in the action's settings #122

v3.0.0

The action is updated to run on Node.js v20

v2.4.0

Add ability to install standalone binary (pnpm/action-setup#92).

v2.3.0

v2.2.4

No deprecation warnings are printed about set-state and set-output commands (pnpm/action-setup#57)

v2.2.3

Bump Node.js version to 16 pnpm/action-setup#56

v2.2.2

Fixing network issues.

Related issues:

Related PR:

v2.2.1

Fix "packageManager" reader pnpm/action-setup#35

v2.2.0

v2.1.0

Support pnpm v7 pnpm/action-setup#29

v2.0.1

Update versions in code examples in README.md to the latest ones to avoid users using the wrong versions.

Commits
  • fe02b34 docs: bump action-setup version in README
  • bee1f09 feat: throw error when multiple versions specified (#122)
  • ce859e3 refactor: replace fs-extra with Node.js built-in fs methods (#120)
  • 2ab6dce docs(README): fix link to LICENSE
  • e280758 docs(README): update dependency versions (#117)
  • 129abb7 Bump undici from 5.28.2 to 5.28.3 (#115)
  • a3252b7 docs(README): update version
  • 1ee9c9d feat!: node20 upgrade (#110)
  • ebcfd69 Bump actions/setup-node from 3 to 4 (#103)
  • d2613e0 docs: update pnpm version in caching example (#94)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pnpm/action-setup&package-manager=github_actions&previous-version=2&new-version=4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 6 +++--- .github/workflows/canary.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2180ddbf3b9b..4396503081a7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1058,7 +1058,7 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ env.HEAD_COMMIT }} - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v4 with: version: 8.3.1 - name: Set up Node @@ -1155,7 +1155,7 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ env.HEAD_COMMIT }} - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v4 with: version: 8.3.1 - name: Set up Node @@ -1234,7 +1234,7 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ env.HEAD_COMMIT }} - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v4 with: version: 8.3.1 - name: Set up Node diff --git a/.github/workflows/canary.yml b/.github/workflows/canary.yml index 5d2214a850ca..a9bd341b15b8 100644 --- a/.github/workflows/canary.yml +++ b/.github/workflows/canary.yml @@ -101,7 +101,7 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ env.HEAD_COMMIT }} - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v4 with: version: 8.3.1 From 5494cb52fc12c552ef04d025b53c3bd6de58b171 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Mon, 3 Jun 2024 15:55:30 +0200 Subject: [PATCH 17/41] ref(browser): Ensure idle span ending is consistent (#12310) --- .../pageloadWithChildSpanTimeout/init.js | 13 ++++++------- .../pageloadWithChildSpanTimeout/test.ts | 1 + packages/core/src/tracing/idleSpan.ts | 8 +++++--- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageloadWithChildSpanTimeout/init.js b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageloadWithChildSpanTimeout/init.js index 98e297d13625..229372e215c7 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageloadWithChildSpanTimeout/init.js +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageloadWithChildSpanTimeout/init.js @@ -15,10 +15,9 @@ Sentry.init({ }); const activeSpan = Sentry.getActiveSpan(); -if (activeSpan) { - Sentry.startInactiveSpan({ name: 'pageload-child-span' }); -} else { - setTimeout(() => { - Sentry.startInactiveSpan({ name: 'pageload-child-span' }); - }, 200); -} +Sentry.startInactiveSpan({ + name: 'pageload-child-span', + onlyIfParent: true, + // Set this to ensure we do not discard this span due to timeout + startTime: activeSpan && Sentry.spanToJSON(activeSpan).start_timestamp, +}); diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageloadWithChildSpanTimeout/test.ts b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageloadWithChildSpanTimeout/test.ts index 5987061c741f..ca342a5533c2 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageloadWithChildSpanTimeout/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageloadWithChildSpanTimeout/test.ts @@ -21,6 +21,7 @@ sentryTest('should send a pageload span terminated via child span timeout', asyn const eventData = envelopeRequestParser(req); expect(eventData.contexts?.trace?.op).toBe('pageload'); + expect(eventData.contexts?.trace?.data?.['sentry.idle_span_discarded_spans']).toBeUndefined(); expect(eventData.spans?.length).toBeGreaterThanOrEqual(1); const testSpan = eventData.spans?.find(span => span.description === 'pageload-child-span'); expect(testSpan).toBeDefined(); diff --git a/packages/core/src/tracing/idleSpan.ts b/packages/core/src/tracing/idleSpan.ts index 8f3ecb7e7d35..67093076f443 100644 --- a/packages/core/src/tracing/idleSpan.ts +++ b/packages/core/src/tracing/idleSpan.ts @@ -121,7 +121,9 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti beforeSpanEnd(span); } - const timestamp = args[0] || timestampInSeconds(); + // Just ensuring that this keeps working, even if we ever have more arguments here + const [definedEndTimestamp, ...rest] = args; + const timestamp = definedEndTimestamp || timestampInSeconds(); const spanEndTimestamp = spanTimeInputToSeconds(timestamp); // Ensure we end with the last span timestamp, if possible @@ -130,7 +132,7 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti // If we have no spans, we just end, nothing else to do here if (!spans.length) { onIdleSpanEnded(spanEndTimestamp); - return Reflect.apply(target, thisArg, args); + return Reflect.apply(target, thisArg, [spanEndTimestamp, ...rest]); } const childEndTimestamps = spans @@ -152,7 +154,7 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti ); onIdleSpanEnded(endTimestamp); - return Reflect.apply(target, thisArg, [endTimestamp]); + return Reflect.apply(target, thisArg, [endTimestamp, ...rest]); }, }); From 10833b00f9288b50eb0baef81131cbc4cfd6e8f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 16:57:20 +0000 Subject: [PATCH 18/41] feat(deps): Bump @sentry/cli from 2.31.2 to 2.32.1 (#12332) --- packages/remix/package.json | 2 +- yarn.lock | 158 +++++++++++++++++++++++------------- 2 files changed, 103 insertions(+), 57 deletions(-) diff --git a/packages/remix/package.json b/packages/remix/package.json index 893553895117..9f058b189110 100644 --- a/packages/remix/package.json +++ b/packages/remix/package.json @@ -58,7 +58,7 @@ }, "dependencies": { "@remix-run/router": "1.x", - "@sentry/cli": "^2.31.2", + "@sentry/cli": "^2.32.1", "@sentry/core": "8.7.0", "@sentry/node": "8.7.0", "@sentry/opentelemetry": "8.7.0", diff --git a/yarn.lock b/yarn.lock index 51f4ec587e73..a32b917d30de 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7117,45 +7117,45 @@ magic-string "0.27.0" unplugin "1.0.1" -"@sentry/cli-darwin@2.31.2": - version "2.31.2" - resolved "https://registry.yarnpkg.com/@sentry/cli-darwin/-/cli-darwin-2.31.2.tgz#faeb87d09d8b21b8b8dd2e2aa848b538f01ddd26" - integrity sha512-BHA/JJXj1dlnoZQdK4efRCtHRnbBfzbIZUKAze7oRR1RfNqERI84BVUQeKateD3jWSJXQfEuclIShc61KOpbKw== - -"@sentry/cli-linux-arm64@2.31.2": - version "2.31.2" - resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.31.2.tgz#669c9c3f7f9130d26f5db732f793378863d58869" - integrity sha512-FLVKkJ/rWvPy/ka7OrUdRW63a/z8HYI1Gt8Pr6rWs50hb7YJja8lM8IO10tYmcFE/tODICsnHO9HTeUg2g2d1w== - -"@sentry/cli-linux-arm@2.31.2": - version "2.31.2" - resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm/-/cli-linux-arm-2.31.2.tgz#3e36ed7db09e922f00221281252e58dfd8755ea5" - integrity sha512-W8k5mGYYZz/I/OxZH65YAK7dCkQAl+wbuoASGOQjUy5VDgqH0QJ8kGJufXvFPM+f3ZQGcKAnVsZ6tFqZXETBAw== - -"@sentry/cli-linux-i686@2.31.2": - version "2.31.2" - resolved "https://registry.yarnpkg.com/@sentry/cli-linux-i686/-/cli-linux-i686-2.31.2.tgz#02b7da274369b78a5676c20bb26cc37caed5244b" - integrity sha512-A64QtzaPi3MYFpZ+Fwmi0mrSyXgeLJ0cWr4jdeTGrzNpeowSteKgd6tRKU+LVq0k5shKE7wdnHk+jXnoajulMA== - -"@sentry/cli-linux-x64@2.31.2": - version "2.31.2" - resolved "https://registry.yarnpkg.com/@sentry/cli-linux-x64/-/cli-linux-x64-2.31.2.tgz#54f74a9e5925db9ddafebc0efd4056c5377be5fd" - integrity sha512-YL/r+15R4mOEiU3mzn7iFQOeFEUB6KxeKGTTrtpeOGynVUGIdq4nV5rHow5JDbIzOuBS3SpOmcIMluvo1NCh0g== - -"@sentry/cli-win32-i686@2.31.2": - version "2.31.2" - resolved "https://registry.yarnpkg.com/@sentry/cli-win32-i686/-/cli-win32-i686-2.31.2.tgz#5dab845a824be0927566171aa05f015e887fe82d" - integrity sha512-Az/2bmW+TFI059RE0mSBIxTBcoShIclz7BDebmIoCkZ+retrwAzpmBnBCDAHow+Yi43utOow+3/4idGa2OxcLw== - -"@sentry/cli-win32-x64@2.31.2": - version "2.31.2" - resolved "https://registry.yarnpkg.com/@sentry/cli-win32-x64/-/cli-win32-x64-2.31.2.tgz#e12fec0a54f6d9cced5235fbc68ba8f94165634b" - integrity sha512-XIzyRnJu539NhpFa+JYkotzVwv3NrZ/4GfHB/JWA2zReRvsk39jJG8D5HOmm0B9JA63QQT7Dt39RW8g3lkmb6w== - -"@sentry/cli@^2.22.3", "@sentry/cli@^2.31.2": - version "2.31.2" - resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.31.2.tgz#39df8e52966aa8db4f9c51f4bc77abd62b6a630e" - integrity sha512-2aKyUx6La2P+pplL8+2vO67qJ+c1C79KYWAyQBE0JIT5kvKK9JpwtdNoK1F0/2mRpwhhYPADCz3sVIRqmL8cQQ== +"@sentry/cli-darwin@2.32.1": + version "2.32.1" + resolved "https://registry.yarnpkg.com/@sentry/cli-darwin/-/cli-darwin-2.32.1.tgz#9cb3b8cfb7068d40979514dee72e2bb3ad2c6d0a" + integrity sha512-z/lEwANTYPCzbWTZ2+eeeNYxRLllC8knd0h+vtAKlhmGw/fyc/N39cznIFyFu+dLJ6tTdjOWOeikHtKuS/7onw== + +"@sentry/cli-linux-arm64@2.32.1": + version "2.32.1" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.32.1.tgz#785a5d5d3d2919c581bf5b4efc638c3695d8c3bf" + integrity sha512-hsGqHYuecUl1Yhq4MhiRejfh1gNlmhyNPcQEoO/DDRBnGnJyEAdiDpKXJcc2e/lT9k40B55Ob2CP1SeY040T2w== + +"@sentry/cli-linux-arm@2.32.1": + version "2.32.1" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm/-/cli-linux-arm-2.32.1.tgz#7f9e8292850311bab263e7b84800eb407ff37998" + integrity sha512-m0lHkn+o4YKBq8KptGZvpT64FAwSl9mYvHZO9/ChnEGIJ/WyJwiN1X1r9JHVaW4iT5lD0Y5FAyq3JLkk0m0XHg== + +"@sentry/cli-linux-i686@2.32.1": + version "2.32.1" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-i686/-/cli-linux-i686-2.32.1.tgz#8e85fa58dee042e6a4642e960d226788f8e7288b" + integrity sha512-SuMLN1/ceFd3Q/B0DVyh5igjetTAF423txiABAHASenEev0lG0vZkRDXFclfgDtDUKRPmOXW7VDMirM3yZWQHQ== + +"@sentry/cli-linux-x64@2.32.1": + version "2.32.1" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-x64/-/cli-linux-x64-2.32.1.tgz#b68ed9c4ba163b6730d386dbeca828114f1c979b" + integrity sha512-x4FGd6xgvFddz8V/dh6jii4wy9qjWyvYLBTz8Fhi9rIP+b8wQ3oxwHIdzntareetZP7C1ggx+hZheiYocNYVwA== + +"@sentry/cli-win32-i686@2.32.1": + version "2.32.1" + resolved "https://registry.yarnpkg.com/@sentry/cli-win32-i686/-/cli-win32-i686-2.32.1.tgz#e2532893f87f5d180f6e56f49904d4ac141c8788" + integrity sha512-i6aZma9mFzR+hqMY5VliQZEX6ypP/zUjPK0VtIMYWs5cC6PsQLRmuoeJmy3Z7d4nlh0CdK5NPC813Ej6RY6/vg== + +"@sentry/cli-win32-x64@2.32.1": + version "2.32.1" + resolved "https://registry.yarnpkg.com/@sentry/cli-win32-x64/-/cli-win32-x64-2.32.1.tgz#6b60607cbba243f3708779443cd3f16e09d4289c" + integrity sha512-B58w/lRHLb4MUSjJNfMMw2cQykfimDCMLMmeK+1EiT2RmSeNQliwhhBxYcKk82a8kszH6zg3wT2vCea7LyPUyA== + +"@sentry/cli@^2.22.3", "@sentry/cli@^2.32.1": + version "2.32.1" + resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.32.1.tgz#80932d3d58e6d3b52e2bd705673e08deeb9cb5b0" + integrity sha512-MWkbkzZfnlE7s2pPbg4VozRSAeMlIObfZlTIou9ye6XnPt6ZmmxCLOuOgSKMv4sXg6aeqKNzMNiadThxCWyvPg== dependencies: https-proxy-agent "^5.0.0" node-fetch "^2.6.7" @@ -7163,13 +7163,13 @@ proxy-from-env "^1.1.0" which "^2.0.2" optionalDependencies: - "@sentry/cli-darwin" "2.31.2" - "@sentry/cli-linux-arm" "2.31.2" - "@sentry/cli-linux-arm64" "2.31.2" - "@sentry/cli-linux-i686" "2.31.2" - "@sentry/cli-linux-x64" "2.31.2" - "@sentry/cli-win32-i686" "2.31.2" - "@sentry/cli-win32-x64" "2.31.2" + "@sentry/cli-darwin" "2.32.1" + "@sentry/cli-linux-arm" "2.32.1" + "@sentry/cli-linux-arm64" "2.32.1" + "@sentry/cli-linux-i686" "2.32.1" + "@sentry/cli-linux-x64" "2.32.1" + "@sentry/cli-win32-i686" "2.32.1" + "@sentry/cli-win32-x64" "2.32.1" "@sentry/vite-plugin@2.14.2", "@sentry/vite-plugin@^2.14.2": version "2.14.2" @@ -8451,8 +8451,17 @@ dependencies: "@types/unist" "*" -"@types/history-4@npm:@types/history@4.7.8", "@types/history-5@npm:@types/history@4.7.8", "@types/history@*": - name "@types/history-4" +"@types/history-4@npm:@types/history@4.7.8": + version "4.7.8" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" + integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== + +"@types/history-5@npm:@types/history@4.7.8": + version "4.7.8" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" + integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== + +"@types/history@*": version "4.7.8" resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.8.tgz#49348387983075705fe8f4e02fb67f7daaec4934" integrity sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA== @@ -8818,7 +8827,15 @@ "@types/history" "^3" "@types/react" "*" -"@types/react-router-4@npm:@types/react-router@5.1.14", "@types/react-router-5@npm:@types/react-router@5.1.14": +"@types/react-router-4@npm:@types/react-router@5.1.14": + version "5.1.14" + resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.14.tgz#e0442f4eb4c446541ad7435d44a97f8fe6df40da" + integrity sha512-LAJpqYUaCTMT2anZheoidiIymt8MuX286zoVFPM3DVb23aQBH0mAkFvzpd4LKqiolV8bBtZWT5Qp7hClCNDENw== + dependencies: + "@types/history" "*" + "@types/react" "*" + +"@types/react-router-5@npm:@types/react-router@5.1.14": version "5.1.14" resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.14.tgz#e0442f4eb4c446541ad7435d44a97f8fe6df40da" integrity sha512-LAJpqYUaCTMT2anZheoidiIymt8MuX286zoVFPM3DVb23aQBH0mAkFvzpd4LKqiolV8bBtZWT5Qp7hClCNDENw== @@ -26109,8 +26126,7 @@ react-is@^18.0.0: dependencies: "@remix-run/router" "1.0.2" -"react-router-6@npm:react-router@6.3.0", react-router@6.3.0: - name react-router-6 +"react-router-6@npm:react-router@6.3.0": version "6.3.0" resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.3.0.tgz#3970cc64b4cb4eae0c1ea5203a80334fdd175557" integrity sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ== @@ -26125,6 +26141,13 @@ react-router-dom@^6.2.2: history "^5.2.0" react-router "6.3.0" +react-router@6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.3.0.tgz#3970cc64b4cb4eae0c1ea5203a80334fdd175557" + integrity sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ== + dependencies: + history "^5.2.0" + react@^18.0.0: version "18.0.0" resolved "https://registry.yarnpkg.com/react/-/react-18.0.0.tgz#b468736d1f4a5891f38585ba8e8fb29f91c3cb96" @@ -28443,8 +28466,7 @@ string-template@~0.2.1: resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add" integrity sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0= -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: - name string-width-cjs +"string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -28470,6 +28492,15 @@ string-width@^2.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -28565,7 +28596,14 @@ stringify-object@^3.2.1: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -31192,8 +31230,7 @@ workerpool@^6.4.0: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.4.0.tgz#f8d5cfb45fde32fa3b7af72ad617c3369567a462" integrity sha512-i3KR1mQMNwY2wx20ozq2EjISGtQWDIfV56We+yGJ5yDs8jTwQiLLaqHlkBHITlCuJnYlVRmXegxFxZg7gqI++A== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: - name wrap-ansi-cjs +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -31211,6 +31248,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 761b9d290b06f2fa82de9ff718ac72d8a87e6e4c Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Mon, 3 Jun 2024 19:17:11 +0200 Subject: [PATCH 19/41] ci: Fix sveltekit flakes (#12327) Observed a flake here: https://github.com/getsentry/sentry-javascript/actions/runs/9348183996/job/25727088799?pr=12267#step:12:92 --- .../sveltekit-2-svelte-5/tests/performance.test.ts | 6 +++--- .../test-applications/sveltekit-2/tests/performance.test.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.test.ts index 2e5c4eb63e48..622562b9ab6a 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2-svelte-5/tests/performance.test.ts @@ -193,7 +193,7 @@ test.describe('performance events', () => { return txnEvent?.contexts?.trace?.op === 'navigation' && txnEvent?.tags?.runtime === 'browser'; }); - await page.goto('/'); + await waitForInitialPageload(page, { route: '/' }); const navigationClickPromise = page.locator('#routeWithParamsLink').click(); @@ -252,8 +252,6 @@ test.describe('performance events', () => { }); test('captures one navigation transaction per redirect', async ({ page }) => { - await page.goto('/'); - const clientNavigationRedirect1TxnPromise = waitForTransaction('sveltekit-2-svelte-5', txnEvent => { return ( txnEvent?.contexts?.trace?.op === 'navigation' && @@ -278,6 +276,8 @@ test.describe('performance events', () => { ); }); + await waitForInitialPageload(page, { route: '/' }); + const navigationClickPromise = page.locator('#redirectLink').click(); const [redirect1TxnEvent, redirect2TxnEvent, redirect3TxnEvent, _] = await Promise.all([ diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.test.ts index 44d9dbdf5f01..ddaac44096f5 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/performance.test.ts @@ -193,7 +193,7 @@ test.describe('performance events', () => { return txnEvent?.contexts?.trace?.op === 'navigation' && txnEvent?.tags?.runtime === 'browser'; }); - await page.goto('/'); + await waitForInitialPageload(page, { route: '/' }); const navigationClickPromise = page.locator('#routeWithParamsLink').click(); @@ -252,8 +252,6 @@ test.describe('performance events', () => { }); test('captures one navigation transaction per redirect', async ({ page }) => { - await page.goto('/'); - const clientNavigationRedirect1TxnPromise = waitForTransaction('sveltekit-2', txnEvent => { return ( txnEvent?.contexts?.trace?.op === 'navigation' && @@ -278,6 +276,8 @@ test.describe('performance events', () => { ); }); + await waitForInitialPageload(page, { route: '/' }); + const navigationClickPromise = page.locator('#redirectLink').click(); const [redirect1TxnEvent, redirect2TxnEvent, redirect3TxnEvent, _] = await Promise.all([ From 48b228c1e53011cce520571cbe226b6f53089128 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 17:20:04 +0000 Subject: [PATCH 20/41] feat(deps): Bump @opentelemetry/propagator-aws-xray from 1.3.1 to 1.24.1 (#12333) --- yarn.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index a32b917d30de..e2fbf4e54e57 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6268,7 +6268,7 @@ dependencies: "@opentelemetry/semantic-conventions" "1.23.0" -"@opentelemetry/core@1.24.1", "@opentelemetry/core@^1.0.0", "@opentelemetry/core@^1.1.0", "@opentelemetry/core@^1.24.1", "@opentelemetry/core@^1.8.0": +"@opentelemetry/core@1.24.1", "@opentelemetry/core@^1.1.0", "@opentelemetry/core@^1.24.1", "@opentelemetry/core@^1.8.0": version "1.24.1" resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.24.1.tgz#35ab9d2ac9ca938e0ffbdfa40c49c169ac8ba80d" integrity sha512-wMSGfsdmibI88K9wB498zXY04yThPexo8jvwNNlm542HZB7XrrMRBbAyKJqG8qDRJwIBdBrPMi4V9ZPW/sqrcg== @@ -6463,11 +6463,11 @@ integrity sha512-DP2Y91zyw2uNgKLbej6c3IIjyF27sKnRK/UY/6msMIVGPIbZgtH9L0JOioN5L5kYjEkH4CDvt921SjutN7hY4A== "@opentelemetry/propagator-aws-xray@^1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@opentelemetry/propagator-aws-xray/-/propagator-aws-xray-1.3.1.tgz#7fc77a95fe89c705442b0e5a4218422c2954cc07" - integrity sha512-6fDMzFlt5r6VWv7MUd0eOpglXPFqykW8CnOuUxJ1VZyLy6mV1bzBlzpsqEmhx1bjvZYvH93vhGkQZqrm95mlrQ== + version "1.24.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/propagator-aws-xray/-/propagator-aws-xray-1.24.1.tgz#fd041d43f0eee7d482d272bc23688d42abe216d5" + integrity sha512-RzwoLe6QzsYGcpmxxDbbbgSpe3ncxSM4dtFHXh/rCYGjyq0nZGXKvk26mJtWZ4kQ3nuiIoqSZueIuGmt/mvOTA== dependencies: - "@opentelemetry/core" "^1.0.0" + "@opentelemetry/core" "1.24.1" "@opentelemetry/redis-common@^0.36.2": version "0.36.2" From 03f68d01a13c743cead961070aaaf6563221939b Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Fri, 31 May 2024 18:34:51 -0400 Subject: [PATCH 21/41] placeholder tests --- .../unit/util/createPerformanceEntry.test.ts | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts b/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts index 1433159ed9e2..82dc0541be1d 100644 --- a/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts +++ b/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts @@ -141,4 +141,61 @@ describe('Unit | util | createPerformanceEntries', () => { }); }); }); + + describe('getCumulativeLayoutShift', () => { + it('works with an CLS metric', async () => { + const metric = { + value: 5108.299, + entries: [], + }; + + const event = getCumulativeLayoutShift(metric); + + expect(event).toEqual({ + type: 'web-vital', + name: 'cumulative-layout-shift', + start: 1672531205.108299, + end: 1672531205.108299, + data: { value: 5108.299, size: 5108.299, nodeId: undefined }, + }); + }); + }); + + describe('getFirstInputDelay', () => { + it('works with an FID metric', async () => { + const metric = { + value: 5108.299, + entries: [], + }; + + const event = getFirstInputDelay(metric); + + expect(event).toEqual({ + type: 'web-vital', + name: 'first-input-delay', + start: 1672531205.108299, + end: 1672531205.108299, + data: { value: 5108.299, size: 5108.299, nodeId: undefined }, + }); + }); + }); + + describe('getInteractionToNextPaint', () => { + it('works with an INP metric', async () => { + const metric = { + value: 5108.299, + entries: [], + }; + + const event = getInteractionToNextPaint(metric); + + expect(event).toEqual({ + type: 'web-vital', + name: 'interaction-to-next-paint', + start: 1672531205.108299, + end: 1672531205.108299, + data: { value: 5108.299, size: 5108.299, nodeId: undefined }, + }); + }); + }); }); From 087b0b3bb449cbad308876aec2f43f5c9aa799d6 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Mon, 3 Jun 2024 20:22:03 -0400 Subject: [PATCH 22/41] linting --- .../suites/replay/customEvents/test.ts | 6 +++--- .../suites/replay/multiple-pages/test.ts | 6 +++--- .../src/coreHandlers/performanceObserver.ts | 17 +++++++++++++---- .../src/util/createPerformanceEntries.ts | 13 ++++++++----- .../unit/util/createPerformanceEntry.test.ts | 8 +++++++- 5 files changed, 34 insertions(+), 16 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts index a5f4d167b8cb..d7c99e60335b 100644 --- a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts @@ -2,13 +2,13 @@ import { expect } from '@playwright/test'; import { sentryTest } from '../../../utils/fixtures'; import { + expectedCLSPerformanceSpan, expectedClickBreadcrumb, expectedFCPPerformanceSpan, - expectedFPPerformanceSpan, - expectedLCPPerformanceSpan, - expectedCLSPerformanceSpan, expectedFIDPerformanceSpan, + expectedFPPerformanceSpan, expectedINPPerformanceSpan, + expectedLCPPerformanceSpan, expectedMemoryPerformanceSpan, expectedNavigationPerformanceSpan, getExpectedReplayEvent, diff --git a/dev-packages/browser-integration-tests/suites/replay/multiple-pages/test.ts b/dev-packages/browser-integration-tests/suites/replay/multiple-pages/test.ts index 3fdd63b30cd9..5610854462a3 100644 --- a/dev-packages/browser-integration-tests/suites/replay/multiple-pages/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/multiple-pages/test.ts @@ -2,13 +2,13 @@ import { expect } from '@playwright/test'; import { sentryTest } from '../../../utils/fixtures'; import { + expectedCLSPerformanceSpan, expectedClickBreadcrumb, expectedFCPPerformanceSpan, - expectedFPPerformanceSpan, - expectedLCPPerformanceSpan, - expectedCLSPerformanceSpan, expectedFIDPerformanceSpan, + expectedFPPerformanceSpan, expectedINPPerformanceSpan, + expectedLCPPerformanceSpan, expectedMemoryPerformanceSpan, expectedNavigationBreadcrumb, expectedNavigationPerformanceSpan, diff --git a/packages/replay-internal/src/coreHandlers/performanceObserver.ts b/packages/replay-internal/src/coreHandlers/performanceObserver.ts index 6f5b2d2633aa..25ccde10dd1b 100644 --- a/packages/replay-internal/src/coreHandlers/performanceObserver.ts +++ b/packages/replay-internal/src/coreHandlers/performanceObserver.ts @@ -1,8 +1,17 @@ -import { addClsInstrumentationHandler, addFidInstrumentationHandler, addLcpInstrumentationHandler, addPerformanceInstrumentationHandler } from '@sentry-internal/browser-utils'; - -import type { ReplayContainer } from '../types'; -import { getLargestContentfulPaint, getCumulativeLayoutShift, getFirstInputDelay, getInteractionToNextPaint } from '../util/createPerformanceEntries'; +import { + addClsInstrumentationHandler, + addFidInstrumentationHandler, + addLcpInstrumentationHandler, + addPerformanceInstrumentationHandler, +} from '@sentry-internal/browser-utils'; import { addInpInstrumentationHandler } from '@sentry-internal/browser-utils/build/types/metrics/instrument'; +import type { ReplayContainer } from '../types'; +import { + getCumulativeLayoutShift, + getFirstInputDelay, + getInteractionToNextPaint, + getLargestContentfulPaint, +} from '../util/createPerformanceEntries'; /** * Sets up a PerformanceObserver to listen to all performance entry types. diff --git a/packages/replay-internal/src/util/createPerformanceEntries.ts b/packages/replay-internal/src/util/createPerformanceEntries.ts index 4988d0e3d1c3..ab2a982990a3 100644 --- a/packages/replay-internal/src/util/createPerformanceEntries.ts +++ b/packages/replay-internal/src/util/createPerformanceEntries.ts @@ -187,11 +187,14 @@ export function getInteractionToNextPaint(metric: { /** * Add an web vital event to the replay based on the web vital metric. */ -export function getWebVital(metric: { - value: number; - rating: 'good' | 'needs-improvement' | 'poor'; - entries: PerformanceEntry[]; -}, name: string): ReplayPerformanceEntry { +export function getWebVital( + metric: { + value: number; + rating: 'good' | 'needs-improvement' | 'poor'; + entries: PerformanceEntry[]; + }, + name: string, +): ReplayPerformanceEntry { const entries = metric.entries; const lastEntry = entries[entries.length - 1] as (PerformanceEntry & { element?: Element }) | undefined; const element = lastEntry ? lastEntry.element : undefined; diff --git a/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts b/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts index 82dc0541be1d..4b2d866c171a 100644 --- a/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts +++ b/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts @@ -11,7 +11,13 @@ vi.mock('@sentry/utils', async () => ({ })); import { WINDOW } from '../../../src/constants'; -import { createPerformanceEntries, getLargestContentfulPaint, getCumulativeLayoutShift, getFirstInputDelay, getInteractionToNextPaint } from '../../../src/util/createPerformanceEntries'; +import { + createPerformanceEntries, + getCumulativeLayoutShift, + getFirstInputDelay, + getInteractionToNextPaint, + getLargestContentfulPaint, +} from '../../../src/util/createPerformanceEntries'; import { PerformanceEntryNavigation } from '../../fixtures/performanceEntry/navigation'; describe('Unit | util | createPerformanceEntries', () => { From 753c99b71e4c08b99a035cab8971b52784f761b6 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Tue, 4 Jun 2024 10:41:53 -0400 Subject: [PATCH 23/41] fix inp import --- packages/browser-utils/src/index.ts | 1 + .../replay-internal/src/coreHandlers/performanceObserver.ts | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/browser-utils/src/index.ts b/packages/browser-utils/src/index.ts index 7e7c4d0a387a..1dcc6824ce58 100644 --- a/packages/browser-utils/src/index.ts +++ b/packages/browser-utils/src/index.ts @@ -4,6 +4,7 @@ export { addFidInstrumentationHandler, addTtfbInstrumentationHandler, addLcpInstrumentationHandler, + addInpInstrumentationHandler, } from './metrics/instrument'; export { diff --git a/packages/replay-internal/src/coreHandlers/performanceObserver.ts b/packages/replay-internal/src/coreHandlers/performanceObserver.ts index 25ccde10dd1b..76f9f1995f34 100644 --- a/packages/replay-internal/src/coreHandlers/performanceObserver.ts +++ b/packages/replay-internal/src/coreHandlers/performanceObserver.ts @@ -3,8 +3,9 @@ import { addFidInstrumentationHandler, addLcpInstrumentationHandler, addPerformanceInstrumentationHandler, + addInpInstrumentationHandler, } from '@sentry-internal/browser-utils'; -import { addInpInstrumentationHandler } from '@sentry-internal/browser-utils/build/types/metrics/instrument'; +import { } from '@sentry-internal/browser-utils/build/types/metrics/instrument'; import type { ReplayContainer } from '../types'; import { getCumulativeLayoutShift, From 7c34d013b39056739745bddc2435b6007aab074b Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Tue, 4 Jun 2024 12:28:20 -0400 Subject: [PATCH 24/41] format + update test --- .../tests/fixtures/ReplayRecordingData.ts | 58 +++++++++++++++++++ .../src/coreHandlers/performanceObserver.ts | 1 - 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts index e7fd943c0f08..5a484dbb9201 100644 --- a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts +++ b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts @@ -219,6 +219,64 @@ export const ReplayRecordingData = [ data: { value: expect.any(Number), size: expect.any(Number), + rating: expect.any(String), + nodeId: 16, + }, + }, + }, + }, + { + type: 5, + timestamp: expect.any(Number), + data: { + tag: 'performanceSpan', + payload: { + op: 'web-vital', + description: 'culmulative-layout-shift', + startTimestamp: expect.any(Number), + endTimestamp: expect.any(Number), + data: { + value: expect.any(Number), + size: expect.any(Number), + rating: expect.any(String), + nodeId: 16, + }, + }, + }, + }, + { + type: 5, + timestamp: expect.any(Number), + data: { + tag: 'performanceSpan', + payload: { + op: 'web-vital', + description: 'first-input-delay', + startTimestamp: expect.any(Number), + endTimestamp: expect.any(Number), + data: { + value: expect.any(Number), + size: expect.any(Number), + rating: expect.any(String), + nodeId: 16, + }, + }, + }, + }, + { + type: 5, + timestamp: expect.any(Number), + data: { + tag: 'performanceSpan', + payload: { + op: 'web-vital', + description: 'interaction-to-next-paint', + startTimestamp: expect.any(Number), + endTimestamp: expect.any(Number), + data: { + value: expect.any(Number), + size: expect.any(Number), + rating: expect.any(String), nodeId: 16, }, }, diff --git a/packages/replay-internal/src/coreHandlers/performanceObserver.ts b/packages/replay-internal/src/coreHandlers/performanceObserver.ts index 76f9f1995f34..240e1f5cbf0c 100644 --- a/packages/replay-internal/src/coreHandlers/performanceObserver.ts +++ b/packages/replay-internal/src/coreHandlers/performanceObserver.ts @@ -5,7 +5,6 @@ import { addPerformanceInstrumentationHandler, addInpInstrumentationHandler, } from '@sentry-internal/browser-utils'; -import { } from '@sentry-internal/browser-utils/build/types/metrics/instrument'; import type { ReplayContainer } from '../types'; import { getCumulativeLayoutShift, From 0cc8090e82d54bb7dc0e4469236b2c3f8935642d Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Tue, 4 Jun 2024 12:33:29 -0400 Subject: [PATCH 25/41] lint --- .../replay-internal/src/coreHandlers/performanceObserver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/replay-internal/src/coreHandlers/performanceObserver.ts b/packages/replay-internal/src/coreHandlers/performanceObserver.ts index 240e1f5cbf0c..4ade74ca35a3 100644 --- a/packages/replay-internal/src/coreHandlers/performanceObserver.ts +++ b/packages/replay-internal/src/coreHandlers/performanceObserver.ts @@ -1,9 +1,9 @@ import { addClsInstrumentationHandler, addFidInstrumentationHandler, + addInpInstrumentationHandler, addLcpInstrumentationHandler, addPerformanceInstrumentationHandler, - addInpInstrumentationHandler, } from '@sentry-internal/browser-utils'; import type { ReplayContainer } from '../types'; import { From f695f686418e5dfa6a9e08fc71e51b15d077676d Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Tue, 4 Jun 2024 12:57:16 -0400 Subject: [PATCH 26/41] fix test --- .../suites/replay/multiple-pages/test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/replay/multiple-pages/test.ts b/dev-packages/browser-integration-tests/suites/replay/multiple-pages/test.ts index 5610854462a3..eb088ffc827d 100644 --- a/dev-packages/browser-integration-tests/suites/replay/multiple-pages/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/multiple-pages/test.ts @@ -81,7 +81,7 @@ sentryTest( const collectedPerformanceSpans = [...recording0.performanceSpans, ...recording1.performanceSpans]; const collectedBreadcrumbs = [...recording0.breadcrumbs, ...recording1.breadcrumbs]; - expect(collectedPerformanceSpans.length).toEqual(6); + expect(collectedPerformanceSpans.length).toEqual(8); expect(collectedPerformanceSpans).toEqual( expect.arrayContaining([ expectedNavigationPerformanceSpan, @@ -122,7 +122,7 @@ sentryTest( const collectedPerformanceSpansAfterReload = [...recording2.performanceSpans, ...recording3.performanceSpans]; const collectedBreadcrumbsAdterReload = [...recording2.breadcrumbs, ...recording3.breadcrumbs]; - expect(collectedPerformanceSpansAfterReload.length).toEqual(6); + expect(collectedPerformanceSpansAfterReload.length).toEqual(8); expect(collectedPerformanceSpansAfterReload).toEqual( expect.arrayContaining([ expectedReloadPerformanceSpan, @@ -316,7 +316,7 @@ sentryTest( ]; const collectedBreadcrumbsAfterIndexNavigation = [...recording8.breadcrumbs, ...recording9.breadcrumbs]; - expect(collectedPerformanceSpansAfterIndexNavigation.length).toEqual(6); + expect(collectedPerformanceSpansAfterIndexNavigation.length).toEqual(8); expect(collectedPerformanceSpansAfterIndexNavigation).toEqual( expect.arrayContaining([ expectedNavigationPerformanceSpan, From 7772427869040d4ed065eff4ff1cb759a6a2f89c Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Thu, 6 Jun 2024 00:48:02 -0400 Subject: [PATCH 27/41] some PR comment refactor --- .../src/coreHandlers/performanceObserver.ts | 23 ++++---- .../replay-internal/src/types/replayFrame.ts | 24 +------- .../src/util/createPerformanceEntries.ts | 56 ++++++++++--------- 3 files changed, 44 insertions(+), 59 deletions(-) diff --git a/packages/replay-internal/src/coreHandlers/performanceObserver.ts b/packages/replay-internal/src/coreHandlers/performanceObserver.ts index 4ade74ca35a3..01b7ea6d7c60 100644 --- a/packages/replay-internal/src/coreHandlers/performanceObserver.ts +++ b/packages/replay-internal/src/coreHandlers/performanceObserver.ts @@ -5,7 +5,8 @@ import { addLcpInstrumentationHandler, addPerformanceInstrumentationHandler, } from '@sentry-internal/browser-utils'; -import type { ReplayContainer } from '../types'; +import type { AllPerformanceEntryData, ReplayContainer, ReplayPerformanceEntry } from '../types'; +import type { Metric} from '../util/createPerformanceEntries'; import { getCumulativeLayoutShift, getFirstInputDelay, @@ -36,22 +37,18 @@ export function setupPerformanceObserver(replay: ReplayContainer): () => void { }); clearCallbacks.push( - addLcpInstrumentationHandler(({ metric }) => { - replay.replayPerformanceEntries.push(getLargestContentfulPaint(metric)); - }), - addClsInstrumentationHandler(({ metric }) => { - replay.replayPerformanceEntries.push(getCumulativeLayoutShift(metric)); - }), - addFidInstrumentationHandler(({ metric }) => { - replay.replayPerformanceEntries.push(getFirstInputDelay(metric)); - }), - addInpInstrumentationHandler(({ metric }) => { - replay.replayPerformanceEntries.push(getInteractionToNextPaint(metric)); - }), + addLcpInstrumentationHandler(webVitalHandler(getLargestContentfulPaint)), + addClsInstrumentationHandler(webVitalHandler(getCumulativeLayoutShift)), + addFidInstrumentationHandler(webVitalHandler(getFirstInputDelay)), + addInpInstrumentationHandler(webVitalHandler(getInteractionToNextPaint)), ); // A callback to cleanup all handlers return () => { clearCallbacks.forEach(clearCallback => clearCallback()); }; + + function webVitalHandler(getter: (metric: Metric) => ReplayPerformanceEntry): (data: { metric: Metric; }) => void { + return ({metric}) => void replay.replayPerformanceEntries.push(getter(metric)); + } } diff --git a/packages/replay-internal/src/types/replayFrame.ts b/packages/replay-internal/src/types/replayFrame.ts index e5388a065504..6a7a1a8e255a 100644 --- a/packages/replay-internal/src/types/replayFrame.ts +++ b/packages/replay-internal/src/types/replayFrame.ts @@ -162,24 +162,9 @@ interface ReplayHistoryFrame extends ReplayBaseSpanFrame { op: 'navigation.push'; } -interface ReplayLargestContentfulPaintFrame extends ReplayBaseSpanFrame { +interface ReplayWebVitalFrame extends ReplayBaseSpanFrame { data: WebVitalData; - op: 'largest-contentful-paint'; -} - -interface ReplayCumulativeLayoutShiftFrame extends ReplayBaseSpanFrame { - data: WebVitalData; - op: 'cumulative-layout-shift'; -} - -interface ReplayFirstInputDelayFrame extends ReplayBaseSpanFrame { - data: WebVitalData; - op: 'first-input-delay'; -} - -interface ReplayInteractionToNextPaintFrame extends ReplayBaseSpanFrame { - data: WebVitalData; - op: 'interaction-to-next-paint'; + op: 'largest-contentful-paint' | 'cumulative-layout-shift' | 'first-input-delay' | 'interaction-to-next-paint'; } interface ReplayMemoryFrame extends ReplayBaseSpanFrame { @@ -211,10 +196,7 @@ export type ReplaySpanFrame = | ReplayBaseSpanFrame | ReplayHistoryFrame | ReplayRequestFrame - | ReplayLargestContentfulPaintFrame - | ReplayCumulativeLayoutShiftFrame - | ReplayFirstInputDelayFrame - | ReplayInteractionToNextPaintFrame + | ReplayWebVitalFrame | ReplayMemoryFrame | ReplayNavigationFrame | ReplayPaintFrame diff --git a/packages/replay-internal/src/util/createPerformanceEntries.ts b/packages/replay-internal/src/util/createPerformanceEntries.ts index ab2a982990a3..e42031661236 100644 --- a/packages/replay-internal/src/util/createPerformanceEntries.ts +++ b/packages/replay-internal/src/util/createPerformanceEntries.ts @@ -25,6 +25,31 @@ const ENTRY_TYPES: Record< navigation: createNavigationEntry, }; +export interface Metric { + /** + * The name of the metric (in acronym form). + */ + name: 'CLS' | 'FCP' | 'FID' | 'INP' | 'LCP' | 'TTFB'; + + /** + * The current value of the metric. + */ + value: number; + + /** + * The rating as to whether the metric value is within the "good", + * "needs improvement", or "poor" thresholds of the metric. + */ + rating: 'good' | 'needs-improvement' | 'poor'; + + /** + * Any performance entries relevant to the metric value calculation. + * The array may also be empty if the metric value was not based on any + * entries (e.g. a CLS value of 0 given no layout shifts). + */ + entries: PerformanceEntry[] | PerformanceEventTiming[]; +} + /** * Create replay performance entries from the browser performance entries. */ @@ -143,44 +168,29 @@ function createResourceEntry( /** * Add a LCP event to the replay based on a LCP metric. */ -export function getLargestContentfulPaint(metric: { - value: number; - rating: 'good' | 'needs-improvement' | 'poor'; - entries: PerformanceEntry[]; -}): ReplayPerformanceEntry { +export function getLargestContentfulPaint(metric: Metric +): ReplayPerformanceEntry { return getWebVital(metric, 'largest-contentful-paint'); } /** * Add a CLS event to the replay based on a CLS metric. */ -export function getCumulativeLayoutShift(metric: { - value: number; - rating: 'good' | 'needs-improvement' | 'poor'; - entries: PerformanceEntry[]; -}): ReplayPerformanceEntry { +export function getCumulativeLayoutShift(metric: Metric): ReplayPerformanceEntry { return getWebVital(metric, 'cumulative-layout-shift'); } /** * Add a FID event to the replay based on a FID metric. */ -export function getFirstInputDelay(metric: { - value: number; - rating: 'good' | 'needs-improvement' | 'poor'; - entries: PerformanceEntry[]; -}): ReplayPerformanceEntry { +export function getFirstInputDelay(metric: Metric): ReplayPerformanceEntry { return getWebVital(metric, 'first-input-delay'); } /** * Add an INP event to the replay based on an INP metric. */ -export function getInteractionToNextPaint(metric: { - value: number; - rating: 'good' | 'needs-improvement' | 'poor'; - entries: PerformanceEntry[]; -}): ReplayPerformanceEntry { +export function getInteractionToNextPaint(metric: Metric): ReplayPerformanceEntry { return getWebVital(metric, 'interaction-to-next-paint'); } @@ -188,11 +198,7 @@ export function getInteractionToNextPaint(metric: { * Add an web vital event to the replay based on the web vital metric. */ export function getWebVital( - metric: { - value: number; - rating: 'good' | 'needs-improvement' | 'poor'; - entries: PerformanceEntry[]; - }, + metric: Metric, name: string, ): ReplayPerformanceEntry { const entries = metric.entries; From aa04cf8f68b233da2b0a8dbe0bd22421f2ab7a33 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Thu, 6 Jun 2024 14:05:52 -0400 Subject: [PATCH 28/41] PR comments --- .../src/coreHandlers/performanceObserver.ts | 16 ++++++---------- .../src/util/createPerformanceEntries.ts | 13 ++++++++----- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/packages/replay-internal/src/coreHandlers/performanceObserver.ts b/packages/replay-internal/src/coreHandlers/performanceObserver.ts index 01b7ea6d7c60..638ef53b05fb 100644 --- a/packages/replay-internal/src/coreHandlers/performanceObserver.ts +++ b/packages/replay-internal/src/coreHandlers/performanceObserver.ts @@ -5,13 +5,13 @@ import { addLcpInstrumentationHandler, addPerformanceInstrumentationHandler, } from '@sentry-internal/browser-utils'; -import type { AllPerformanceEntryData, ReplayContainer, ReplayPerformanceEntry } from '../types'; -import type { Metric} from '../util/createPerformanceEntries'; +import type { ReplayContainer } from '../types'; import { getCumulativeLayoutShift, getFirstInputDelay, getInteractionToNextPaint, getLargestContentfulPaint, + webVitalHandler, } from '../util/createPerformanceEntries'; /** @@ -37,18 +37,14 @@ export function setupPerformanceObserver(replay: ReplayContainer): () => void { }); clearCallbacks.push( - addLcpInstrumentationHandler(webVitalHandler(getLargestContentfulPaint)), - addClsInstrumentationHandler(webVitalHandler(getCumulativeLayoutShift)), - addFidInstrumentationHandler(webVitalHandler(getFirstInputDelay)), - addInpInstrumentationHandler(webVitalHandler(getInteractionToNextPaint)), + addLcpInstrumentationHandler(webVitalHandler(getLargestContentfulPaint, replay)), + addClsInstrumentationHandler(webVitalHandler(getCumulativeLayoutShift, replay)), + addFidInstrumentationHandler(webVitalHandler(getFirstInputDelay, replay)), + addInpInstrumentationHandler(webVitalHandler(getInteractionToNextPaint, replay)), ); // A callback to cleanup all handlers return () => { clearCallbacks.forEach(clearCallback => clearCallback()); }; - - function webVitalHandler(getter: (metric: Metric) => ReplayPerformanceEntry): (data: { metric: Metric; }) => void { - return ({metric}) => void replay.replayPerformanceEntries.push(getter(metric)); - } } diff --git a/packages/replay-internal/src/util/createPerformanceEntries.ts b/packages/replay-internal/src/util/createPerformanceEntries.ts index e42031661236..252ac2b54119 100644 --- a/packages/replay-internal/src/util/createPerformanceEntries.ts +++ b/packages/replay-internal/src/util/createPerformanceEntries.ts @@ -8,6 +8,7 @@ import type { ExperimentalPerformanceResourceTiming, NavigationData, PaintData, + ReplayContainer, ReplayPerformanceEntry, ResourceData, WebVitalData, @@ -26,11 +27,6 @@ const ENTRY_TYPES: Record< }; export interface Metric { - /** - * The name of the metric (in acronym form). - */ - name: 'CLS' | 'FCP' | 'FID' | 'INP' | 'LCP' | 'TTFB'; - /** * The current value of the metric. */ @@ -50,6 +46,13 @@ export interface Metric { entries: PerformanceEntry[] | PerformanceEventTiming[]; } +/** + * Handler creater for web vitals + */ +export function webVitalHandler(getter: (metric: Metric) => ReplayPerformanceEntry, replay: ReplayContainer): (data: { metric: Metric; }) => void { + return ({metric}) => void replay.replayPerformanceEntries.push(getter(metric)); +} + /** * Create replay performance entries from the browser performance entries. */ From f81ca6f58449202a795308a23cbaa29b1862df52 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Fri, 7 Jun 2024 01:07:09 -0400 Subject: [PATCH 29/41] add inp to test --- .../suites/replay/customEvents/test.ts | 7 ++++++- .../utils/replayEventTemplates.ts | 3 --- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts index d7c99e60335b..e2a1e44474b3 100644 --- a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts @@ -48,10 +48,15 @@ sentryTest( const replayEvent0 = getReplayEvent(await reqPromise0); const { performanceSpans: performanceSpans0 } = getCustomRecordingEvents(await reqPromise0); - expect(replayEvent0).toEqual(getExpectedReplayEvent({ segment_id: 0 })); + expect(await replayEvent0).toEqual(getExpectedReplayEvent({ segment_id: 0 })); await page.locator('#img-button').click(); + // Page hide to trigger INP + await page.evaluate(() => { + window.dispatchEvent(new Event('pagehide')); + }); + const replayEvent1 = getReplayEvent(await reqPromise1); const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(await reqPromise1); diff --git a/dev-packages/browser-integration-tests/utils/replayEventTemplates.ts b/dev-packages/browser-integration-tests/utils/replayEventTemplates.ts index 878edd77b58e..84daef80f938 100644 --- a/dev-packages/browser-integration-tests/utils/replayEventTemplates.ts +++ b/dev-packages/browser-integration-tests/utils/replayEventTemplates.ts @@ -140,7 +140,6 @@ export const expectedCLSPerformanceSpan = { endTimestamp: expect.any(Number), data: { value: expect.any(Number), - nodeId: expect.any(Number), rating: expect.any(String), size: expect.any(Number), }, @@ -153,7 +152,6 @@ export const expectedFIDPerformanceSpan = { endTimestamp: expect.any(Number), data: { value: expect.any(Number), - nodeId: expect.any(Number), rating: expect.any(String), size: expect.any(Number), }, @@ -166,7 +164,6 @@ export const expectedINPPerformanceSpan = { endTimestamp: expect.any(Number), data: { value: expect.any(Number), - nodeId: expect.any(Number), rating: expect.any(String), size: expect.any(Number), }, From bdc7bca2c6b4f9ef2b1e8fd10b174aab8869ad25 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Fri, 7 Jun 2024 01:07:47 -0400 Subject: [PATCH 30/41] typos & tests --- .../react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts | 2 +- .../test/unit/util/createPerformanceEntry.test.ts | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts index 5a484dbb9201..5b29b8979ab3 100644 --- a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts +++ b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts @@ -232,7 +232,7 @@ export const ReplayRecordingData = [ tag: 'performanceSpan', payload: { op: 'web-vital', - description: 'culmulative-layout-shift', + description: 'cumulative-layout-shift', startTimestamp: expect.any(Number), endTimestamp: expect.any(Number), data: { diff --git a/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts b/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts index 4b2d866c171a..122aa6ff5dcd 100644 --- a/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts +++ b/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts @@ -152,6 +152,7 @@ describe('Unit | util | createPerformanceEntries', () => { it('works with an CLS metric', async () => { const metric = { value: 5108.299, + rating: 'good' as const, entries: [], }; @@ -171,6 +172,7 @@ describe('Unit | util | createPerformanceEntries', () => { it('works with an FID metric', async () => { const metric = { value: 5108.299, + rating: 'good' as const, entries: [], }; @@ -190,6 +192,7 @@ describe('Unit | util | createPerformanceEntries', () => { it('works with an INP metric', async () => { const metric = { value: 5108.299, + rating: 'good' as const, entries: [], }; From 27c53eea271b685a0e5500f517513ba1b033834d Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Fri, 7 Jun 2024 01:29:33 -0400 Subject: [PATCH 31/41] lint & fix performance entry test --- .../suites/replay/customEvents/test.ts | 2 + .../tests/send-to-sentry.test.ts | 5 ++ .../src/util/createPerformanceEntries.ts | 15 +++-- .../unit/util/createPerformanceEntry.test.ts | 60 ------------------- 4 files changed, 14 insertions(+), 68 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts index e2a1e44474b3..a5b9786caa97 100644 --- a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts @@ -52,6 +52,8 @@ sentryTest( await page.locator('#img-button').click(); + await page.waitForTimeout(500); + // Page hide to trigger INP await page.evaluate(() => { window.dispatchEvent(new Event('pagehide')); diff --git a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts index d9c3e09f2ad2..c59200dd3ddd 100644 --- a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts @@ -155,6 +155,11 @@ test('Sends a Replay recording to Sentry', async ({ browser }) => { // Keypress event ensures LCP is finished await page.type('body', 'Y'); + // Page hide to trigger INP + await page.evaluate(() => { + window.dispatchEvent(new Event('pagehide')); + }); + // Wait for replay to be sent if (replayId === undefined) { diff --git a/packages/replay-internal/src/util/createPerformanceEntries.ts b/packages/replay-internal/src/util/createPerformanceEntries.ts index 252ac2b54119..0e56fc3fc328 100644 --- a/packages/replay-internal/src/util/createPerformanceEntries.ts +++ b/packages/replay-internal/src/util/createPerformanceEntries.ts @@ -49,8 +49,11 @@ export interface Metric { /** * Handler creater for web vitals */ -export function webVitalHandler(getter: (metric: Metric) => ReplayPerformanceEntry, replay: ReplayContainer): (data: { metric: Metric; }) => void { - return ({metric}) => void replay.replayPerformanceEntries.push(getter(metric)); +export function webVitalHandler( + getter: (metric: Metric) => ReplayPerformanceEntry, + replay: ReplayContainer, +): (data: { metric: Metric }) => void { + return ({ metric }) => void replay.replayPerformanceEntries.push(getter(metric)); } /** @@ -171,8 +174,7 @@ function createResourceEntry( /** * Add a LCP event to the replay based on a LCP metric. */ -export function getLargestContentfulPaint(metric: Metric -): ReplayPerformanceEntry { +export function getLargestContentfulPaint(metric: Metric): ReplayPerformanceEntry { return getWebVital(metric, 'largest-contentful-paint'); } @@ -200,10 +202,7 @@ export function getInteractionToNextPaint(metric: Metric): ReplayPerformanceEntr /** * Add an web vital event to the replay based on the web vital metric. */ -export function getWebVital( - metric: Metric, - name: string, -): ReplayPerformanceEntry { +export function getWebVital(metric: Metric, name: string): ReplayPerformanceEntry { const entries = metric.entries; const lastEntry = entries[entries.length - 1] as (PerformanceEntry & { element?: Element }) | undefined; const element = lastEntry ? lastEntry.element : undefined; diff --git a/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts b/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts index 122aa6ff5dcd..f13d72feecf4 100644 --- a/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts +++ b/packages/replay-internal/test/unit/util/createPerformanceEntry.test.ts @@ -147,64 +147,4 @@ describe('Unit | util | createPerformanceEntries', () => { }); }); }); - - describe('getCumulativeLayoutShift', () => { - it('works with an CLS metric', async () => { - const metric = { - value: 5108.299, - rating: 'good' as const, - entries: [], - }; - - const event = getCumulativeLayoutShift(metric); - - expect(event).toEqual({ - type: 'web-vital', - name: 'cumulative-layout-shift', - start: 1672531205.108299, - end: 1672531205.108299, - data: { value: 5108.299, size: 5108.299, nodeId: undefined }, - }); - }); - }); - - describe('getFirstInputDelay', () => { - it('works with an FID metric', async () => { - const metric = { - value: 5108.299, - rating: 'good' as const, - entries: [], - }; - - const event = getFirstInputDelay(metric); - - expect(event).toEqual({ - type: 'web-vital', - name: 'first-input-delay', - start: 1672531205.108299, - end: 1672531205.108299, - data: { value: 5108.299, size: 5108.299, nodeId: undefined }, - }); - }); - }); - - describe('getInteractionToNextPaint', () => { - it('works with an INP metric', async () => { - const metric = { - value: 5108.299, - rating: 'good' as const, - entries: [], - }; - - const event = getInteractionToNextPaint(metric); - - expect(event).toEqual({ - type: 'web-vital', - name: 'interaction-to-next-paint', - start: 1672531205.108299, - end: 1672531205.108299, - data: { value: 5108.299, size: 5108.299, nodeId: undefined }, - }); - }); - }); }); From f52307582823500f7167fd7b4110ba4f4df7c845 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Fri, 7 Jun 2024 01:46:46 -0400 Subject: [PATCH 32/41] hopefully actually fixed some tests?? --- .../suites/replay/customEvents/test.ts | 4 ++-- .../tests/fixtures/ReplayRecordingData.ts | 3 --- .../react-send-to-sentry/tests/send-to-sentry.test.ts | 2 ++ 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts index a5b9786caa97..30cfe1159be9 100644 --- a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts @@ -52,13 +52,13 @@ sentryTest( await page.locator('#img-button').click(); - await page.waitForTimeout(500); - // Page hide to trigger INP await page.evaluate(() => { window.dispatchEvent(new Event('pagehide')); }); + await page.waitForTimeout(500); + const replayEvent1 = getReplayEvent(await reqPromise1); const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(await reqPromise1); diff --git a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts index 5b29b8979ab3..3fa67ff9feb7 100644 --- a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts +++ b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts @@ -239,7 +239,6 @@ export const ReplayRecordingData = [ value: expect.any(Number), size: expect.any(Number), rating: expect.any(String), - nodeId: 16, }, }, }, @@ -258,7 +257,6 @@ export const ReplayRecordingData = [ value: expect.any(Number), size: expect.any(Number), rating: expect.any(String), - nodeId: 16, }, }, }, @@ -277,7 +275,6 @@ export const ReplayRecordingData = [ value: expect.any(Number), size: expect.any(Number), rating: expect.any(String), - nodeId: 16, }, }, }, diff --git a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts index c59200dd3ddd..10fde4ac5151 100644 --- a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts @@ -160,6 +160,8 @@ test('Sends a Replay recording to Sentry', async ({ browser }) => { window.dispatchEvent(new Event('pagehide')); }); + await page.waitForTimeout(500); + // Wait for replay to be sent if (replayId === undefined) { From f21a812978de5459760559eefed9dba6d97a5cc0 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Fri, 7 Jun 2024 02:04:25 -0400 Subject: [PATCH 33/41] remove inp from e2e test --- .../suites/replay/customEvents/test.ts | 2 +- .../tests/fixtures/ReplayRecordingData.ts | 18 ------------------ .../tests/send-to-sentry.test.ts | 7 ------- 3 files changed, 1 insertion(+), 26 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts index 30cfe1159be9..134e0f71fb95 100644 --- a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts @@ -48,7 +48,7 @@ sentryTest( const replayEvent0 = getReplayEvent(await reqPromise0); const { performanceSpans: performanceSpans0 } = getCustomRecordingEvents(await reqPromise0); - expect(await replayEvent0).toEqual(getExpectedReplayEvent({ segment_id: 0 })); + expect(replayEvent0).toEqual(getExpectedReplayEvent({ segment_id: 0 })); await page.locator('#img-button').click(); diff --git a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts index 3fa67ff9feb7..74bff4f82713 100644 --- a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts +++ b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts @@ -261,24 +261,6 @@ export const ReplayRecordingData = [ }, }, }, - { - type: 5, - timestamp: expect.any(Number), - data: { - tag: 'performanceSpan', - payload: { - op: 'web-vital', - description: 'interaction-to-next-paint', - startTimestamp: expect.any(Number), - endTimestamp: expect.any(Number), - data: { - value: expect.any(Number), - size: expect.any(Number), - rating: expect.any(String), - }, - }, - }, - }, { type: 5, timestamp: expect.any(Number), diff --git a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts index 10fde4ac5151..d9c3e09f2ad2 100644 --- a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts @@ -155,13 +155,6 @@ test('Sends a Replay recording to Sentry', async ({ browser }) => { // Keypress event ensures LCP is finished await page.type('body', 'Y'); - // Page hide to trigger INP - await page.evaluate(() => { - window.dispatchEvent(new Event('pagehide')); - }); - - await page.waitForTimeout(500); - // Wait for replay to be sent if (replayId === undefined) { From 3eaf3f942318496fa8ea47bc341bb8a67f904b0b Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Fri, 7 Jun 2024 02:28:58 -0400 Subject: [PATCH 34/41] try copying web-vitals-inp test? --- .../suites/replay/customEvents/test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts index 134e0f71fb95..d2713bfd1a0a 100644 --- a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts @@ -51,14 +51,15 @@ sentryTest( expect(replayEvent0).toEqual(getExpectedReplayEvent({ segment_id: 0 })); await page.locator('#img-button').click(); + await page.locator('#img-button').isVisible(); + + await page.waitForTimeout(500); // Page hide to trigger INP await page.evaluate(() => { window.dispatchEvent(new Event('pagehide')); }); - await page.waitForTimeout(500); - const replayEvent1 = getReplayEvent(await reqPromise1); const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(await reqPromise1); From 39e20b2407c2d628424f95f53a8e163f378229a3 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Fri, 7 Jun 2024 11:46:00 -0400 Subject: [PATCH 35/41] add promise all to test --- .../suites/replay/customEvents/test.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts index d2713bfd1a0a..78c2760f9330 100644 --- a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts @@ -50,15 +50,15 @@ sentryTest( expect(replayEvent0).toEqual(getExpectedReplayEvent({ segment_id: 0 })); - await page.locator('#img-button').click(); - await page.locator('#img-button').isVisible(); + await Promise.all([ + await page.locator('#img-button').click(), - await page.waitForTimeout(500); + // Page hide to trigger INP + await page.evaluate(() => { + window.dispatchEvent(new Event('pagehide')); + }), + ]); - // Page hide to trigger INP - await page.evaluate(() => { - window.dispatchEvent(new Event('pagehide')); - }); const replayEvent1 = getReplayEvent(await reqPromise1); const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(await reqPromise1); From e7d7db022dea9297d1b0458161ac61d6cbca8ff1 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Fri, 7 Jun 2024 12:14:35 -0400 Subject: [PATCH 36/41] rm await inside all --- .../suites/replay/customEvents/test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts index 78c2760f9330..85028fabc30e 100644 --- a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts @@ -51,10 +51,10 @@ sentryTest( expect(replayEvent0).toEqual(getExpectedReplayEvent({ segment_id: 0 })); await Promise.all([ - await page.locator('#img-button').click(), + page.locator('#img-button').click(), // Page hide to trigger INP - await page.evaluate(() => { + page.evaluate(() => { window.dispatchEvent(new Event('pagehide')); }), ]); From 44590d14ce72be92a7e5d892cb3e35eced54a204 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Fri, 7 Jun 2024 13:05:06 -0400 Subject: [PATCH 37/41] remove inp from tests --- .../suites/replay/customEvents/test.ts | 12 +----------- .../suites/replay/multiple-pages/test.ts | 5 ----- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts index 85028fabc30e..d2225b6d400b 100644 --- a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts @@ -7,7 +7,6 @@ import { expectedFCPPerformanceSpan, expectedFIDPerformanceSpan, expectedFPPerformanceSpan, - expectedINPPerformanceSpan, expectedLCPPerformanceSpan, expectedMemoryPerformanceSpan, expectedNavigationPerformanceSpan, @@ -50,15 +49,7 @@ sentryTest( expect(replayEvent0).toEqual(getExpectedReplayEvent({ segment_id: 0 })); - await Promise.all([ - page.locator('#img-button').click(), - - // Page hide to trigger INP - page.evaluate(() => { - window.dispatchEvent(new Event('pagehide')); - }), - ]); - + page.locator('#img-button').click(); const replayEvent1 = getReplayEvent(await reqPromise1); const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(await reqPromise1); @@ -75,7 +66,6 @@ sentryTest( expectedLCPPerformanceSpan, expectedCLSPerformanceSpan, expectedFIDPerformanceSpan, - expectedINPPerformanceSpan, expectedFPPerformanceSpan, expectedFCPPerformanceSpan, expectedMemoryPerformanceSpan, // two memory spans - once per flush diff --git a/dev-packages/browser-integration-tests/suites/replay/multiple-pages/test.ts b/dev-packages/browser-integration-tests/suites/replay/multiple-pages/test.ts index eb088ffc827d..7bacf5a8ae17 100644 --- a/dev-packages/browser-integration-tests/suites/replay/multiple-pages/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/multiple-pages/test.ts @@ -7,7 +7,6 @@ import { expectedFCPPerformanceSpan, expectedFIDPerformanceSpan, expectedFPPerformanceSpan, - expectedINPPerformanceSpan, expectedLCPPerformanceSpan, expectedMemoryPerformanceSpan, expectedNavigationBreadcrumb, @@ -88,7 +87,6 @@ sentryTest( expectedLCPPerformanceSpan, expectedCLSPerformanceSpan, expectedFIDPerformanceSpan, - expectedINPPerformanceSpan, expectedFPPerformanceSpan, expectedFCPPerformanceSpan, expectedMemoryPerformanceSpan, // two memory spans - once per flush @@ -129,7 +127,6 @@ sentryTest( expectedLCPPerformanceSpan, expectedCLSPerformanceSpan, expectedFIDPerformanceSpan, - expectedINPPerformanceSpan, expectedFPPerformanceSpan, expectedFCPPerformanceSpan, expectedMemoryPerformanceSpan, @@ -199,7 +196,6 @@ sentryTest( expectedLCPPerformanceSpan, expectedCLSPerformanceSpan, expectedFIDPerformanceSpan, - expectedINPPerformanceSpan, expectedFPPerformanceSpan, expectedFCPPerformanceSpan, expectedMemoryPerformanceSpan, @@ -323,7 +319,6 @@ sentryTest( expectedLCPPerformanceSpan, expectedCLSPerformanceSpan, expectedFIDPerformanceSpan, - expectedINPPerformanceSpan, expectedFPPerformanceSpan, expectedFCPPerformanceSpan, expectedMemoryPerformanceSpan, From 4849a8f5525d45d5cc9a093795e54417898e3f14 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Fri, 7 Jun 2024 14:30:17 -0400 Subject: [PATCH 38/41] get element from right place for other web vitals --- .../utils/replayEventTemplates.ts | 2 ++ .../src/util/createPerformanceEntries.ts | 24 ++++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/dev-packages/browser-integration-tests/utils/replayEventTemplates.ts b/dev-packages/browser-integration-tests/utils/replayEventTemplates.ts index 84daef80f938..257c47fbfa9b 100644 --- a/dev-packages/browser-integration-tests/utils/replayEventTemplates.ts +++ b/dev-packages/browser-integration-tests/utils/replayEventTemplates.ts @@ -154,6 +154,7 @@ export const expectedFIDPerformanceSpan = { value: expect.any(Number), rating: expect.any(String), size: expect.any(Number), + nodeId: expect.any(Number), }, }; @@ -166,6 +167,7 @@ export const expectedINPPerformanceSpan = { value: expect.any(Number), rating: expect.any(String), size: expect.any(Number), + nodeId: expect.any(Number), }, }; diff --git a/packages/replay-internal/src/util/createPerformanceEntries.ts b/packages/replay-internal/src/util/createPerformanceEntries.ts index 0e56fc3fc328..4573823ce910 100644 --- a/packages/replay-internal/src/util/createPerformanceEntries.ts +++ b/packages/replay-internal/src/util/createPerformanceEntries.ts @@ -175,38 +175,44 @@ function createResourceEntry( * Add a LCP event to the replay based on a LCP metric. */ export function getLargestContentfulPaint(metric: Metric): ReplayPerformanceEntry { - return getWebVital(metric, 'largest-contentful-paint'); + const lastEntry = metric.entries[metric.entries.length - 1] as (PerformanceEntry & { element?: Element }) | undefined; + const element = lastEntry ? lastEntry.element : undefined; + return getWebVital(metric, 'largest-contentful-paint', element); } /** * Add a CLS event to the replay based on a CLS metric. */ export function getCumulativeLayoutShift(metric: Metric): ReplayPerformanceEntry { - return getWebVital(metric, 'cumulative-layout-shift'); + return getWebVital(metric, 'cumulative-layout-shift', undefined); } /** * Add a FID event to the replay based on a FID metric. */ export function getFirstInputDelay(metric: Metric): ReplayPerformanceEntry { - return getWebVital(metric, 'first-input-delay'); + const lastEntry = metric.entries[metric.entries.length - 1] as (PerformanceEntry & { target?: Element }) | undefined; + const element = lastEntry ? lastEntry.target : undefined; + return getWebVital(metric, 'first-input-delay', element); } /** * Add an INP event to the replay based on an INP metric. */ export function getInteractionToNextPaint(metric: Metric): ReplayPerformanceEntry { - return getWebVital(metric, 'interaction-to-next-paint'); + const lastEntry = metric.entries[metric.entries.length - 1] as (PerformanceEntry & { target?: Element }) | undefined; + const element = lastEntry ? lastEntry.target : undefined; + return getWebVital(metric, 'interaction-to-next-paint', element); } /** * Add an web vital event to the replay based on the web vital metric. */ -export function getWebVital(metric: Metric, name: string): ReplayPerformanceEntry { - const entries = metric.entries; - const lastEntry = entries[entries.length - 1] as (PerformanceEntry & { element?: Element }) | undefined; - const element = lastEntry ? lastEntry.element : undefined; - +export function getWebVital( + metric: Metric, + name: string, + element: Element | undefined, +): ReplayPerformanceEntry { const value = metric.value; const rating = metric.rating; From f2a287ba3a3a9188c09c73c456c84eb0ef1b83e9 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Fri, 7 Jun 2024 15:28:03 -0400 Subject: [PATCH 39/41] forgot to update e2e test --- .../react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts index 74bff4f82713..156c2775f5ff 100644 --- a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts +++ b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/fixtures/ReplayRecordingData.ts @@ -257,6 +257,7 @@ export const ReplayRecordingData = [ value: expect.any(Number), size: expect.any(Number), rating: expect.any(String), + nodeId: 10, }, }, }, From 738508a3b531bc48a9603badc821cad27f52f417 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Fri, 7 Jun 2024 16:57:37 -0400 Subject: [PATCH 40/41] add cls node --- .../suites/replay/customEvents/test.ts | 2 +- .../src/util/createPerformanceEntries.ts | 33 ++++++++++++------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts index d2225b6d400b..053c31c3881e 100644 --- a/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/customEvents/test.ts @@ -49,7 +49,7 @@ sentryTest( expect(replayEvent0).toEqual(getExpectedReplayEvent({ segment_id: 0 })); - page.locator('#img-button').click(); + await page.locator('#img-button').click(); const replayEvent1 = getReplayEvent(await reqPromise1); const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(await reqPromise1); diff --git a/packages/replay-internal/src/util/createPerformanceEntries.ts b/packages/replay-internal/src/util/createPerformanceEntries.ts index 4573823ce910..5c4c9da9efec 100644 --- a/packages/replay-internal/src/util/createPerformanceEntries.ts +++ b/packages/replay-internal/src/util/createPerformanceEntries.ts @@ -46,6 +46,12 @@ export interface Metric { entries: PerformanceEntry[] | PerformanceEventTiming[]; } +interface LayoutShiftAttribution { + node?: Node; + previousRect: DOMRectReadOnly; + currentRect: DOMRectReadOnly; +} + /** * Handler creater for web vitals */ @@ -175,34 +181,37 @@ function createResourceEntry( * Add a LCP event to the replay based on a LCP metric. */ export function getLargestContentfulPaint(metric: Metric): ReplayPerformanceEntry { - const lastEntry = metric.entries[metric.entries.length - 1] as (PerformanceEntry & { element?: Element }) | undefined; - const element = lastEntry ? lastEntry.element : undefined; - return getWebVital(metric, 'largest-contentful-paint', element); + const lastEntry = metric.entries[metric.entries.length - 1] as (PerformanceEntry & { element?: Node }) | undefined; + const node = lastEntry ? lastEntry.element : undefined; + return getWebVital(metric, 'largest-contentful-paint', node); } /** * Add a CLS event to the replay based on a CLS metric. */ export function getCumulativeLayoutShift(metric: Metric): ReplayPerformanceEntry { - return getWebVital(metric, 'cumulative-layout-shift', undefined); + // get first node that shifts + const firstEntry = metric.entries[0] as (PerformanceEntry & { sources?: LayoutShiftAttribution[] }) | undefined; + const node = firstEntry ? firstEntry.sources ? firstEntry.sources[0].node : undefined : undefined; + return getWebVital(metric, 'cumulative-layout-shift', node); } /** * Add a FID event to the replay based on a FID metric. */ export function getFirstInputDelay(metric: Metric): ReplayPerformanceEntry { - const lastEntry = metric.entries[metric.entries.length - 1] as (PerformanceEntry & { target?: Element }) | undefined; - const element = lastEntry ? lastEntry.target : undefined; - return getWebVital(metric, 'first-input-delay', element); + const lastEntry = metric.entries[metric.entries.length - 1] as (PerformanceEntry & { target?: Node }) | undefined; + const node = lastEntry ? lastEntry.target : undefined; + return getWebVital(metric, 'first-input-delay', node); } /** * Add an INP event to the replay based on an INP metric. */ export function getInteractionToNextPaint(metric: Metric): ReplayPerformanceEntry { - const lastEntry = metric.entries[metric.entries.length - 1] as (PerformanceEntry & { target?: Element }) | undefined; - const element = lastEntry ? lastEntry.target : undefined; - return getWebVital(metric, 'interaction-to-next-paint', element); + const lastEntry = metric.entries[metric.entries.length - 1] as (PerformanceEntry & { target?: Node }) | undefined; + const node = lastEntry ? lastEntry.target : undefined; + return getWebVital(metric, 'interaction-to-next-paint', node); } /** @@ -211,7 +220,7 @@ export function getInteractionToNextPaint(metric: Metric): ReplayPerformanceEntr export function getWebVital( metric: Metric, name: string, - element: Element | undefined, + node: Node | undefined, ): ReplayPerformanceEntry { const value = metric.value; const rating = metric.rating; @@ -227,7 +236,7 @@ export function getWebVital( value, size: value, rating, - nodeId: element ? record.mirror.getId(element) : undefined, + nodeId: node ? record.mirror.getId(node) : undefined, }, }; From 853ed14dad36c720e6c3ab97f9bb36bc8c5573ec Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Fri, 7 Jun 2024 17:10:00 -0400 Subject: [PATCH 41/41] lint --- packages/replay-internal/src/util/createPerformanceEntries.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/replay-internal/src/util/createPerformanceEntries.ts b/packages/replay-internal/src/util/createPerformanceEntries.ts index 5c4c9da9efec..b7cca6b05ddf 100644 --- a/packages/replay-internal/src/util/createPerformanceEntries.ts +++ b/packages/replay-internal/src/util/createPerformanceEntries.ts @@ -192,7 +192,7 @@ export function getLargestContentfulPaint(metric: Metric): ReplayPerformanceEntr export function getCumulativeLayoutShift(metric: Metric): ReplayPerformanceEntry { // get first node that shifts const firstEntry = metric.entries[0] as (PerformanceEntry & { sources?: LayoutShiftAttribution[] }) | undefined; - const node = firstEntry ? firstEntry.sources ? firstEntry.sources[0].node : undefined : undefined; + const node = firstEntry ? (firstEntry.sources ? firstEntry.sources[0].node : undefined) : undefined; return getWebVital(metric, 'cumulative-layout-shift', node); }