|
| 1 | +import { getGlobalObject } from '@sentry/utils'; |
| 2 | +import { JSDOM } from 'jsdom'; |
1 | 3 | import { default as Router } from 'next/router';
|
2 | 4 |
|
3 | 5 | import { nextRouterInstrumentation } from '../../src/performance/client';
|
@@ -28,28 +30,156 @@ describe('client', () => {
|
28 | 30 | });
|
29 | 31 |
|
30 | 32 | describe('nextRouterInstrumentation', () => {
|
| 33 | + const originalGlobalDocument = getGlobalObject<Window>().document; |
| 34 | + |
| 35 | + function setUpNextPage(pageProperties: { |
| 36 | + url: string; |
| 37 | + route: string; |
| 38 | + query: any; |
| 39 | + props: any; |
| 40 | + hasNextData: boolean; |
| 41 | + }) { |
| 42 | + const dom = new JSDOM( |
| 43 | + // Just some example what a __NEXT_DATA__ tag might look like |
| 44 | + pageProperties.hasNextData |
| 45 | + ? `<body> |
| 46 | + <script id="__NEXT_DATA__" type="application/json"> |
| 47 | + { |
| 48 | + "props": ${JSON.stringify(pageProperties.props)}, |
| 49 | + "page": "${pageProperties.route}", |
| 50 | + "query": ${JSON.stringify(pageProperties.query)}, |
| 51 | + "buildId": "y76hvndNJBAithejdVGLW", |
| 52 | + "isFallback": false, |
| 53 | + "gssp": true, |
| 54 | + "appGip": true, |
| 55 | + "scriptLoader": [] |
| 56 | + } |
| 57 | + </script> |
| 58 | + </body>` |
| 59 | + : '<body><h1>No next data :(</h1></body>', |
| 60 | + { url: pageProperties.url }, |
| 61 | + ); |
| 62 | + |
| 63 | + Object.defineProperty(global, 'document', { value: dom.window.document, writable: true, configurable: true }); |
| 64 | + } |
| 65 | + |
| 66 | + afterEach(() => { |
| 67 | + // Clean up JSDom |
| 68 | + Object.defineProperty(global, 'document', { |
| 69 | + value: originalGlobalDocument, |
| 70 | + writable: true, |
| 71 | + configurable: true, |
| 72 | + }); |
| 73 | + }); |
| 74 | + |
31 | 75 | it('waits for Router.ready()', () => {
|
| 76 | + setUpNextPage({ url: 'https://example.com/', route: '/', query: {}, props: {}, hasNextData: false }); |
32 | 77 | const mockStartTransaction = jest.fn();
|
33 | 78 | expect(readyCalled).toBe(false);
|
34 | 79 | nextRouterInstrumentation(mockStartTransaction);
|
35 | 80 | expect(readyCalled).toBe(true);
|
36 | 81 | });
|
37 | 82 |
|
38 |
| - it('creates a pageload transaction', () => { |
39 |
| - const mockStartTransaction = jest.fn(); |
40 |
| - nextRouterInstrumentation(mockStartTransaction); |
41 |
| - expect(mockStartTransaction).toHaveBeenCalledTimes(1); |
42 |
| - expect(mockStartTransaction).toHaveBeenLastCalledWith({ |
43 |
| - name: '/[user]/posts/[id]', |
44 |
| - op: 'pageload', |
45 |
| - tags: { |
46 |
| - 'routing.instrumentation': 'next-router', |
| 83 | + it.each([ |
| 84 | + [ |
| 85 | + 'https://example.com/lforst/posts/1337?q=42', |
| 86 | + '/[user]/posts/[id]', |
| 87 | + { user: 'lforst', id: '1337', q: '42' }, |
| 88 | + { |
| 89 | + _sentryGetInitialPropsTraceId: 'SOME_TRACE_ID', |
| 90 | + _sentryGetInitialPropsBaggage: |
| 91 | + 'other=vendor,foo=bar,third=party,last=item,sentry-release=2.1.0,sentry-environment=myEnv', |
47 | 92 | },
|
48 |
| - metadata: { |
49 |
| - source: 'route', |
| 93 | + true, |
| 94 | + { |
| 95 | + name: '/[user]/posts/[id]', |
| 96 | + op: 'pageload', |
| 97 | + tags: { |
| 98 | + 'routing.instrumentation': 'next-router', |
| 99 | + }, |
| 100 | + data: { |
| 101 | + user: 'lforst', |
| 102 | + id: '1337', |
| 103 | + q: '42', |
| 104 | + }, |
| 105 | + metadata: { |
| 106 | + source: 'route', |
| 107 | + baggage: [{ environment: 'myEnv', release: '2.1.0' }, '', true], |
| 108 | + }, |
| 109 | + traceId: 'SOME_TRACE_ID', |
50 | 110 | },
|
51 |
| - }); |
52 |
| - }); |
| 111 | + ], |
| 112 | + [ |
| 113 | + 'https://example.com/static', |
| 114 | + '/static', |
| 115 | + {}, |
| 116 | + { |
| 117 | + pageProps: { |
| 118 | + _sentryGetServerSidePropsTraceId: 'SOME_TRACE_ID', |
| 119 | + _sentryGetServerSidePropsBaggage: |
| 120 | + 'other=vendor,foo=bar,third=party,last=item,sentry-release=2.1.0,sentry-environment=myEnv', |
| 121 | + }, |
| 122 | + }, |
| 123 | + true, |
| 124 | + { |
| 125 | + name: '/static', |
| 126 | + op: 'pageload', |
| 127 | + tags: { |
| 128 | + 'routing.instrumentation': 'next-router', |
| 129 | + }, |
| 130 | + data: {}, |
| 131 | + metadata: { |
| 132 | + source: 'route', |
| 133 | + baggage: [{ environment: 'myEnv', release: '2.1.0' }, '', true], |
| 134 | + }, |
| 135 | + traceId: 'SOME_TRACE_ID', |
| 136 | + }, |
| 137 | + ], |
| 138 | + [ |
| 139 | + 'https://example.com/', |
| 140 | + '/', |
| 141 | + {}, |
| 142 | + {}, |
| 143 | + true, |
| 144 | + { |
| 145 | + name: '/', |
| 146 | + op: 'pageload', |
| 147 | + tags: { |
| 148 | + 'routing.instrumentation': 'next-router', |
| 149 | + }, |
| 150 | + data: {}, |
| 151 | + metadata: { |
| 152 | + source: 'route', |
| 153 | + }, |
| 154 | + }, |
| 155 | + ], |
| 156 | + [ |
| 157 | + 'https://example.com/lforst/posts/1337?q=42', |
| 158 | + '/', |
| 159 | + {}, |
| 160 | + {}, |
| 161 | + false, // no __NEXT_DATA__ tag |
| 162 | + { |
| 163 | + name: '/lforst/posts/1337', |
| 164 | + op: 'pageload', |
| 165 | + tags: { |
| 166 | + 'routing.instrumentation': 'next-router', |
| 167 | + }, |
| 168 | + metadata: { |
| 169 | + source: 'url', |
| 170 | + }, |
| 171 | + }, |
| 172 | + ], |
| 173 | + ])( |
| 174 | + 'creates a pageload transaction (#%#)', |
| 175 | + (url, route, query, props, hasNextData, expectedStartTransactionCall) => { |
| 176 | + const mockStartTransaction = jest.fn(); |
| 177 | + setUpNextPage({ url, route, query, props, hasNextData }); |
| 178 | + nextRouterInstrumentation(mockStartTransaction); |
| 179 | + expect(mockStartTransaction).toHaveBeenCalledTimes(1); |
| 180 | + expect(mockStartTransaction).toHaveBeenLastCalledWith(expectedStartTransactionCall); |
| 181 | + }, |
| 182 | + ); |
53 | 183 |
|
54 | 184 | it('does not create a pageload transaction if option not given', () => {
|
55 | 185 | const mockStartTransaction = jest.fn();
|
|
0 commit comments