Skip to content

Commit c25dbcd

Browse files
authored
Merge pull request #599 from bugsnag/PLAT-13898/react-router-tests
Add react-router tests
2 parents 316ae7e + 5e8a6cd commit c25dbcd

File tree

3 files changed

+109
-22
lines changed

3 files changed

+109
-22
lines changed

test/browser/features/component-lifecycle-spans.feature

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,18 @@ Feature: Component lifecycle spans
1111
And a span name equals "[ViewLoadPhase/Unmount]Component"
1212
And a span named "[ViewLoadPhase/Update]Component" contains the string array attribute "bugsnag.component.update.props":
1313
| count |
14+
15+
# react router doesn't work in Chrome 61 as AbortController does not exist
16+
@skip_chrome_61
17+
Scenario: Component lifecycle spans are automatically instrumented with React Router
18+
Given I navigate to the test URL "/docs/react-router"
19+
And I click the element "change-route-component-spans"
20+
And I click the element "update-props"
21+
And I click the element "hide-component"
22+
And I click the element "stop-clock"
23+
When I wait to receive 1 trace
24+
Then a span name equals "[ViewLoad/Component]Component"
25+
And a span name equals "[ViewLoadPhase/Mount]Component"
26+
And a span name equals "[ViewLoadPhase/Unmount]Component"
27+
And a span named "[ViewLoadPhase/Update]Component" contains the string array attribute "bugsnag.component.update.props":
28+
| count |

test/browser/features/fixtures/packages/react-router/rollup.config.mjs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,12 @@ export default {
3333
input: 'src/index.jsx',
3434
plugins: [
3535
nodeResolve({ browser: true, jail: path.resolve(`${__dirname}/../..`), extensions: ['.mjs', '.js', '.json', '.node', '.jsx'] }),
36+
babel({
37+
babelHelpers: 'bundled',
38+
presets: ['@babel/preset-react'],
39+
extensions: ['.js', '.jsx']
40+
}),
3641
commonjs(),
37-
babel({ babelHelpers: 'bundled' }),
3842
replace({
3943
preventAssignment: true,
4044
values: {

test/browser/features/fixtures/packages/react-router/src/index.jsx

Lines changed: 89 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,133 @@
1-
import React, { useEffect } from 'react'
2-
import ReactDOM from 'react-dom/client'
1+
import React, { useEffect, useState } from "react"
2+
import ReactDOM from "react-dom/client"
33
import {
44
createBrowserRouter,
55
RouterProvider,
66
Link,
77
Outlet
8-
} from 'react-router-dom';
9-
import BugsnagPerformance from '@bugsnag/browser-performance'
10-
import { ReactRouterRoutingProvider } from '@bugsnag/react-router-performance'
8+
} from "react-router-dom";
9+
import BugsnagPerformance from "@bugsnag/browser-performance"
10+
import { ReactRouterRoutingProvider } from "@bugsnag/react-router-performance"
11+
import { withInstrumentedComponent } from "@bugsnag/plugin-react-performance"
1112

1213
const parameters = new URLSearchParams(window.location.search)
13-
const apiKey = parameters.get('api_key')
14-
const endpoint = parameters.get('endpoint')
14+
const apiKey = parameters.get("api_key")
15+
const endpoint = parameters.get("endpoint")
1516

16-
const basename = '/docs/react-router'
17+
const basename = "/docs/react-router"
1718

1819
function Root() {
1920
return (
2021
<>
2122
<Link id="change-route" to="/contacts/1">
2223
Contact 1
2324
</Link>
25+
<Link id="change-route-component-spans" to="/component-lifecycle-spans">
26+
Component Lifecycle Spans
27+
</Link>
2428
<Outlet />
2529
</>
2630
)
2731
}
2832

2933
function Contact() {
3034
useEffect(() => {
31-
document.title = 'Contact 1'
35+
document.title = "Contact 1"
3236
}, [])
3337

3438
return <div id="contact">Contact</div>
3539
}
3640

41+
function Component({ count }) {
42+
return (
43+
<div>
44+
<p>Wrapped Component</p>
45+
<p>count: {count}</p>
46+
</div>
47+
)
48+
}
49+
50+
const WrappedComponent = withInstrumentedComponent(Component)
51+
52+
function KeepAlive() {
53+
useEffect(() => {
54+
// stop the page from settling until the 'stop-clock' button is
55+
// clicked, otherwise we can't reliably get a first input delay event
56+
57+
const node = document.getElementById("clock")
58+
let time = 0
59+
60+
const interval = setInterval(() => {
61+
node.innerText += `${time++}\n`
62+
}, 50)
63+
64+
document.getElementById("stop-clock").addEventListener("click", () => {
65+
document.title = "New title"
66+
67+
// delay stopping the clock for a bit so the performance observers
68+
// have a chance to fire
69+
setTimeout(() => { clearInterval(interval) }, 1000)
70+
})
71+
72+
return () => {
73+
clearInterval(interval)
74+
}
75+
}, [])
76+
77+
return (
78+
<div>
79+
<button id="stop-clock">Stop</button>
80+
<pre id="clock"></pre>
81+
<p>I'm here to make the layout shift when the clock ticks</p>
82+
</div>
83+
)
84+
}
85+
86+
function ComponentLifecycleSpans() {
87+
const [show, setShow] = useState(true)
88+
const [count, setCount] = useState(0)
89+
90+
return (
91+
<div id="component-lifecycle-spans">
92+
<h1>Component Lifecycle Spans</h1>
93+
<button id="update-props" onClick={() => { setCount(n => n + 1) }}>Update props</button>
94+
<button id="hide-component" onClick={() => { setShow(n => !n) }}>Hide component</button>
95+
{show ? <WrappedComponent count={count} /> : null}
96+
<KeepAlive />
97+
</div>
98+
)
99+
}
100+
37101
const routes = [
38-
{
39-
path: '/',
40-
element: <Root />,
41-
children: [
42-
{
43-
path: 'contacts/:contactId',
44-
element: <Contact />,
45-
},
46-
]
47-
},
102+
{
103+
path: "/",
104+
element: <Root />,
105+
children: [
106+
{
107+
path: "contacts/:contactId",
108+
element: <Contact />
109+
},
110+
{
111+
path: "component-lifecycle-spans",
112+
element: <ComponentLifecycleSpans />
113+
}
114+
]
115+
}
48116
]
49117

50118
const router = createBrowserRouter(routes, { basename })
51119

52120
BugsnagPerformance.start({
53121
apiKey,
54122
endpoint,
55-
maximumBatchSize: 2,
123+
maximumBatchSize: 6,
56124
batchInactivityTimeoutMs: 5000,
57125
autoInstrumentFullPageLoads: false,
58126
autoInstrumentNetworkRequests: false,
59127
routingProvider: new ReactRouterRoutingProvider(routes, basename)
60128
})
61129

62-
ReactDOM.createRoot(document.getElementById('root')).render(
130+
ReactDOM.createRoot(document.getElementById("root")).render(
63131
<React.StrictMode>
64132
<RouterProvider router={router} />
65133
</React.StrictMode>,

0 commit comments

Comments
 (0)