diff --git a/CHANGELOG.md b/CHANGELOG.md index 0856bda6d5..b6dd3546c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Fixes + +- `browserReplayIntegration` is no longer included by default on React Native Web ([#4270](https://github.com/getsentry/sentry-react-native/pull/4270), [#4308](https://github.com/getsentry/sentry-react-native/pull/4308)) + ## 5.35.0 ### Fixes diff --git a/src/js/integrations/default.ts b/src/js/integrations/default.ts index bcbac5c2cb..29369b3dad 100644 --- a/src/js/integrations/default.ts +++ b/src/js/integrations/default.ts @@ -10,7 +10,6 @@ import { browserApiErrorsIntegration, browserGlobalHandlersIntegration, browserLinkedErrorsIntegration, - browserReplayIntegration, debugSymbolicatorIntegration, dedupeIntegration, deviceContextIntegration, @@ -120,10 +119,13 @@ export function getDefaultIntegrations(options: ReactNativeClientOptions): Integ (options._experiments && typeof options._experiments.replaysOnErrorSampleRate === 'number') || (options._experiments && typeof options._experiments.replaysSessionSampleRate === 'number') ) { - integrations.push(notWeb() ? mobileReplayIntegration() : browserReplayIntegration()); if (!notWeb()) { + // We can't create and add browserReplayIntegration as it overrides the users supplied one + // The browser replay integration works differently than the rest of default integrations (options as BrowserOptions).replaysOnErrorSampleRate = options._experiments.replaysOnErrorSampleRate; (options as BrowserOptions).replaysSessionSampleRate = options._experiments.replaysSessionSampleRate; + } else { + integrations.push(mobileReplayIntegration()); } } diff --git a/test/sdk.test.ts b/test/sdk.test.ts index 0593ba1667..9921289a0e 100644 --- a/test/sdk.test.ts +++ b/test/sdk.test.ts @@ -648,6 +648,96 @@ describe('Tests the SDK functionality', () => { expect(actualIntegrations).toEqual(expect.arrayContaining([expect.objectContaining({ name: 'ExpoContext' })])); }); + + it('adds mobile replay integration when _experiments.replaysOnErrorSampleRate is set', () => { + init({ + _experiments: { + replaysOnErrorSampleRate: 1.0, + }, + }); + + const actualOptions = usedOptions(); + const actualIntegrations = actualOptions?.integrations; + expect(actualIntegrations).toEqual(expect.arrayContaining([expect.objectContaining({ name: 'MobileReplay' })])); + }); + + it('adds mobile replay integration when _experiments.replaysSessionSampleRate is set', () => { + init({ + _experiments: { + replaysSessionSampleRate: 1.0, + }, + }); + + const actualOptions = usedOptions(); + const actualIntegrations = actualOptions?.integrations; + expect(actualIntegrations).toEqual(expect.arrayContaining([expect.objectContaining({ name: 'MobileReplay' })])); + }); + + it('does not add mobile replay integration when no replay sample rates are set', () => { + init({ + _experiments: {}, + }); + + const actualOptions = usedOptions(); + const actualIntegrations = actualOptions?.integrations; + expect(actualIntegrations).toEqual(expect.not.arrayContaining([expect.objectContaining({ name: 'MobileReplay' })])); + }); + + it('does not add any replay integration when on web even with on error sample rate', () => { + (notWeb as jest.Mock).mockImplementation(() => false); + init({ + _experiments: { + replaysOnErrorSampleRate: 1.0, + }, + }); + + const actualOptions = usedOptions(); + const actualIntegrations = actualOptions?.integrations; + expect(actualIntegrations).toEqual(expect.not.arrayContaining([expect.objectContaining({ name: 'Replay' })])); + expect(actualIntegrations).toEqual(expect.not.arrayContaining([expect.objectContaining({ name: 'MobileReplay' })])); + }); + + it('does not add any replay integration when on web even with session sample rate', () => { + (notWeb as jest.Mock).mockImplementation(() => false); + init({ + _experiments: { + replaysSessionSampleRate: 1.0, + }, + }); + + const actualOptions = usedOptions(); + const actualIntegrations = actualOptions?.integrations; + expect(actualIntegrations).toEqual(expect.not.arrayContaining([expect.objectContaining({ name: 'Replay' })])); + expect(actualIntegrations).toEqual(expect.not.arrayContaining([expect.objectContaining({ name: 'MobileReplay' })])); + }); + + it('does not add any replay integration when on web', () => { + (notWeb as jest.Mock).mockImplementation(() => false); + init({}); + + const actualOptions = usedOptions(); + const actualIntegrations = actualOptions?.integrations; + expect(actualIntegrations).toEqual(expect.not.arrayContaining([expect.objectContaining({ name: 'Replay' })])); + expect(actualIntegrations).toEqual(expect.not.arrayContaining([expect.objectContaining({ name: 'MobileReplay' })])); + }); + + it('converts experimental replay options to standard web options when on web', () => { + (notWeb as jest.Mock).mockImplementation(() => false); + init({ + _experiments: { + replaysOnErrorSampleRate: 0.5, + replaysSessionSampleRate: 0.1, + }, + }); + + const actualOptions = usedOptions(); + expect(actualOptions).toEqual( + expect.objectContaining({ + replaysOnErrorSampleRate: 0.5, + replaysSessionSampleRate: 0.1, + }), + ); + }); }); function createMockedIntegration({ name }: { name?: string } = {}): Integration {