|
| 1 | +import { expect } from '@playwright/test'; |
| 2 | +import type { ClientReport } from '@sentry/core'; |
| 3 | +import { extractTraceparentData, parseBaggageHeader } from '@sentry/core'; |
| 4 | + |
| 5 | +import { sentryTest } from '../../../../../utils/fixtures'; |
| 6 | +import { |
| 7 | + envelopeRequestParser, |
| 8 | + getMultipleSentryEnvelopeRequests, |
| 9 | + shouldSkipTracingTest, |
| 10 | + waitForClientReportRequest, |
| 11 | +} from '../../../../../utils/helpers'; |
| 12 | + |
| 13 | +const metaTagSampleRand = 0.9; |
| 14 | +const metaTagSampleRate = 0.2; |
| 15 | +const metaTagTraceId = '12345678901234567890123456789012'; |
| 16 | + |
| 17 | +sentryTest.describe('When `sampleLinkedTracesConsistently` is `true` and page contains <meta> tags', () => { |
| 18 | + sentryTest( |
| 19 | + 'Continues negative sampling decision from meta tag across all traces and downstream propagations', |
| 20 | + async ({ getLocalTestUrl, page }) => { |
| 21 | + if (shouldSkipTracingTest()) { |
| 22 | + sentryTest.skip(); |
| 23 | + } |
| 24 | + |
| 25 | + const url = await getLocalTestUrl({ testDir: __dirname }); |
| 26 | + |
| 27 | + let txnsReceived = 0; |
| 28 | + // @ts-expect-error - no need to return something valid here |
| 29 | + getMultipleSentryEnvelopeRequests<Event>(page, 1, { envelopeType: 'transaction' }, () => { |
| 30 | + ++txnsReceived; |
| 31 | + return {}; |
| 32 | + }); |
| 33 | + |
| 34 | + const clientReportPromise = waitForClientReportRequest(page); |
| 35 | + |
| 36 | + await sentryTest.step('Initial pageload', async () => { |
| 37 | + await page.goto(url); |
| 38 | + expect(txnsReceived).toEqual(0); |
| 39 | + }); |
| 40 | + |
| 41 | + await sentryTest.step('Custom instrumented button click', async () => { |
| 42 | + await page.locator('#btn1').click(); |
| 43 | + expect(txnsReceived).toEqual(0); |
| 44 | + }); |
| 45 | + |
| 46 | + await sentryTest.step('Navigation', async () => { |
| 47 | + await page.goto(`${url}#foo`); |
| 48 | + expect(txnsReceived).toEqual(0); |
| 49 | + }); |
| 50 | + |
| 51 | + await sentryTest.step('Make fetch request', async () => { |
| 52 | + let sentryTrace = undefined; |
| 53 | + let baggage = undefined; |
| 54 | + |
| 55 | + await page.route('https://someUrl.com', (route, req) => { |
| 56 | + baggage = req.headers()['baggage']; |
| 57 | + sentryTrace = req.headers()['sentry-trace']; |
| 58 | + return route.fulfill({ status: 200, body: 'ok' }); |
| 59 | + }); |
| 60 | + |
| 61 | + await page.locator('#btn2').click(); |
| 62 | + |
| 63 | + expect(sentryTrace).toBeDefined(); |
| 64 | + expect(baggage).toBeDefined(); |
| 65 | + |
| 66 | + expect(extractTraceparentData(sentryTrace)).toEqual({ |
| 67 | + traceId: expect.not.stringContaining(metaTagTraceId), |
| 68 | + parentSpanId: expect.stringMatching(/^[0-9a-f]{16}$/), |
| 69 | + parentSampled: false, |
| 70 | + }); |
| 71 | + |
| 72 | + expect(parseBaggageHeader(baggage)).toEqual({ |
| 73 | + 'sentry-environment': 'production', |
| 74 | + 'sentry-public_key': 'public', |
| 75 | + 'sentry-sample_rand': `${metaTagSampleRand}`, |
| 76 | + 'sentry-sample_rate': `${metaTagSampleRate}`, |
| 77 | + 'sentry-sampled': 'false', |
| 78 | + 'sentry-trace_id': expect.not.stringContaining(metaTagTraceId), |
| 79 | + 'sentry-transaction': 'custom root span 2', |
| 80 | + }); |
| 81 | + }); |
| 82 | + |
| 83 | + await sentryTest.step('Client report', async () => { |
| 84 | + await page.evaluate(() => { |
| 85 | + Object.defineProperty(document, 'visibilityState', { |
| 86 | + configurable: true, |
| 87 | + get: function () { |
| 88 | + return 'hidden'; |
| 89 | + }, |
| 90 | + }); |
| 91 | + |
| 92 | + // Dispatch the visibilitychange event to notify listeners |
| 93 | + document.dispatchEvent(new Event('visibilitychange')); |
| 94 | + }); |
| 95 | + |
| 96 | + const clientReport = envelopeRequestParser<ClientReport>(await clientReportPromise); |
| 97 | + expect(clientReport).toEqual({ |
| 98 | + timestamp: expect.any(Number), |
| 99 | + discarded_events: [ |
| 100 | + { |
| 101 | + category: 'transaction', |
| 102 | + quantity: 4, |
| 103 | + reason: 'sample_rate', |
| 104 | + }, |
| 105 | + ], |
| 106 | + }); |
| 107 | + }); |
| 108 | + |
| 109 | + await sentryTest.step('Wait for transactions to be discarded', async () => { |
| 110 | + // give it a little longer just in case a txn is pending to be sent |
| 111 | + await page.waitForTimeout(1000); |
| 112 | + expect(txnsReceived).toEqual(0); |
| 113 | + }); |
| 114 | + }, |
| 115 | + ); |
| 116 | +}); |
0 commit comments