diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 649f5388ea13..e58995a09015 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -381,7 +381,7 @@ jobs: name: Browser Unit Tests needs: [job_get_metadata, job_build] timeout-minutes: 10 - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 steps: - name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }}) uses: actions/checkout@v4 diff --git a/.github/workflows/flaky-test-detector.yml b/.github/workflows/flaky-test-detector.yml index 1207c9fbf3fd..7774ca1d8d0b 100644 --- a/.github/workflows/flaky-test-detector.yml +++ b/.github/workflows/flaky-test-detector.yml @@ -23,7 +23,7 @@ concurrency: jobs: flaky-detector: - runs-on: ubuntu-20.04 + runs-on: ubuntu-20.04-large-js timeout-minutes: 60 name: 'Check tests for flakiness' # Also skip if PR is from master -> develop diff --git a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureRequestBody/test.ts b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureRequestBody/test.ts index 4f29b0422d2a..bd8050b740aa 100644 --- a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureRequestBody/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureRequestBody/test.ts @@ -3,9 +3,9 @@ import { expect } from '@playwright/test'; import { sentryTest } from '../../../../../utils/fixtures'; import { envelopeRequestParser, waitForErrorRequest } from '../../../../../utils/helpers'; import { - getCustomRecordingEvents, + collectReplayRequests, + getReplayPerformanceSpans, shouldSkipReplayTest, - waitForReplayRequest, } from '../../../../../utils/replayHelpers'; sentryTest('captures text request body', async ({ getLocalTestPath, page, browserName }) => { @@ -30,7 +30,9 @@ sentryTest('captures text request body', async ({ getLocalTestPath, page, browse }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -65,9 +67,8 @@ sentryTest('captures text request body', async ({ getLocalTestPath, page, browse }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'POST', @@ -109,7 +110,9 @@ sentryTest('captures JSON request body', async ({ getLocalTestPath, page, browse }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -144,9 +147,8 @@ sentryTest('captures JSON request body', async ({ getLocalTestPath, page, browse }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'POST', @@ -188,7 +190,9 @@ sentryTest('captures non-text request body', async ({ getLocalTestPath, page, br }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -227,9 +231,8 @@ sentryTest('captures non-text request body', async ({ getLocalTestPath, page, br }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'POST', @@ -271,7 +274,9 @@ sentryTest('captures text request body when matching relative URL', async ({ get }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestUrl({ testDir: __dirname }); await page.goto(url); @@ -306,9 +311,8 @@ sentryTest('captures text request body when matching relative URL', async ({ get }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'POST', @@ -348,7 +352,9 @@ sentryTest('does not capture request body when URL does not match', async ({ get }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -383,9 +389,8 @@ sentryTest('does not capture request body when URL does not match', async ({ get }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'POST', diff --git a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureRequestHeaders/test.ts b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureRequestHeaders/test.ts index d1cc0a58e118..68296df30cdd 100644 --- a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureRequestHeaders/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureRequestHeaders/test.ts @@ -3,9 +3,9 @@ import { expect } from '@playwright/test'; import { sentryTest } from '../../../../../utils/fixtures'; import { envelopeRequestParser, waitForErrorRequest } from '../../../../../utils/helpers'; import { - getCustomRecordingEvents, + collectReplayRequests, + getReplayPerformanceSpans, shouldSkipReplayTest, - waitForReplayRequest, } from '../../../../../utils/replayHelpers'; sentryTest('handles empty/missing request headers', async ({ getLocalTestPath, page, browserName }) => { @@ -28,7 +28,9 @@ sentryTest('handles empty/missing request headers', async ({ getLocalTestPath, p }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -61,9 +63,8 @@ sentryTest('handles empty/missing request headers', async ({ getLocalTestPath, p }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'POST', @@ -100,7 +101,9 @@ sentryTest('captures request headers as POJO', async ({ getLocalTestPath, page, }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -140,9 +143,8 @@ sentryTest('captures request headers as POJO', async ({ getLocalTestPath, page, }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'POST', @@ -184,7 +186,9 @@ sentryTest('captures request headers on Request', async ({ getLocalTestPath, pag }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -224,9 +228,8 @@ sentryTest('captures request headers on Request', async ({ getLocalTestPath, pag }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'POST', @@ -267,7 +270,9 @@ sentryTest('captures request headers as Headers instance', async ({ getLocalTest }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); @@ -308,9 +313,8 @@ sentryTest('captures request headers as Headers instance', async ({ getLocalTest }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'POST', @@ -351,7 +355,9 @@ sentryTest('does not captures request headers if URL does not match', async ({ g }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -391,9 +397,8 @@ sentryTest('does not captures request headers if URL does not match', async ({ g }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'POST', diff --git a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureRequestSize/test.ts b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureRequestSize/test.ts index 3e250bd20df3..bc79df066246 100644 --- a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureRequestSize/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureRequestSize/test.ts @@ -3,9 +3,9 @@ import { expect } from '@playwright/test'; import { sentryTest } from '../../../../../utils/fixtures'; import { envelopeRequestParser, waitForErrorRequest } from '../../../../../utils/helpers'; import { - getCustomRecordingEvents, + collectReplayRequests, + getReplayPerformanceSpans, shouldSkipReplayTest, - waitForReplayRequest, } from '../../../../../utils/replayHelpers'; sentryTest('captures request body size when body is sent', async ({ getLocalTestPath, page }) => { @@ -28,7 +28,9 @@ sentryTest('captures request body size when body is sent', async ({ getLocalTest }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -63,9 +65,8 @@ sentryTest('captures request body size when body is sent', async ({ getLocalTest }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'POST', @@ -112,7 +113,9 @@ sentryTest('captures request size from non-text request body', async ({ getLocal }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -149,9 +152,8 @@ sentryTest('captures request size from non-text request body', async ({ getLocal }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'POST', diff --git a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureResponseBody/test.ts b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureResponseBody/test.ts index b1c0a496476e..c4607fa9cbf7 100644 --- a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureResponseBody/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureResponseBody/test.ts @@ -3,9 +3,9 @@ import { expect } from '@playwright/test'; import { sentryTest } from '../../../../../utils/fixtures'; import { envelopeRequestParser, waitForErrorRequest } from '../../../../../utils/helpers'; import { - getCustomRecordingEvents, + collectReplayRequests, + getReplayPerformanceSpans, shouldSkipReplayTest, - waitForReplayRequest, } from '../../../../../utils/replayHelpers'; sentryTest('captures text response body', async ({ getLocalTestPath, page, browserName }) => { @@ -31,7 +31,9 @@ sentryTest('captures text response body', async ({ getLocalTestPath, page, brows }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -65,9 +67,8 @@ sentryTest('captures text response body', async ({ getLocalTestPath, page, brows }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'POST', @@ -112,7 +113,9 @@ sentryTest('captures JSON response body', async ({ getLocalTestPath, page, brows }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -146,9 +149,8 @@ sentryTest('captures JSON response body', async ({ getLocalTestPath, page, brows }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'POST', @@ -193,7 +195,9 @@ sentryTest('captures non-text response body', async ({ getLocalTestPath, page, b }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -227,9 +231,8 @@ sentryTest('captures non-text response body', async ({ getLocalTestPath, page, b }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'POST', @@ -272,7 +275,9 @@ sentryTest('does not capture response body when URL does not match', async ({ ge }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -306,9 +311,8 @@ sentryTest('does not capture response body when URL does not match', async ({ ge }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'POST', diff --git a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureResponseHeaders/test.ts b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureResponseHeaders/test.ts index 93fe566c6bb6..c587db401e4f 100644 --- a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureResponseHeaders/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureResponseHeaders/test.ts @@ -3,9 +3,9 @@ import { expect } from '@playwright/test'; import { sentryTest } from '../../../../../utils/fixtures'; import { envelopeRequestParser, waitForErrorRequest } from '../../../../../utils/helpers'; import { - getCustomRecordingEvents, + collectReplayRequests, + getReplayPerformanceSpans, shouldSkipReplayTest, - waitForReplayRequest, } from '../../../../../utils/replayHelpers'; sentryTest('handles empty headers', async ({ getLocalTestPath, page, browserName }) => { @@ -30,7 +30,9 @@ sentryTest('handles empty headers', async ({ getLocalTestPath, page, browserName }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -61,9 +63,8 @@ sentryTest('handles empty headers', async ({ getLocalTestPath, page, browserName }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'GET', @@ -105,7 +106,9 @@ sentryTest('captures response headers', async ({ getLocalTestPath, page }) => { }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -136,9 +139,8 @@ sentryTest('captures response headers', async ({ getLocalTestPath, page }) => { }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'GET', @@ -186,7 +188,9 @@ sentryTest('does not capture response headers if URL does not match', async ({ g }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -217,9 +221,8 @@ sentryTest('does not capture response headers if URL does not match', async ({ g }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'GET', diff --git a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureResponseSize/test.ts b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureResponseSize/test.ts index cba36c1814b9..ad3aafe34562 100644 --- a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureResponseSize/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureResponseSize/test.ts @@ -3,9 +3,9 @@ import { expect } from '@playwright/test'; import { sentryTest } from '../../../../../utils/fixtures'; import { envelopeRequestParser, waitForErrorRequest } from '../../../../../utils/helpers'; import { - getCustomRecordingEvents, + collectReplayRequests, + getReplayPerformanceSpans, shouldSkipReplayTest, - waitForReplayRequest, } from '../../../../../utils/replayHelpers'; sentryTest('captures response size from Content-Length header if available', async ({ getLocalTestPath, page }) => { @@ -35,7 +35,10 @@ sentryTest('captures response size from Content-Length header if available', asy }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -67,9 +70,8 @@ sentryTest('captures response size from Content-Length header if available', asy }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'GET', @@ -123,7 +125,10 @@ sentryTest('captures response size without Content-Length header', async ({ getL }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -155,9 +160,8 @@ sentryTest('captures response size without Content-Length header', async ({ getL }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'GET', @@ -208,7 +212,10 @@ sentryTest('captures response size from non-text response body', async ({ getLoc }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -241,9 +248,8 @@ sentryTest('captures response size from non-text response body', async ({ getLoc }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.fetch')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.fetch')).toEqual([ { data: { method: 'POST', diff --git a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureTimestamps/test.ts b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureTimestamps/test.ts index 203a89caaaab..cce931062770 100644 --- a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureTimestamps/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/fetch/captureTimestamps/test.ts @@ -3,9 +3,9 @@ import { expect } from '@playwright/test'; import { sentryTest } from '../../../../../utils/fixtures'; import { envelopeRequestParser, waitForErrorRequest } from '../../../../../utils/helpers'; import { - getCustomRecordingEvents, + collectReplayRequests, + getReplayPerformanceSpans, shouldSkipReplayTest, - waitForReplayRequest, } from '../../../../../utils/replayHelpers'; sentryTest('captures correct timestamps', async ({ getLocalTestPath, page, browserName }) => { @@ -30,7 +30,9 @@ sentryTest('captures correct timestamps', async ({ getLocalTestPath, page, brows }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.fetch'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -50,10 +52,9 @@ sentryTest('captures correct timestamps', async ({ getLocalTestPath, page, brows const request = await requestPromise; const eventData = envelopeRequestParser(request); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); + const { replayRecordingSnapshots } = await replayRequestPromise; - const xhrSpan = performanceSpans1.find(span => span.op === 'resource.fetch')!; + const xhrSpan = getReplayPerformanceSpans(replayRecordingSnapshots).find(span => span.op === 'resource.fetch')!; expect(xhrSpan).toBeDefined(); diff --git a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureRequestBody/test.ts b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureRequestBody/test.ts index b2d4fddaad9e..cd19ba50dd99 100644 --- a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureRequestBody/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureRequestBody/test.ts @@ -3,9 +3,9 @@ import { expect } from '@playwright/test'; import { sentryTest } from '../../../../../utils/fixtures'; import { envelopeRequestParser, waitForErrorRequest } from '../../../../../utils/helpers'; import { - getCustomRecordingEvents, + collectReplayRequests, + getReplayPerformanceSpans, shouldSkipReplayTest, - waitForReplayRequest, } from '../../../../../utils/replayHelpers'; sentryTest('captures text request body', async ({ getLocalTestPath, page, browserName }) => { @@ -29,7 +29,9 @@ sentryTest('captures text request body', async ({ getLocalTestPath, page, browse }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -68,9 +70,8 @@ sentryTest('captures text request body', async ({ getLocalTestPath, page, browse }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.xhr')).toEqual([ { data: { method: 'POST', @@ -110,7 +111,9 @@ sentryTest('captures JSON request body', async ({ getLocalTestPath, page, browse }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -149,9 +152,8 @@ sentryTest('captures JSON request body', async ({ getLocalTestPath, page, browse }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.xhr')).toEqual([ { data: { method: 'POST', @@ -191,7 +193,9 @@ sentryTest('captures non-text request body', async ({ getLocalTestPath, page, br }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -234,9 +238,8 @@ sentryTest('captures non-text request body', async ({ getLocalTestPath, page, br }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.xhr')).toEqual([ { data: { method: 'POST', @@ -276,7 +279,9 @@ sentryTest('captures text request body when matching relative URL', async ({ get }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestUrl({ testDir: __dirname }); await page.goto(url); @@ -315,9 +320,8 @@ sentryTest('captures text request body when matching relative URL', async ({ get }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.xhr')).toEqual([ { data: { method: 'POST', @@ -357,7 +361,9 @@ sentryTest('does not capture request body when URL does not match', async ({ get }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -396,9 +402,8 @@ sentryTest('does not capture request body when URL does not match', async ({ get }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.xhr')).toEqual([ { data: { method: 'POST', diff --git a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureRequestHeaders/test.ts b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureRequestHeaders/test.ts index 7158f034a2ef..c9dd8c455b41 100644 --- a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureRequestHeaders/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureRequestHeaders/test.ts @@ -3,9 +3,9 @@ import { expect } from '@playwright/test'; import { sentryTest } from '../../../../../utils/fixtures'; import { envelopeRequestParser, waitForErrorRequest } from '../../../../../utils/helpers'; import { - getCustomRecordingEvents, + collectReplayRequests, + getReplayPerformanceSpans, shouldSkipReplayTest, - waitForReplayRequest, } from '../../../../../utils/replayHelpers'; sentryTest('captures request headers', async ({ getLocalTestPath, page, browserName }) => { @@ -29,7 +29,9 @@ sentryTest('captures request headers', async ({ getLocalTestPath, page, browserN }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -54,7 +56,7 @@ sentryTest('captures request headers', async ({ getLocalTestPath, page, browserN /* eslint-enable */ }); - const [request, replayReq1] = await Promise.all([requestPromise, replayRequestPromise1]); + const request = await requestPromise; const eventData = envelopeRequestParser(request); expect(eventData.exception?.values).toHaveLength(1); @@ -71,8 +73,8 @@ sentryTest('captures request headers', async ({ getLocalTestPath, page, browserN }, }); - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.xhr')).toEqual([ { data: { method: 'POST', @@ -116,7 +118,9 @@ sentryTest( }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -141,7 +145,7 @@ sentryTest( /* eslint-enable */ }); - const [request, replayReq1] = await Promise.all([requestPromise, replayRequestPromise1]); + const [request] = await Promise.all([requestPromise]); const eventData = envelopeRequestParser(request); @@ -159,8 +163,8 @@ sentryTest( }, }); - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.xhr')).toEqual([ { data: { method: 'POST', diff --git a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureRequestSize/test.ts b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureRequestSize/test.ts index 15e5cc431d35..d33d8a64f1c1 100644 --- a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureRequestSize/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureRequestSize/test.ts @@ -3,9 +3,9 @@ import { expect } from '@playwright/test'; import { sentryTest } from '../../../../../utils/fixtures'; import { envelopeRequestParser, waitForErrorRequest } from '../../../../../utils/helpers'; import { - getCustomRecordingEvents, + collectReplayRequests, + getReplayPerformanceSpans, shouldSkipReplayTest, - waitForReplayRequest, } from '../../../../../utils/replayHelpers'; sentryTest('captures request body size when body is sent', async ({ getLocalTestPath, page, browserName }) => { @@ -29,7 +29,9 @@ sentryTest('captures request body size when body is sent', async ({ getLocalTest }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -68,9 +70,8 @@ sentryTest('captures request body size when body is sent', async ({ getLocalTest }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.xhr')).toEqual([ { data: { method: 'POST', @@ -118,7 +119,9 @@ sentryTest('captures request size from non-text request body', async ({ getLocal }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -159,9 +162,8 @@ sentryTest('captures request size from non-text request body', async ({ getLocal }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.xhr')).toEqual([ { data: { method: 'POST', diff --git a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureResponseBody/test.ts b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureResponseBody/test.ts index 12ef0b2a6068..97e9bcd749fa 100644 --- a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureResponseBody/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureResponseBody/test.ts @@ -3,9 +3,9 @@ import { expect } from '@playwright/test'; import { sentryTest } from '../../../../../utils/fixtures'; import { envelopeRequestParser, waitForErrorRequest } from '../../../../../utils/helpers'; import { - getCustomRecordingEvents, + collectReplayRequests, + getReplayPerformanceSpans, shouldSkipReplayTest, - waitForReplayRequest, } from '../../../../../utils/replayHelpers'; sentryTest('captures text response body', async ({ getLocalTestPath, page, browserName }) => { @@ -33,7 +33,9 @@ sentryTest('captures text response body', async ({ getLocalTestPath, page, brows }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -72,9 +74,8 @@ sentryTest('captures text response body', async ({ getLocalTestPath, page, brows }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.xhr')).toEqual([ { data: { method: 'POST', @@ -118,7 +119,9 @@ sentryTest('captures JSON response body', async ({ getLocalTestPath, page, brows }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -157,9 +160,8 @@ sentryTest('captures JSON response body', async ({ getLocalTestPath, page, brows }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.xhr')).toEqual([ { data: { method: 'POST', @@ -203,7 +205,9 @@ sentryTest('captures JSON response body when responseType=json', async ({ getLoc }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -244,9 +248,8 @@ sentryTest('captures JSON response body when responseType=json', async ({ getLoc }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.xhr')).toEqual([ { data: { method: 'POST', @@ -290,7 +293,9 @@ sentryTest('captures non-text response body', async ({ getLocalTestPath, page, b }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -329,9 +334,8 @@ sentryTest('captures non-text response body', async ({ getLocalTestPath, page, b }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.xhr')).toEqual([ { data: { method: 'POST', @@ -377,7 +381,9 @@ sentryTest( }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -416,9 +422,8 @@ sentryTest( }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.xhr')).toEqual([ { data: { method: 'POST', diff --git a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureResponseHeaders/test.ts b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureResponseHeaders/test.ts index ed2c2f5b2765..754c2adf588f 100644 --- a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureResponseHeaders/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureResponseHeaders/test.ts @@ -3,9 +3,9 @@ import { expect } from '@playwright/test'; import { sentryTest } from '../../../../../utils/fixtures'; import { envelopeRequestParser, waitForErrorRequest } from '../../../../../utils/helpers'; import { - getCustomRecordingEvents, + collectReplayRequests, + getReplayPerformanceSpans, shouldSkipReplayTest, - waitForReplayRequest, } from '../../../../../utils/replayHelpers'; sentryTest('captures response headers', async ({ getLocalTestPath, page, browserName }) => { @@ -36,7 +36,9 @@ sentryTest('captures response headers', async ({ getLocalTestPath, page, browser }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -74,9 +76,8 @@ sentryTest('captures response headers', async ({ getLocalTestPath, page, browser }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.xhr')).toEqual([ { data: { method: 'GET', @@ -127,7 +128,9 @@ sentryTest( }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -165,9 +168,8 @@ sentryTest( }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.xhr')).toEqual([ { data: { method: 'GET', diff --git a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureResponseSize/test.ts b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureResponseSize/test.ts index ea0d6240c8e9..5024e65741e9 100644 --- a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureResponseSize/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureResponseSize/test.ts @@ -3,9 +3,9 @@ import { expect } from '@playwright/test'; import { sentryTest } from '../../../../../utils/fixtures'; import { envelopeRequestParser, waitForErrorRequest } from '../../../../../utils/helpers'; import { - getCustomRecordingEvents, + collectReplayRequests, + getReplayPerformanceSpans, shouldSkipReplayTest, - waitForReplayRequest, } from '../../../../../utils/replayHelpers'; sentryTest( @@ -34,7 +34,9 @@ sentryTest( }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -73,9 +75,8 @@ sentryTest( }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.xhr')).toEqual([ { data: { method: 'GET', @@ -130,7 +131,9 @@ sentryTest('captures response size without Content-Length header', async ({ getL }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -169,9 +172,8 @@ sentryTest('captures response size without Content-Length header', async ({ getL }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.xhr')).toEqual([ { data: { method: 'GET', @@ -223,7 +225,9 @@ sentryTest('captures response size for non-string bodies', async ({ getLocalTest }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -262,9 +266,8 @@ sentryTest('captures response size for non-string bodies', async ({ getLocalTest }, }); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - expect(performanceSpans1.filter(span => span.op === 'resource.xhr')).toEqual([ + const { replayRecordingSnapshots } = await replayRequestPromise; + expect(getReplayPerformanceSpans(replayRecordingSnapshots).filter(span => span.op === 'resource.xhr')).toEqual([ { data: { method: 'POST', diff --git a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureTimestamps/test.ts b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureTimestamps/test.ts index 1a60ceea6509..d5d065f83ec5 100644 --- a/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureTimestamps/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/extendNetworkBreadcrumbs/xhr/captureTimestamps/test.ts @@ -3,9 +3,9 @@ import { expect } from '@playwright/test'; import { sentryTest } from '../../../../../utils/fixtures'; import { envelopeRequestParser, waitForErrorRequest } from '../../../../../utils/helpers'; import { - getCustomRecordingEvents, + collectReplayRequests, + getReplayPerformanceSpans, shouldSkipReplayTest, - waitForReplayRequest, } from '../../../../../utils/replayHelpers'; sentryTest('captures correct timestamps', async ({ getLocalTestPath, page, browserName }) => { @@ -30,7 +30,9 @@ sentryTest('captures correct timestamps', async ({ getLocalTestPath, page, brows }); const requestPromise = waitForErrorRequest(page); - const replayRequestPromise1 = waitForReplayRequest(page, 0); + const replayRequestPromise = collectReplayRequests(page, recordingEvents => { + return getReplayPerformanceSpans(recordingEvents).some(span => span.op === 'resource.xhr'); + }); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); @@ -58,10 +60,8 @@ sentryTest('captures correct timestamps', async ({ getLocalTestPath, page, brows const request = await requestPromise; const eventData = envelopeRequestParser(request); - const replayReq1 = await replayRequestPromise1; - const { performanceSpans: performanceSpans1 } = getCustomRecordingEvents(replayReq1); - - const xhrSpan = performanceSpans1.find(span => span.op === 'resource.xhr')!; + const { replayRecordingSnapshots } = await replayRequestPromise; + const xhrSpan = getReplayPerformanceSpans(replayRecordingSnapshots).find(span => span.op === 'resource.xhr')!; expect(xhrSpan).toBeDefined(); diff --git a/dev-packages/browser-integration-tests/utils/replayHelpers.ts b/dev-packages/browser-integration-tests/utils/replayHelpers.ts index 87283e2ceb75..f0015d2dfb7f 100644 --- a/dev-packages/browser-integration-tests/utils/replayHelpers.ts +++ b/dev-packages/browser-integration-tests/utils/replayHelpers.ts @@ -104,6 +104,49 @@ export function waitForReplayRequest( ); } +/** + * Collect replay requests until a given callback is satisfied. + * This can be used to ensure we wait correctly, + * when we don't know in which request a certain replay event/snapshot will be. + */ +export function collectReplayRequests( + page: Page, + callback: (replayRecordingEvents: RecordingSnapshot[], replayEvents: ReplayEvent[]) => boolean, +): Promise<{ replayEvents: ReplayEvent[]; replayRecordingSnapshots: RecordingSnapshot[] }> { + const replayEvents: ReplayEvent[] = []; + const replayRecordingSnapshots: RecordingSnapshot[] = []; + + // eslint-disable-next-line @typescript-eslint/no-floating-promises + const promise = page.waitForResponse(res => { + const req = res.request(); + + const event = getReplayEventFromRequest(req); + + if (!event) { + return false; + } + + replayEvents.push(event); + replayRecordingSnapshots.push(...getDecompressedRecordingEvents(req)); + + try { + return callback(replayRecordingSnapshots, replayEvents); + } catch { + return false; + } + }); + + const replayRequestPromise = async (): Promise<{ + replayEvents: ReplayEvent[]; + replayRecordingSnapshots: RecordingSnapshot[]; + }> => { + await promise; + return { replayEvents, replayRecordingSnapshots }; + }; + + return replayRequestPromise(); +} + /** * Wait until a callback returns true, collecting all replay responses along the way. * This can be useful when you don't know if stuff will be in one or multiple replay requests. @@ -246,14 +289,14 @@ function getAllCustomRrwebRecordingEvents(recordingEvents: RecordingEvent[]): Cu return recordingEvents.filter(isCustomSnapshot).map(event => event.data); } -function getReplayBreadcrumbs(recordingEvents: RecordingSnapshot[], category?: string): Breadcrumb[] { +export function getReplayBreadcrumbs(recordingEvents: RecordingSnapshot[], category?: string): Breadcrumb[] { return getAllCustomRrwebRecordingEvents(recordingEvents) .filter(data => data.tag === 'breadcrumb') .map(data => data.payload) .filter(payload => !category || payload.category === category); } -function getReplayPerformanceSpans(recordingEvents: RecordingEvent[]): PerformanceSpan[] { +export function getReplayPerformanceSpans(recordingEvents: RecordingSnapshot[]): PerformanceSpan[] { return getAllCustomRrwebRecordingEvents(recordingEvents) .filter(data => data.tag === 'performanceSpan') .map(data => data.payload) as PerformanceSpan[];