From eb3a3df09f8e395a95f583a2256e592ccf5d212e Mon Sep 17 00:00:00 2001 From: Oleh Aloshkin Date: Sat, 27 Jan 2024 02:14:18 +0100 Subject: [PATCH 1/4] Fixed attachReduxState option --- packages/react/src/redux.ts | 7 ++++--- packages/react/test/redux.test.ts | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/react/src/redux.ts b/packages/react/src/redux.ts index 38f99d7af825..d98b784993b0 100644 --- a/packages/react/src/redux.ts +++ b/packages/react/src/redux.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { addEventProcessor, getClient, getCurrentScope } from '@sentry/browser'; +import { getClient, getCurrentScope } from '@sentry/browser'; import type { Scope } from '@sentry/types'; import { addNonEnumerableProperty } from '@sentry/utils'; @@ -96,8 +96,10 @@ function createReduxEnhancer(enhancerOptions?: Partial): return (next: StoreEnhancerStoreCreator): StoreEnhancerStoreCreator => (reducer: Reducer, initialState?: PreloadedState) => { + const scope = getCurrentScope(); + options.attachReduxState && - addEventProcessor((event, hint) => { + scope.addEventProcessor((event, hint) => { try { // @ts-expect-error try catch to reduce bundle size if (event.type === undefined && event.contexts.state.state.type === 'redux') { @@ -116,7 +118,6 @@ function createReduxEnhancer(enhancerOptions?: Partial): const sentryReducer: Reducer = (state, action): S => { const newState = reducer(state, action); - const scope = getCurrentScope(); /* Action breadcrumbs */ const transformedAction = options.actionTransformer(action); if (typeof transformedAction !== 'undefined' && transformedAction !== null) { diff --git a/packages/react/test/redux.test.ts b/packages/react/test/redux.test.ts index 0ce064365eeb..01249278a82a 100644 --- a/packages/react/test/redux.test.ts +++ b/packages/react/test/redux.test.ts @@ -5,6 +5,7 @@ import { createReduxEnhancer } from '../src/redux'; const mockAddBreadcrumb = jest.fn(); const mockSetContext = jest.fn(); +const mockAddEventProcessor = Sentry.addEventProcessor as jest.Mock; jest.mock('@sentry/browser', () => ({ ...jest.requireActual('@sentry/browser'), @@ -12,13 +13,12 @@ jest.mock('@sentry/browser', () => ({ return { addBreadcrumb: mockAddBreadcrumb, setContext: mockSetContext, + addEventProcessor: mockAddEventProcessor, }; }, addEventProcessor: jest.fn(), })); -const mockAddEventProcessor = Sentry.addEventProcessor as jest.Mock; - afterEach(() => { mockAddBreadcrumb.mockReset(); mockSetContext.mockReset(); From e737dd39c9715e9930973f801ffa6b6031291d6f Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Mon, 29 Jan 2024 08:53:04 +0000 Subject: [PATCH 2/4] Lint --- CONTRIBUTING.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9ab617cdeffe..812aaa870df5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -37,10 +37,11 @@ able to use it. From the top level of the repo, there are three commands availab dependencies (`utils`, `core`, `browser`, etc), and all packages which depend on it (currently `gatsby` and `nextjs`)) - `yarn build:dev:watch`, which runs `yarn build:dev` in watch mode (recommended) -You can also run a production build via `yarn build`, which will build everything except for the tarballs for publishing to NPM. -You can use this if you want to bundle Sentry yourself. The build output can be found in the packages `build/` folder, e.g. `packages/browser/build`. -Bundled files can be found in `packages/browser/build/bundles`. -Note that there are no guarantees about the produced file names etc., so make sure to double check which files are generated after upgrading. +You can also run a production build via `yarn build`, which will build everything except for the tarballs for publishing +to NPM. You can use this if you want to bundle Sentry yourself. The build output can be found in the packages `build/` +folder, e.g. `packages/browser/build`. Bundled files can be found in `packages/browser/build/bundles`. Note that there +are no guarantees about the produced file names etc., so make sure to double check which files are generated after +upgrading. ## Testing SDK Packages Locally From 14f06624727b7fa23131b6f3e1f3964140f66020 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Mon, 29 Jan 2024 08:56:54 +0000 Subject: [PATCH 3/4] Add processor to global scope --- packages/react/src/redux.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/react/src/redux.ts b/packages/react/src/redux.ts index d98b784993b0..f177f0975ba0 100644 --- a/packages/react/src/redux.ts +++ b/packages/react/src/redux.ts @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { getClient, getCurrentScope } from '@sentry/browser'; +import { getGlobalScope } from '@sentry/core'; import type { Scope } from '@sentry/types'; import { addNonEnumerableProperty } from '@sentry/utils'; @@ -96,10 +97,8 @@ function createReduxEnhancer(enhancerOptions?: Partial): return (next: StoreEnhancerStoreCreator): StoreEnhancerStoreCreator => (reducer: Reducer, initialState?: PreloadedState) => { - const scope = getCurrentScope(); - options.attachReduxState && - scope.addEventProcessor((event, hint) => { + getGlobalScope().addEventProcessor((event, hint) => { try { // @ts-expect-error try catch to reduce bundle size if (event.type === undefined && event.contexts.state.state.type === 'redux') { @@ -118,6 +117,8 @@ function createReduxEnhancer(enhancerOptions?: Partial): const sentryReducer: Reducer = (state, action): S => { const newState = reducer(state, action); + const scope = getCurrentScope(); + /* Action breadcrumbs */ const transformedAction = options.actionTransformer(action); if (typeof transformedAction !== 'undefined' && transformedAction !== null) { From e348ecb140c9be998c945bfb0276300fac383394 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Mon, 29 Jan 2024 09:17:37 +0000 Subject: [PATCH 4/4] Fix tests --- packages/react/src/redux.ts | 3 +-- packages/react/test/redux.test.ts | 32 +++++++++++++++++-------------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/packages/react/src/redux.ts b/packages/react/src/redux.ts index f177f0975ba0..fb3ca2fa073f 100644 --- a/packages/react/src/redux.ts +++ b/packages/react/src/redux.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { getClient, getCurrentScope } from '@sentry/browser'; -import { getGlobalScope } from '@sentry/core'; +import { getClient, getCurrentScope, getGlobalScope } from '@sentry/core'; import type { Scope } from '@sentry/types'; import { addNonEnumerableProperty } from '@sentry/utils'; diff --git a/packages/react/test/redux.test.ts b/packages/react/test/redux.test.ts index 01249278a82a..537c133cd3fd 100644 --- a/packages/react/test/redux.test.ts +++ b/packages/react/test/redux.test.ts @@ -5,15 +5,19 @@ import { createReduxEnhancer } from '../src/redux'; const mockAddBreadcrumb = jest.fn(); const mockSetContext = jest.fn(); -const mockAddEventProcessor = Sentry.addEventProcessor as jest.Mock; +const mockGlobalScopeAddEventProcessor = jest.fn(); -jest.mock('@sentry/browser', () => ({ - ...jest.requireActual('@sentry/browser'), +jest.mock('@sentry/core', () => ({ + ...jest.requireActual('@sentry/core'), getCurrentScope() { return { addBreadcrumb: mockAddBreadcrumb, setContext: mockSetContext, - addEventProcessor: mockAddEventProcessor, + }; + }, + getGlobalScope() { + return { + addEventProcessor: mockGlobalScopeAddEventProcessor, }; }, addEventProcessor: jest.fn(), @@ -22,7 +26,7 @@ jest.mock('@sentry/browser', () => ({ afterEach(() => { mockAddBreadcrumb.mockReset(); mockSetContext.mockReset(); - mockAddEventProcessor.mockReset(); + mockGlobalScopeAddEventProcessor.mockReset(); }); describe('createReduxEnhancer', () => { @@ -257,9 +261,9 @@ describe('createReduxEnhancer', () => { Redux.createStore((state = initialState) => state, enhancer); - expect(mockAddEventProcessor).toHaveBeenCalledTimes(1); + expect(mockGlobalScopeAddEventProcessor).toHaveBeenCalledTimes(1); - const callbackFunction = mockAddEventProcessor.mock.calls[0][0]; + const callbackFunction = mockGlobalScopeAddEventProcessor.mock.calls[0][0]; const mockEvent = { contexts: { @@ -306,7 +310,7 @@ describe('createReduxEnhancer', () => { Redux.createStore((state = initialState) => state, enhancer); - expect(mockAddEventProcessor).toHaveBeenCalledTimes(0); + expect(mockGlobalScopeAddEventProcessor).toHaveBeenCalledTimes(0); }); it('does not attach when state.type is not redux', () => { @@ -318,9 +322,9 @@ describe('createReduxEnhancer', () => { Redux.createStore((state = initialState) => state, enhancer); - expect(mockAddEventProcessor).toHaveBeenCalledTimes(1); + expect(mockGlobalScopeAddEventProcessor).toHaveBeenCalledTimes(1); - const callbackFunction = mockAddEventProcessor.mock.calls[0][0]; + const callbackFunction = mockGlobalScopeAddEventProcessor.mock.calls[0][0]; const mockEvent = { contexts: { @@ -353,9 +357,9 @@ describe('createReduxEnhancer', () => { Redux.createStore((state = initialState) => state, enhancer); - expect(mockAddEventProcessor).toHaveBeenCalledTimes(1); + expect(mockGlobalScopeAddEventProcessor).toHaveBeenCalledTimes(1); - const callbackFunction = mockAddEventProcessor.mock.calls[0][0]; + const callbackFunction = mockGlobalScopeAddEventProcessor.mock.calls[0][0]; const mockEvent = { contexts: { @@ -385,9 +389,9 @@ describe('createReduxEnhancer', () => { Redux.createStore((state = initialState) => state, enhancer); - expect(mockAddEventProcessor).toHaveBeenCalledTimes(1); + expect(mockGlobalScopeAddEventProcessor).toHaveBeenCalledTimes(1); - const callbackFunction = mockAddEventProcessor.mock.calls[0][0]; + const callbackFunction = mockGlobalScopeAddEventProcessor.mock.calls[0][0]; const mockEvent = { type: 'not_redux',