Skip to content

Commit 998a97c

Browse files
committed
test(react): Profiler component
1 parent 4c649e2 commit 998a97c

File tree

6 files changed

+143
-23
lines changed

6 files changed

+143
-23
lines changed

packages/react/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,20 @@
2121
"tslib": "^1.9.3"
2222
},
2323
"peerDependencies": {
24-
"react": "^16.0.0"
24+
"react": "^16.0.0",
25+
"react-dom": "^16.0.0"
2526
},
2627
"devDependencies": {
2728
"@testing-library/react": "^10.0.4",
2829
"@types/react": "^16.9.35",
30+
"@types/react-test-renderer": "^16.9.2",
2931
"jest": "^24.7.1",
3032
"npm-run-all": "^4.1.2",
3133
"prettier": "^1.17.0",
3234
"prettier-check": "^2.0.0",
3335
"react": "^16.0.0",
3436
"react-dom": "^16.0.0",
37+
"react-test-renderer": "^16.13.1",
3538
"rimraf": "^2.6.3",
3639
"rollup": "^1.10.1",
3740
"rollup-plugin-commonjs": "^9.3.4",

packages/react/src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
export * from '@sentry/browser';
1+
import * as Sentry from '@sentry/browser';
2+
3+
export { Sentry };

packages/react/src/profiler.tsx

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,32 +39,36 @@ const getInitActivity = (componentDisplayName: string, timeout = DEFAULT_DURATIO
3939
export const withProfiler = <P extends object>(WrappedComponent: React.ComponentType<P>, timeout?: number) => {
4040
const componentDisplayName = WrappedComponent.displayName || WrappedComponent.name || 'Component';
4141

42-
return class WithProfiler extends React.Component<Omit<P, keyof InjectedProps>> {
42+
return class extends React.Component<Omit<P, keyof InjectedProps>, { activity: number | null }> {
4343
public static displayName: string = `profiler(${componentDisplayName})`;
4444

45-
public activity: number | null = getInitActivity(componentDisplayName, timeout);
45+
public constructor(props: P) {
46+
super(props);
47+
48+
this.state = {
49+
activity: getInitActivity(componentDisplayName, timeout),
50+
};
51+
}
4652

47-
// tslint:disable-next-line: completed-docs
4853
public componentWillUnmount(): void {
4954
this.finishProfile();
5055
}
5156

5257
public finishProfile = () => {
53-
if(!this.activity) {
58+
if (!this.state.activity) {
5459
return;
5560
}
5661

5762
const tracingIntegration = getCurrentHub().getIntegration(TRACING_GETTER);
5863
if (tracingIntegration !== null) {
5964
// tslint:disable-next-line:no-unsafe-any
60-
(tracingIntegration as any).constructor.popActivity(this.activity);
61-
this.activity = null
65+
(tracingIntegration as any).constructor.popActivity(this.state.activity);
66+
this.setState({ activity: null });
6267
}
63-
}
68+
};
6469

65-
// tslint:disable-next-line: completed-docs
6670
public render(): React.ReactNode {
67-
return <WrappedComponent {...this.props as P} finishProfile={this.finishProfile} />;
71+
return <WrappedComponent {...this.props as P} />;
6872
}
6973
};
7074
};

packages/react/test/profiler.test.tsx

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,74 @@
1-
import { render } from '@testing-library/react';
21
import * as React from 'react';
2+
import { create, ReactTestInstance } from 'react-test-renderer';
33

44
import { withProfiler } from '../src/profiler';
55

6+
const mockPushActivity = jest.fn().mockReturnValue(1);
7+
const mockPopActivity = jest.fn();
8+
9+
jest.mock('@sentry/browser', () => ({
10+
getCurrentHub: () => ({
11+
getIntegration: (_: string) => {
12+
class MockIntegration {
13+
public constructor(name: string) {
14+
this.name = name;
15+
}
16+
public name: string;
17+
public setupOnce: () => void = jest.fn();
18+
public static pushActivity: () => void = mockPushActivity;
19+
public static popActivity: () => void = mockPopActivity;
20+
}
21+
22+
return new MockIntegration('test');
23+
},
24+
}),
25+
}));
26+
627
describe('withProfiler', () => {
7-
it("sets displayName properly", () => {
8-
// tslint:disable-next-line: variable-name
9-
const HelloWorld = () => <h1>Hello World</h1>;
10-
11-
// tslint:disable-next-line: variable-name
12-
const ProfiledComponent = withProfiler(HelloWorld);
13-
expect(ProfiledComponent.displayName).toBe("profiler(HelloWorld)")
14-
})
28+
it('sets displayName properly', () => {
29+
const TestComponent = () => <h1>Hello World</h1>;
30+
31+
const ProfiledComponent = withProfiler(TestComponent);
32+
expect(ProfiledComponent.displayName).toBe('profiler(TestComponent)');
33+
});
34+
35+
describe('Tracing Integration', () => {
36+
beforeEach(() => {
37+
mockPushActivity.mockClear();
38+
mockPopActivity.mockClear();
39+
});
40+
41+
it('is called with pushActivity() when mounted', () => {
42+
const ProfiledComponent = withProfiler(() => <h1>Hello World</h1>);
43+
44+
expect(mockPushActivity).toHaveBeenCalledTimes(0);
45+
create(<ProfiledComponent />);
46+
expect(mockPushActivity).toHaveBeenCalledTimes(1);
47+
});
48+
49+
it('is called with popActivity() when unmounted', () => {
50+
const ProfiledComponent = withProfiler(() => <h1>Hello World</h1>);
51+
52+
expect(mockPopActivity).toHaveBeenCalledTimes(0);
53+
54+
const profiler = create(<ProfiledComponent />);
55+
profiler.unmount();
56+
57+
expect(mockPopActivity).toHaveBeenCalledTimes(1);
58+
});
59+
60+
it('calls finishProfile() when unmounting', () => {
61+
const ProfiledComponent = withProfiler(() => <h1>Hello World</h1>);
62+
63+
const mockFinishProfile = jest.fn();
64+
const profiler = create(<ProfiledComponent />);
65+
66+
const instance = profiler.getInstance() as ReactTestInstance & { finishProfile(): void };
67+
instance.finishProfile = mockFinishProfile;
68+
69+
expect(mockFinishProfile).toHaveBeenCalledTimes(0);
70+
profiler.unmount();
71+
expect(mockFinishProfile).toHaveBeenCalledTimes(1);
72+
});
73+
});
1574
});

packages/react/tslint.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
"no-implicit-dependencies": [
55
true,
66
"dev"
7-
]
7+
],
8+
"variable-name": false,
9+
"completed-docs": false
810
}
911
}

yarn.lock

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,6 +1445,13 @@
14451445
dependencies:
14461446
"@types/react" "*"
14471447

1448+
"@types/react-test-renderer@^16.9.2":
1449+
version "16.9.2"
1450+
resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-16.9.2.tgz#e1c408831e8183e5ad748fdece02214a7c2ab6c5"
1451+
integrity sha512-4eJr1JFLIAlWhzDkBCkhrOIWOvOxcCAfQh+jiKg7l/nNZcCIL2MHl2dZhogIFKyHzedVWHaVP1Yydq/Ruu4agw==
1452+
dependencies:
1453+
"@types/react" "*"
1454+
14481455
"@types/react@*", "@types/react@^16.9.35":
14491456
version "16.9.35"
14501457
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.35.tgz#a0830d172e8aadd9bd41709ba2281a3124bbd368"
@@ -1779,11 +1786,32 @@ [email protected]:
17791786
version "0.8.2"
17801787
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
17811788

1782-
agent-base@4, agent-base@5, agent-base@6, agent-base@^4.3.0, agent-base@~4.2.0:
1789+
agent-base@4, agent-base@^4.3.0:
1790+
version "4.3.0"
1791+
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
1792+
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
1793+
dependencies:
1794+
es6-promisify "^5.0.0"
1795+
1796+
agent-base@5:
17831797
version "5.1.1"
17841798
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-5.1.1.tgz#e8fb3f242959db44d63be665db7a8e739537a32c"
17851799
integrity sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==
17861800

1801+
agent-base@6:
1802+
version "6.0.0"
1803+
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.0.tgz#5d0101f19bbfaed39980b22ae866de153b93f09a"
1804+
integrity sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==
1805+
dependencies:
1806+
debug "4"
1807+
1808+
agent-base@~4.2.0:
1809+
version "4.2.1"
1810+
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9"
1811+
integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==
1812+
dependencies:
1813+
es6-promisify "^5.0.0"
1814+
17871815
agentkeepalive@^3.4.1:
17881816
version "3.5.2"
17891817
resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.5.2.tgz#a113924dd3fa24a0bc3b78108c450c2abee00f67"
@@ -4501,6 +4529,18 @@ es-to-primitive@^1.1.1, es-to-primitive@^1.2.0:
45014529
is-date-object "^1.0.1"
45024530
is-symbol "^1.0.2"
45034531

4532+
es6-promise@^4.0.3:
4533+
version "4.2.8"
4534+
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
4535+
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
4536+
4537+
es6-promisify@^5.0.0:
4538+
version "5.0.0"
4539+
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
4540+
integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
4541+
dependencies:
4542+
es6-promise "^4.0.3"
4543+
45044544
escape-html@~1.0.3:
45054545
version "1.0.3"
45064546
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
@@ -9288,7 +9328,7 @@ react-dom@^16.0.0:
92889328
prop-types "^15.6.2"
92899329
scheduler "^0.19.1"
92909330

9291-
react-is@^16.12.0, react-is@^16.8.1:
9331+
react-is@^16.12.0, react-is@^16.8.1, react-is@^16.8.6:
92929332
version "16.13.1"
92939333
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
92949334
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
@@ -9298,6 +9338,16 @@ react-is@^16.8.4:
92989338
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.4.tgz#90f336a68c3a29a096a3d648ab80e87ec61482a2"
92999339
integrity sha512-PVadd+WaUDOAciICm/J1waJaSvgq+4rHE/K70j0PFqKhkTBsPv/82UGQJNXAngz1fOQLLxI6z1sEDmJDQhCTAA==
93009340

9341+
react-test-renderer@^16.13.1:
9342+
version "16.13.1"
9343+
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.13.1.tgz#de25ea358d9012606de51e012d9742e7f0deabc1"
9344+
integrity sha512-Sn2VRyOK2YJJldOqoh8Tn/lWQ+ZiKhyZTPtaO0Q6yNj+QDbmRkVFap6pZPy3YQk8DScRDfyqm/KxKYP9gCMRiQ==
9345+
dependencies:
9346+
object-assign "^4.1.1"
9347+
prop-types "^15.6.2"
9348+
react-is "^16.8.6"
9349+
scheduler "^0.19.1"
9350+
93019351
react@^16.0.0:
93029352
version "16.13.1"
93039353
resolved "https://registry.yarnpkg.com/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e"

0 commit comments

Comments
 (0)