Skip to content

Commit f0d8e74

Browse files
committed
Add integration tests.
1 parent 45d4700 commit f0d8e74

File tree

14 files changed

+10269
-1
lines changed

14 files changed

+10269
-1
lines changed

packages/react/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@
6868
"lint": "run-s lint:prettier lint:eslint",
6969
"lint:eslint": "eslint . --format stylish",
7070
"lint:prettier": "prettier --check \"{src,test,scripts}/**/**.ts\"",
71-
"test": "jest",
71+
"test": "run-s test:unit test:integration",
72+
"test:unit": "jest",
73+
"test:integration": "ts-node ./test/integration/run.ts",
7274
"test:watch": "jest --watch",
7375
"yalc:publish": "ts-node ../../scripts/prepack.ts && yalc publish build --push"
7476
},
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# production
12+
/build
13+
14+
# misc
15+
.DS_Store
16+
.env.local
17+
.env.development.local
18+
.env.test.local
19+
.env.production.local
20+
21+
npm-debug.log*
22+
yarn-debug.log*
23+
yarn-error.log*
24+
25+
/test-results/
26+
/playwright-report/
27+
/playwright/.cache/
28+
29+
!*.d.ts
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
{
2+
"name": "react-create-hash-router-test",
3+
"version": "0.1.0",
4+
"private": true,
5+
"dependencies": {
6+
"@sentry/react": "file:../../..",
7+
"@testing-library/jest-dom": "5.14.1",
8+
"@testing-library/react": "13.0.0",
9+
"@testing-library/user-event": "13.2.1",
10+
"@types/jest": "27.0.1",
11+
"@types/node": "16.7.13",
12+
"@types/react": "18.0.0",
13+
"@types/react-dom": "18.0.0",
14+
"react": "18.2.0",
15+
"react-dom": "18.2.0",
16+
"react-router-dom": "^6.4.1",
17+
"react-scripts": "5.0.1",
18+
"typescript": "4.4.2",
19+
"web-vitals": "2.1.0"
20+
},
21+
"scripts": {
22+
"build": "react-scripts build",
23+
"start": "serve -s build",
24+
"pretest": "run-s build",
25+
"test": "playwright test",
26+
"posttest": "rimraf build node_modules"
27+
},
28+
"eslintConfig": {
29+
"extends": [
30+
"react-app",
31+
"react-app/jest"
32+
]
33+
},
34+
"browserslist": {
35+
"production": [
36+
">0.2%",
37+
"not dead",
38+
"not op_mini all"
39+
],
40+
"development": [
41+
"last 1 chrome version",
42+
"last 1 firefox version",
43+
"last 1 safari version"
44+
]
45+
},
46+
"devDependencies": {
47+
"@playwright/test": "1.31.1",
48+
"serve": "14.0.1"
49+
},
50+
"resolutions": {
51+
"@sentry/browser": "file:../../../../browser",
52+
"@sentry/core": "file:../../../../core",
53+
"@sentry/integrations": "file:../../../../integrations",
54+
"@sentry/node": "file:../../../../node",
55+
"@sentry/react": "file:../../../../react",
56+
"@sentry/replay": "file:../../../../replay",
57+
"@sentry/tracing": "file:../../../../tracing",
58+
"@sentry-internal/tracing": "file:../../../../tracing-internal",
59+
"@sentry/types": "file:../../../../types",
60+
"@sentry/utils": "file:../../../../utils"
61+
},
62+
"volta": {
63+
"node": "16.19.0",
64+
"yarn": "1.22.19"
65+
}
66+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import type { PlaywrightTestConfig } from '@playwright/test';
2+
import { devices } from '@playwright/test';
3+
4+
/**
5+
* See https://playwright.dev/docs/test-configuration.
6+
*/
7+
const config: PlaywrightTestConfig = {
8+
testDir: './tests',
9+
/* Maximum time one test can run for. */
10+
timeout: 60 * 1000,
11+
expect: {
12+
/**
13+
* Maximum time expect() should wait for the condition to be met.
14+
* For example in `await expect(locator).toHaveText();`
15+
*/
16+
timeout: 5000,
17+
},
18+
/* Run tests in files in parallel */
19+
fullyParallel: true,
20+
/* Fail the build on CI if you accidentally left test.only in the source code. */
21+
forbidOnly: !!process.env.CI,
22+
/* Retry on CI only */
23+
retries: 0,
24+
/* Opt out of parallel tests on CI. */
25+
workers: 1,
26+
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
27+
reporter: 'list',
28+
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
29+
use: {
30+
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
31+
actionTimeout: 0,
32+
33+
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
34+
trace: 'on-first-retry',
35+
},
36+
37+
/* Configure projects for major browsers */
38+
projects: [
39+
{
40+
name: 'chromium',
41+
use: {
42+
...devices['Desktop Chrome'],
43+
},
44+
},
45+
// For now we only test Chrome!
46+
// {
47+
// name: 'firefox',
48+
// use: {
49+
// ...devices['Desktop Firefox'],
50+
// },
51+
// },
52+
// {
53+
// name: 'webkit',
54+
// use: {
55+
// ...devices['Desktop Safari'],
56+
// },
57+
// },
58+
],
59+
60+
/* Run your local dev server before starting the tests */
61+
webServer: {
62+
command: 'yarn start',
63+
port: 4321,
64+
env: {
65+
PORT: 4321,
66+
},
67+
},
68+
};
69+
70+
export default config;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
<meta name="theme-color" content="#000000" />
7+
<meta name="description" content="Web site created using create-react-app" />
8+
<title>React App</title>
9+
</head>
10+
<body>
11+
<noscript>You need to enable JavaScript to run this app.</noscript>
12+
<div id="root"></div>
13+
<!--
14+
This HTML file is a template.
15+
If you open it directly in the browser, you will see an empty page.
16+
17+
You can add webfonts, meta tags, or analytics to this file.
18+
The build step will place the bundled scripts into the <body> tag.
19+
20+
To begin the development, run `npm start` or `yarn start`.
21+
To create a production bundle, use `npm run build` or `yarn build`.
22+
-->
23+
</body>
24+
</html>
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import React from 'react';
2+
import ReactDOM from 'react-dom/client';
3+
import * as Sentry from '@sentry/react';
4+
import {
5+
useLocation,
6+
useNavigationType,
7+
createRoutesFromChildren,
8+
matchRoutes,
9+
RouterProvider,
10+
createHashRouter,
11+
} from 'react-router-dom';
12+
import Index from './pages/Index';
13+
import User from './pages/User';
14+
15+
Sentry.init({
16+
// environment: 'qa', // dynamic sampling bias to keep transactions
17+
dsn: 'https://[email protected]/1337',
18+
integrations: [
19+
new Sentry.BrowserTracing({
20+
routingInstrumentation: Sentry.reactRouterV6Instrumentation(
21+
React.useEffect,
22+
useLocation,
23+
useNavigationType,
24+
createRoutesFromChildren,
25+
matchRoutes,
26+
),
27+
}),
28+
],
29+
debug: true,
30+
// We recommend adjusting this value in production, or using tracesSampler
31+
// for finer control
32+
tracesSampleRate: 1.0,
33+
});
34+
35+
const sentryCreateHashRouter = Sentry.wrapCreateBrowserRouter(createHashRouter);
36+
37+
const router = sentryCreateHashRouter([
38+
{
39+
path: '/',
40+
element: <Index />,
41+
},
42+
{
43+
path: '/user/:id',
44+
element: <User />,
45+
},
46+
]);
47+
48+
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
49+
50+
root.render(<RouterProvider router={router} />);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import * as React from 'react';
2+
import * as Sentry from '@sentry/react';
3+
import { Link } from 'react-router-dom';
4+
5+
const Index = () => {
6+
return (
7+
<>
8+
<input
9+
type="button"
10+
value="Capture Exception"
11+
id="exception-button"
12+
onClick={() => {
13+
Sentry.captureException(new Error('I am an error!'));
14+
}}
15+
/>
16+
<Link to="/user/5" id="navigation">
17+
navigate
18+
</Link>
19+
</>
20+
);
21+
};
22+
23+
export default Index;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import * as React from 'react';
2+
3+
const User = () => {
4+
return <p>I am a blank page :)</p>;
5+
};
6+
7+
export default User;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/// <reference types="react-scripts" />
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { Transaction } from '@sentry/types';
2+
import { getMultipleSentryEnvelopeRequests } from '../../utils';
3+
import { test, expect } from '@playwright/test';
4+
5+
test('Sends an error to Sentry', async ({ page }) => {
6+
await page.goto('/');
7+
8+
await page.waitForTimeout(2000);
9+
10+
const [, errors] = await Promise.all([
11+
page.click('#exception-button'),
12+
getMultipleSentryEnvelopeRequests<Event>(page, 1),
13+
]);
14+
15+
expect(errors[0].exception?.values?.[0].value).toBe('I am an error!');
16+
});
17+
18+
test('Sends a pageload transaction to Sentry', async ({ page }) => {
19+
const [pageloadEnvelope] = await getMultipleSentryEnvelopeRequests<Transaction>(page, 1, {
20+
url: '/',
21+
});
22+
23+
expect(pageloadEnvelope.contexts?.trace?.op).toBe('pageload');
24+
expect(pageloadEnvelope.transaction).toBe('/');
25+
});
26+
27+
test('Sends a parameterized pageload transaction to Sentry', async ({ page }) => {
28+
const [pageloadEnvelope] = await getMultipleSentryEnvelopeRequests<Transaction>(page, 1, {
29+
url: '/#/user/123',
30+
});
31+
32+
expect(pageloadEnvelope.contexts?.trace?.op).toBe('pageload');
33+
expect(pageloadEnvelope.transaction).toBe('/user/:id');
34+
});
35+
36+
test('Sends a navigation transaction to Sentry', async ({ page }) => {
37+
await page.goto('/');
38+
39+
await page.waitForTimeout(2000);
40+
41+
const [, transactions] = await Promise.all([
42+
page.click('#navigation'),
43+
getMultipleSentryEnvelopeRequests<Transaction>(page, 1),
44+
]);
45+
46+
expect(transactions[0].contexts?.trace?.op).toBe('navigation');
47+
expect(transactions[0].transaction).toBe('/user/:id');
48+
});
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"compilerOptions": {
3+
"target": "es5",
4+
"lib": ["dom", "dom.iterable", "esnext"],
5+
"allowJs": true,
6+
"skipLibCheck": true,
7+
"esModuleInterop": true,
8+
"allowSyntheticDefaultImports": true,
9+
"strict": true,
10+
"forceConsistentCasingInFileNames": true,
11+
"noFallthroughCasesInSwitch": true,
12+
"module": "esnext",
13+
"moduleResolution": "node",
14+
"resolveJsonModule": true,
15+
"isolatedModules": true,
16+
"noEmit": true,
17+
"jsx": "react"
18+
},
19+
"include": ["src", "tests", "../utils.ts"]
20+
}

0 commit comments

Comments
 (0)