Skip to content

Commit fd80fe1

Browse files
committed
test(remix): Add a boilerplate for Remix SDK integration tests.
1 parent f1cfc70 commit fd80fe1

File tree

15 files changed

+7271
-0
lines changed

15 files changed

+7271
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": ["@remix-run/eslint-config", "@remix-run/eslint-config/node"]
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
node_modules
2+
3+
/.cache
4+
/build
5+
/public/build
6+
.env
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { RemixBrowser, useLocation, useMatches } from '@remix-run/react';
2+
import { hydrate } from 'react-dom';
3+
import * as Sentry from '@sentry/remix';
4+
import { useEffect } from 'react';
5+
6+
Sentry.init({
7+
dsn: 'https://[email protected]/1337',
8+
tracesSampleRate: 1,
9+
integrations: [
10+
new Sentry.BrowserTracing({
11+
routingInstrumentation: Sentry.remixRouterInstrumentation(useEffect, useLocation, useMatches),
12+
}),
13+
],
14+
});
15+
16+
hydrate(<RemixBrowser />, document);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import type { EntryContext } from '@remix-run/node';
2+
import { RemixServer } from '@remix-run/react';
3+
import { renderToString } from 'react-dom/server';
4+
import * as Sentry from '@sentry/remix';
5+
6+
Sentry.init({
7+
dsn: 'https://[email protected]/1337',
8+
tracesSampleRate: 1,
9+
});
10+
11+
export default function handleRequest(
12+
request: Request,
13+
responseStatusCode: number,
14+
responseHeaders: Headers,
15+
remixContext: EntryContext,
16+
) {
17+
let markup = renderToString(<RemixServer context={remixContext} url={request.url} />);
18+
19+
responseHeaders.set('Content-Type', 'text/html');
20+
21+
return new Response('<!DOCTYPE html>' + markup, {
22+
status: responseStatusCode,
23+
headers: responseHeaders,
24+
});
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import type { MetaFunction } from '@remix-run/node';
2+
import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react';
3+
import { withSentry } from '@sentry/remix';
4+
5+
export const meta: MetaFunction = () => ({
6+
charset: 'utf-8',
7+
title: 'New Remix App',
8+
viewport: 'width=device-width,initial-scale=1',
9+
});
10+
11+
function App() {
12+
return (
13+
<html lang="en">
14+
<head>
15+
<Meta />
16+
<Links />
17+
</head>
18+
<body>
19+
<Outlet />
20+
<ScrollRestoration />
21+
<Scripts />
22+
<LiveReload />
23+
</body>
24+
</html>
25+
);
26+
}
27+
28+
export default withSentry(App);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export default function Index() {
2+
return (
3+
<div>
4+
<h1>Remix Integration Tests Home</h1>
5+
</div>
6+
);
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { json, LoaderFunction } from '@remix-run/node';
2+
import { useLoaderData } from '@remix-run/react';
3+
4+
type LoaderData = { id: string };
5+
6+
export const loader: LoaderFunction = async ({ params: { id } }) => {
7+
return json({
8+
id,
9+
});
10+
};
11+
12+
export default function LoaderJSONResponse() {
13+
const data = useLoaderData<LoaderData>();
14+
15+
return (
16+
<div>
17+
<h1>{data.id}</h1>
18+
</div>
19+
);
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const baseConfig = require('../../jest.config.js');
2+
3+
module.exports = {
4+
globalSetup: '<rootDir>/test/server/utils/run-server.ts',
5+
...baseConfig,
6+
testMatch: ['**/*.test.ts'],
7+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"private": true,
3+
"sideEffects": false,
4+
"scripts": {
5+
"build": "remix build",
6+
"dev": "remix dev",
7+
"start": "remix-serve build",
8+
"test": "yarn test:client && yarn test:server",
9+
"test:client": "echo \"TODO\"",
10+
"test:server": "jest"
11+
},
12+
"dependencies": {
13+
"@remix-run/express": "^1.6.5",
14+
"@remix-run/node": "^1.6.5",
15+
"@remix-run/react": "^1.6.5",
16+
"@remix-run/serve": "^1.6.5",
17+
"@sentry/remix": "file:../..",
18+
"react": "^17.0.2",
19+
"react-dom": "^17.0.2"
20+
},
21+
"devDependencies": {
22+
"@remix-run/dev": "^1.6.5",
23+
"@remix-run/eslint-config": "^1.6.5",
24+
"@types/react": "^17.0.47",
25+
"@types/react-dom": "^17.0.17",
26+
"eslint": "^8.20.0",
27+
"typescript": "^4.7.4"
28+
},
29+
"resolutions": {
30+
"@sentry/browser": "file:../../../browser",
31+
"@sentry/core": "file:../../../core",
32+
"@sentry/hub": "file:../../../hub",
33+
"@sentry/integrations": "file:../../../integrations",
34+
"@sentry/node": "file:../../../node",
35+
"@sentry/react": "file:../../../react",
36+
"@sentry/tracing": "file:../../../tracing",
37+
"@sentry/types": "file:../../../types",
38+
"@sentry/utils": "file:../../../utils"
39+
},
40+
"engines": {
41+
"node": ">=14"
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/** @type {import('@remix-run/dev').AppConfig} */
2+
module.exports = {
3+
appDirectory: 'app',
4+
assetsBuildDirectory: 'public/build',
5+
serverBuildPath: 'build/index.js',
6+
publicPath: '/build/',
7+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { assertSentryTransaction, getEnvelopeRequest } from '../../../../../node-integration-tests/utils';
2+
3+
describe('Remix API Loaders', () => {
4+
it('correctly instruments a Remix API loader', async () => {
5+
const url = 'http://localhost:3000/loader-json-response/123123';
6+
const envelope = await getEnvelopeRequest(url);
7+
const transaction = envelope[2];
8+
9+
assertSentryTransaction(transaction, {
10+
spans: [
11+
{
12+
description: url,
13+
op: 'remix.server.loader',
14+
},
15+
{
16+
description: url,
17+
op: 'remix.server.documentRequest',
18+
},
19+
],
20+
});
21+
});
22+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import express, { Express } from 'express';
2+
import { createRequestHandler } from '@remix-run/express';
3+
4+
/**
5+
* Runs a test server
6+
*/
7+
function runServer(testDir: string): void {
8+
const app = express();
9+
10+
app.all('*', createRequestHandler({ build: require('../../../build') }));
11+
12+
app.listen(3000);
13+
}
14+
15+
export default runServer;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
3+
"compilerOptions": {
4+
"lib": ["DOM", "DOM.Iterable", "ES2019"],
5+
"isolatedModules": true,
6+
"esModuleInterop": true,
7+
"jsx": "react-jsx",
8+
"moduleResolution": "node",
9+
"resolveJsonModule": true,
10+
"target": "ES2019",
11+
"strict": true,
12+
"allowJs": true,
13+
"forceConsistentCasingInFileNames": true,
14+
"baseUrl": ".",
15+
"paths": {
16+
"~/*": ["./app/*"]
17+
},
18+
"noEmit": true
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
4+
"include": ["suites/**/*.ts"],
5+
6+
"compilerOptions": {
7+
// should include all types from `./tsconfig.json` plus types for all test frameworks used
8+
"types": ["node", "jest"]
9+
10+
// other package-specific, test-specific options
11+
}
12+
}

0 commit comments

Comments
 (0)