|
1 | 1 | import type { Integration } from '@sentry/core'; |
2 | | -import { debug, getGlobalScope, getIsolationScope } from '@sentry/core'; |
| 2 | +import { debug, getGlobalScope, getIsolationScope, SentryNonRecordingSpan } from '@sentry/core'; |
3 | 3 | import * as SentryReact from '@sentry/react'; |
4 | 4 | import { getClient, getCurrentScope, WINDOW } from '@sentry/react'; |
5 | 5 | import { JSDOM } from 'jsdom'; |
6 | 6 | import { afterAll, afterEach, describe, expect, it, vi } from 'vitest'; |
7 | 7 | import { breadcrumbsIntegration, browserTracingIntegration, init } from '../src/client'; |
| 8 | +import { INCOMPLETE_APP_ROUTER_INSTRUMENTATION_TRANSACTION_NAME } from '../src/client/routing/appRouterRoutingInstrumentation'; |
8 | 9 |
|
9 | 10 | const reactInit = vi.spyOn(SentryReact, 'init'); |
10 | 11 | const debugLogSpy = vi.spyOn(debug, 'log'); |
@@ -83,20 +84,68 @@ describe('Client init()', () => { |
83 | 84 | ); |
84 | 85 | }); |
85 | 86 |
|
86 | | - it('adds 404 transaction filter', () => { |
87 | | - init({ |
88 | | - dsn: 'https://dogsarebadatkeepingsecrets@squirrelchasers.ingest.sentry.io/12312012', |
89 | | - tracesSampleRate: 1.0, |
| 87 | + describe('transaction filtering', () => { |
| 88 | + const TEST_DSN_404 = 'https://dogsarebadatkeepingsecrets@squirrelchasers.ingest.sentry.io/12312012'; |
| 89 | + |
| 90 | + it('drops /404 transactions', () => { |
| 91 | + init({ dsn: TEST_DSN_404, tracesSampleRate: 1.0 }); |
| 92 | + const transportSend = vi.spyOn(getClient()!.getTransport()!, 'send'); |
| 93 | + |
| 94 | + // Ensure we have no current span, so our next span is a transaction |
| 95 | + SentryReact.withActiveSpan(null, () => { |
| 96 | + SentryReact.startInactiveSpan({ name: '/404' })?.end(); |
| 97 | + }); |
| 98 | + |
| 99 | + expect(transportSend).not.toHaveBeenCalled(); |
| 100 | + expect(debugLogSpy).toHaveBeenCalledWith(expect.stringContaining('matches `ignoreSpans`')); |
90 | 101 | }); |
91 | | - const transportSend = vi.spyOn(getClient()!.getTransport()!, 'send'); |
92 | 102 |
|
93 | | - // Ensure we have no current span, so our next span is a transaction |
94 | | - SentryReact.withActiveSpan(null, () => { |
95 | | - SentryReact.startInactiveSpan({ name: '/404' })?.end(); |
| 103 | + it('drops incomplete navigation transactions', () => { |
| 104 | + init({ dsn: TEST_DSN_404, tracesSampleRate: 1.0 }); |
| 105 | + const transportSend = vi.spyOn(getClient()!.getTransport()!, 'send'); |
| 106 | + |
| 107 | + // Ensure we have no current span, so our next span is a transaction |
| 108 | + SentryReact.withActiveSpan(null, () => { |
| 109 | + SentryReact.startInactiveSpan({ name: INCOMPLETE_APP_ROUTER_INSTRUMENTATION_TRANSACTION_NAME })?.end(); |
| 110 | + }); |
| 111 | + |
| 112 | + expect(transportSend).not.toHaveBeenCalled(); |
| 113 | + expect(debugLogSpy).toHaveBeenCalledWith(expect.stringContaining('matches `ignoreSpans`')); |
96 | 114 | }); |
97 | 115 |
|
98 | | - expect(transportSend).not.toHaveBeenCalled(); |
99 | | - expect(debugLogSpy).toHaveBeenCalledWith('An event processor returned `null`, will not send event.'); |
| 116 | + describe('span streaming', () => { |
| 117 | + it('drops /404 segment spans', () => { |
| 118 | + init({ dsn: TEST_DSN_404, tracesSampleRate: 1.0, traceLifecycle: 'stream' }); |
| 119 | + |
| 120 | + // Ensure we have no current span, so our next span is a segment span |
| 121 | + const span = SentryReact.withActiveSpan(null, () => SentryReact.startInactiveSpan({ name: '/404' })); |
| 122 | + |
| 123 | + expect(span).toBeInstanceOf(SentryNonRecordingSpan); |
| 124 | + expect(debugLogSpy).toHaveBeenCalledWith(expect.stringContaining('matches `ignoreSpans`')); |
| 125 | + }); |
| 126 | + |
| 127 | + it('drops incomplete navigation segment spans', () => { |
| 128 | + init({ dsn: TEST_DSN_404, tracesSampleRate: 1.0, traceLifecycle: 'stream' }); |
| 129 | + |
| 130 | + // Ensure we have no current span, so our next span is a segment span |
| 131 | + const span = SentryReact.withActiveSpan(null, () => |
| 132 | + SentryReact.startInactiveSpan({ name: INCOMPLETE_APP_ROUTER_INSTRUMENTATION_TRANSACTION_NAME }), |
| 133 | + ); |
| 134 | + |
| 135 | + expect(span).toBeInstanceOf(SentryNonRecordingSpan); |
| 136 | + expect(debugLogSpy).toHaveBeenCalledWith(expect.stringContaining('matches `ignoreSpans`')); |
| 137 | + }); |
| 138 | + |
| 139 | + it('drops /404 non-segment spans', () => { |
| 140 | + init({ dsn: TEST_DSN_404, tracesSampleRate: 1.0, traceLifecycle: 'stream' }); |
| 141 | + |
| 142 | + SentryReact.startSpan({ name: 'parent' }, parent => { |
| 143 | + expect(parent).not.toBeInstanceOf(SentryNonRecordingSpan); |
| 144 | + const child = SentryReact.startInactiveSpan({ name: '/404' }); |
| 145 | + expect(child).toBeInstanceOf(SentryNonRecordingSpan); |
| 146 | + }); |
| 147 | + }); |
| 148 | + }); |
100 | 149 | }); |
101 | 150 |
|
102 | 151 | describe('integrations', () => { |
|
0 commit comments