Skip to content

Commit a1bd56f

Browse files
chore(wrap): Remove props updateProps, name and children from wrap options type
1 parent 10c9244 commit a1bd56f

File tree

5 files changed

+133
-26
lines changed

5 files changed

+133
-26
lines changed

packages/core/src/js/options.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ export interface ReactNativeClientOptions
294294

295295
export interface ReactNativeWrapperOptions {
296296
/** Props for the root React profiler */
297-
profilerProps?: ProfilerProps;
297+
profilerProps?: Omit<ProfilerProps, 'updateProps' | 'children' | 'name'>;
298298

299299
/** Props for the root touch event boundary */
300300
touchEventBoundaryProps?: TouchEventBoundaryProps;

packages/core/src/js/sdk.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ export function wrap<P extends Record<string, unknown>>(
156156
options?: ReactNativeWrapperOptions
157157
): React.ComponentType<P> {
158158
const profilerProps = {
159-
...(options?.profilerProps ?? {}),
159+
...(options?.profilerProps),
160160
name: RootComponent.displayName ?? 'Root',
161161
updateProps: {}
162162
};

packages/core/src/js/tracing/reactnativeprofiler.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ const ReactNativeProfilerGlobalState = {
1212
},
1313
};
1414

15+
type ProfilerConstructorProps = ConstructorParameters<typeof Profiler>[0];
16+
1517
/**
1618
* Custom profiler for the React Native app root.
1719
*/
1820
export class ReactNativeProfiler extends Profiler {
1921
public readonly name: string = 'ReactNativeProfiler';
2022

21-
public constructor(props: ConstructorParameters<typeof Profiler>[0]) {
23+
public constructor(props: ProfilerConstructorProps) {
2224
_setRootComponentCreationTimestampMs(timestampInSeconds() * 1000);
2325
super(props);
2426
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// We can't test wrap with mock and non mocked components, otherwise it will break the RN testing library.
2+
import { render } from '@testing-library/react-native';
3+
import * as React from 'react';
4+
import type { ReactNativeWrapperOptions } from 'src/js/options';
5+
6+
jest.doMock('../src/js/touchevents', () => {
7+
return {
8+
TouchEventBoundary: ({ children }: { children: React.ReactNode }) => (
9+
// eslint-disable-next-line react/no-unknown-property
10+
<div testID="touch-boundaryID">{children}</div>
11+
),
12+
}
13+
});
14+
15+
jest.doMock('../src/js/tracing', () => {
16+
return {
17+
ReactNativeProfiler: jest.fn(({ children }: { children: React.ReactNode }) => (
18+
// eslint-disable-next-line react/no-unknown-property
19+
<div testID="profilerID">{children}</div>
20+
)),
21+
}
22+
});
23+
24+
jest.doMock('../src/js/feedback/FeedbackWidgetManager', () => {
25+
return {
26+
FeedbackWidgetProvider: ({ children }: { children: React.ReactNode }) => (
27+
// eslint-disable-next-line react/no-unknown-property
28+
<div testID="feedback-widgetID">{children}</div>
29+
),
30+
};
31+
});
32+
33+
34+
import { wrap } from '../src/js/sdk';
35+
import { ReactNativeProfiler } from '../src/js/tracing';
36+
37+
describe('Sentry.wrap', () => {
38+
39+
const DummyComponent: React.FC<{ value?: string }> = ({ value }) => <div>{value}</div>;
40+
41+
it('should not enforce any keys on the wrapped component', () => {
42+
const Mock: React.FC<{ test: 23 }> = () => <></>;
43+
const ActualWrapped = wrap(Mock);
44+
45+
expect(typeof ActualWrapped.defaultProps).toBe(typeof Mock.defaultProps);
46+
});
47+
48+
it('wraps components with Sentry wrappers', () => {
49+
const Wrapped = wrap(DummyComponent);
50+
const renderResult = render(<Wrapped value="wrapped" />);
51+
52+
expect(renderResult.toJSON()).toMatchInlineSnapshot(`
53+
<div
54+
testID="touch-boundaryID"
55+
>
56+
<div
57+
testID="profilerID"
58+
>
59+
<div
60+
testID="feedback-widgetID"
61+
>
62+
<div>
63+
wrapped
64+
</div>
65+
</div>
66+
</div>
67+
</div>
68+
`);
69+
});
70+
71+
describe('ReactNativeProfiler', () => {
72+
it('uses given options when set', () => {
73+
const options: ReactNativeWrapperOptions = {
74+
profilerProps: { disabled: false, includeRender: true, includeUpdates: true },
75+
};
76+
const Wrapped = wrap(DummyComponent, options);
77+
render(<Wrapped value="wrapped" />);
78+
79+
expect(ReactNativeProfiler).toHaveBeenCalledWith(
80+
expect.objectContaining({
81+
name: 'Root',
82+
disabled: false,
83+
includeRender: true,
84+
includeUpdates: true
85+
}),
86+
expect.anything(),
87+
);
88+
89+
expect(ReactNativeProfiler).not.toHaveBeenCalledWith(
90+
expect.objectContaining({
91+
updateProps: expect.anything(),
92+
})
93+
);
94+
});
95+
96+
it('ignore updateProps when set', () => {
97+
const { wrap } = jest.requireActual('../src/js/sdk');
98+
99+
const Wrapped = wrap(DummyComponent, { updateProps: ['prop'] });
100+
render(<Wrapped value="wrapped" />);
101+
102+
expect(ReactNativeProfiler).toHaveBeenCalledWith(
103+
expect.objectContaining({
104+
name: 'Root',
105+
updateProps: {},
106+
}),
107+
expect.anything(),
108+
);
109+
});
110+
});
111+
});

packages/core/test/wrap.test.tsx

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// We can't test wrap with mock and non mocked components, otherwise it will break the RN testing library.
12
import { logger, setCurrentClient } from '@sentry/core';
23
import { render } from '@testing-library/react-native';
34
import * as React from 'react';
@@ -7,30 +8,23 @@ import * as AppRegistry from '../src/js/integrations/appRegistry';
78
import { wrap } from '../src/js/sdk';
89
import { getDefaultTestClientOptions, TestClient } from './mocks/client';
910

10-
describe('Sentry.wrap', () => {
11-
it('should not enforce any keys on the wrapped component', () => {
12-
const Mock: React.FC<{ test: 23 }> = () => <></>;
13-
const ActualWrapped = wrap(Mock);
11+
describe('ReactNativeProfiler', () => {
12+
it('should wrap the component and init with a warning when getAppRegistryIntegration returns undefined', () => {
13+
logger.warn = jest.fn();
14+
const getAppRegistryIntegration = jest.spyOn(AppRegistry, 'getAppRegistryIntegration').mockReturnValueOnce(undefined);
15+
const Mock: React.FC = () => <Text>Test</Text>;
16+
const client = new TestClient(
17+
getDefaultTestClientOptions(),
18+
);
19+
setCurrentClient(client);
1420

15-
expect(typeof ActualWrapped.defaultProps).toBe(typeof Mock.defaultProps);
16-
});
17-
18-
it('should wrap the component and init with a warning when getAppRegistryIntegration returns undefined', () => {
19-
logger.warn = jest.fn();
20-
const getAppRegistryIntegration = jest.spyOn(AppRegistry, 'getAppRegistryIntegration').mockReturnValueOnce(undefined);
21-
const Mock: React.FC = () => <Text>Test</Text>;
22-
const client = new TestClient(
23-
getDefaultTestClientOptions(),
24-
);
25-
setCurrentClient(client);
26-
27-
client.init();
28-
const ActualWrapped = wrap(Mock);
21+
client.init();
22+
const ActualWrapped = wrap(Mock);
2923

30-
const { getByText } = render(<ActualWrapped />);
24+
const { getByText } = render(<ActualWrapped />);
3125

32-
expect(getAppRegistryIntegration).toHaveBeenCalled();
33-
expect(logger.warn).toHaveBeenCalledWith('AppRegistryIntegration.onRunApplication not found or invalid.');
34-
expect(getByText('Test')).toBeTruthy();
26+
expect(getAppRegistryIntegration).toHaveBeenCalled();
27+
expect(logger.warn).toHaveBeenCalledWith('AppRegistryIntegration.onRunApplication not found or invalid.');
28+
expect(getByText('Test')).toBeTruthy();
29+
});
3530
});
36-
});

0 commit comments

Comments
 (0)