Skip to content

Commit

Permalink
Add integration tests for Remix v2 features.
Browse files Browse the repository at this point in the history
  • Loading branch information
onurtemizkan committed Jun 26, 2023
1 parent 09c5626 commit b166664
Show file tree
Hide file tree
Showing 42 changed files with 219 additions and 39 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,7 @@ jobs:
fail-fast: false
matrix:
node: [14, 16, 18]
remix: [1, 2]
steps:
- name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }})
uses: actions/checkout@v3
Expand All @@ -710,6 +711,7 @@ jobs:
- name: Run integration tests
env:
NODE_VERSION: ${{ matrix.node }}
REMIX_VERSION: ${{ matrix.remix }}
run: |
cd packages/remix
yarn test:integration:ci
Expand Down
4 changes: 3 additions & 1 deletion packages/remix/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@
"lint:eslint": "eslint . --format stylish",
"lint:prettier": "prettier --check \"{src,test,scripts}/**/**.ts\"",
"test": "yarn test:unit",
"test:integration": "run-s test:integration:clean test:integration:prepare test:integration:client test:integration:server",
"test:integration": "run-s test:integration:v1 test:integration:v2",
"test:integration:v1": "run-s test:integration:clean test:integration:prepare test:integration:client test:integration:server",
"test:integration:v2": "export REMIX_VERSION=2 && run-s test:integration:v1",
"test:integration:ci": "run-s test:integration:clean test:integration:prepare test:integration:client:ci test:integration:server",
"test:integration:prepare": "(cd test/integration && yarn)",
"test:integration:clean": "(cd test/integration && rimraf .cache node_modules build)",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from '../../../common/routes/action-json-response.$id';
export { default } from '../../../common/routes/action-json-response.$id';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from '../../common/routes/capture-exception';
export { default } from '../../common/routes/capture-exception';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from '../../common/routes/capture-message';
export { default } from '../../common/routes/capture-message';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from '../../../common/routes/error-boundary-capture.$id';
export { default } from '../../../common/routes/error-boundary-capture.$id';
2 changes: 2 additions & 0 deletions packages/remix/test/integration/app_v1/routes/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from '../../common/routes/index';
export { default } from '../../common/routes/index';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from '../../../common/routes/loader-defer-response';
export { default } from '../../../common/routes/loader-defer-response';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from '../../../common/routes/loader-json-response.$id';
export { default } from '../../../common/routes/loader-json-response.$id';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from '../../../common/routes/manual-tracing.$id';
export { default } from '../../../common/routes/manual-tracing.$id';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from '../../../common/routes/scope-bleed.$id';
export { default } from '../../../common/routes/scope-bleed.$id';
16 changes: 16 additions & 0 deletions packages/remix/test/integration/app_v2/entry.client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { RemixBrowser, useLocation, useMatches } from '@remix-run/react';
import { hydrate } from 'react-dom';
import * as Sentry from '@sentry/remix';
import { useEffect } from 'react';

Sentry.init({
dsn: 'https://[email protected]/1337',
tracesSampleRate: 1,
integrations: [
new Sentry.BrowserTracing({
routingInstrumentation: Sentry.remixRouterInstrumentation(useEffect, useLocation, useMatches),
}),
],
});

hydrate(<RemixBrowser />, document);
27 changes: 27 additions & 0 deletions packages/remix/test/integration/app_v2/entry.server.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { EntryContext } from '@remix-run/node';
import { RemixServer } from '@remix-run/react';
import { renderToString } from 'react-dom/server';
import * as Sentry from '@sentry/remix';

Sentry.init({
dsn: 'https://[email protected]/1337',
tracesSampleRate: 1,
// Disabling to test series of envelopes deterministically.
autoSessionTracking: false,
});

export default function handleRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext,
) {
let markup = renderToString(<RemixServer context={remixContext} url={request.url} />);

responseHeaders.set('Content-Type', 'text/html');

return new Response('<!DOCTYPE html>' + markup, {
status: responseStatusCode,
headers: responseHeaders,
});
}
60 changes: 60 additions & 0 deletions packages/remix/test/integration/app_v2/root.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { V2_MetaFunction, LoaderFunction, json, defer, redirect } from '@remix-run/node';
import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react';
import { withSentry } from '@sentry/remix';

export const meta: V2_MetaFunction = ({ data }) => [
{ charset: 'utf-8' },
{ title: 'New Remix App' },
{ name: 'viewport', content: 'width=device-width,initial-scale=1' },
{ name: 'sentry-trace', content: data.sentryTrace },
{ name: 'baggage', content: data.sentryBaggage },
];

export const loader: LoaderFunction = async ({ request }) => {
const url = new URL(request.url);
const type = url.searchParams.get('type');

switch (type) {
case 'empty':
return {};
case 'plain':
return {
data_one: [],
data_two: 'a string',
};
case 'json':
return json({ data_one: [], data_two: 'a string' }, { headers: { 'Cache-Control': 'max-age=300' } });
case 'defer':
return defer({ data_one: [], data_two: 'a string' });
case 'null':
return null;
case 'undefined':
return undefined;
case 'throwRedirect':
throw redirect('/?type=plain');
case 'returnRedirect':
return redirect('/?type=plain');
default: {
return {};
}
}
};

function App() {
return (
<html lang="en">
<head>
<Meta />
<Links />
</head>
<body>
<Outlet />
<ScrollRestoration />
<Scripts />
<LiveReload />
</body>
</html>
);
}

export default withSentry(App);
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from '../../common/routes/action-json-response.$id';
export { default } from '../../common/routes/action-json-response.$id';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from '../../common/routes/capture-exception';
export { default } from '../../common/routes/capture-exception';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from '../../common/routes/capture-message';
export { default } from '../../common/routes/capture-message';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from '../../common/routes/error-boundary-capture.$id';
export { default } from '../../common/routes/error-boundary-capture.$id';
2 changes: 2 additions & 0 deletions packages/remix/test/integration/app_v2/routes/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from '../../common/routes/index';
export { default } from '../../common/routes/index';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from '../../common/routes/loader-defer-response';
export { default } from '../../common/routes/loader-defer-response';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from '../../common/routes/loader-json-response.$id';
export { default } from '../../common/routes/loader-json-response.$id';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from '../../common/routes/manual-tracing.$id';
export { default } from '../../common/routes/manual-tracing.$id';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from '../../common/routes/scope-bleed.$id';
export { default } from '../../common/routes/scope-bleed.$id';
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ import * as Sentry from '@sentry/remix';
export default function ErrorBoundaryCapture() {
Sentry.captureMessage('Sentry Manually Captured Message');

return <div/>;
return <div />;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ import * as Sentry from '@sentry/remix';
export default function ManualTracing() {
const transaction = Sentry.startTransaction({ name: 'test_transaction_1' });
transaction.finish();
return <div/>;
return <div />;
}
11 changes: 10 additions & 1 deletion packages/remix/test/integration/remix.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
/** @type {import('@remix-run/dev').AppConfig} */
const useV2 = process.env.REMIX_VERSION === '2';

module.exports = {
appDirectory: 'app',
appDirectory: useV2 ? 'app_v2' : 'app_v1',
assetsBuildDirectory: 'public/build',
serverBuildPath: 'build/index.js',
publicPath: '/build/',
future: {
v2_errorBoundary: useV2,
v2_headers: useV2,
v2_meta: useV2,
v2_normalizeFormMethod: useV2,
v2_routeConvention: useV2,
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { getMultipleSentryEnvelopeRequests } from './utils/helpers';
import { test, expect } from '@playwright/test';
import { Event } from '@sentry/types';

const useV2 = process.env.REMIX_VERSION === '2';

test('should capture React component errors.', async ({ page }) => {
const envelopes = await getMultipleSentryEnvelopeRequests<Event>(page, 2, {
url: '/error-boundary-capture/0',
Expand All @@ -12,7 +14,9 @@ test('should capture React component errors.', async ({ page }) => {
expect(pageloadEnvelope.contexts?.trace.op).toBe('pageload');
expect(pageloadEnvelope.tags?.['routing.instrumentation']).toBe('remix-router');
expect(pageloadEnvelope.type).toBe('transaction');
expect(pageloadEnvelope.transaction).toBe('routes/error-boundary-capture/$id');
expect(pageloadEnvelope.transaction).toBe(
useV2 ? 'routes/error-boundary-capture.$id' : 'routes/error-boundary-capture/$id',
);

expect(errorEnvelope.level).toBe('error');
expect(errorEnvelope.sdk?.name).toBe('sentry.javascript.remix');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { getMultipleSentryEnvelopeRequests } from './utils/helpers';
import { test, expect } from '@playwright/test';
import { Event } from '@sentry/types';

const useV2 = process.env.REMIX_VERSION === '2';

test('should report a manually created / finished transaction.', async ({ page }) => {
const envelopes = await getMultipleSentryEnvelopeRequests<Event>(page, 2, {
url: '/manual-tracing/0',
Expand All @@ -17,5 +19,5 @@ test('should report a manually created / finished transaction.', async ({ page }
expect(pageloadEnvelope.contexts?.trace?.op).toBe('pageload');
expect(pageloadEnvelope.tags?.['routing.instrumentation']).toBe('remix-router');
expect(pageloadEnvelope.type).toBe('transaction');
expect(pageloadEnvelope.transaction).toBe('routes/manual-tracing/$id');
expect(pageloadEnvelope.transaction).toBe(useV2 ? 'routes/manual-tracing.$id' : 'routes/manual-tracing/$id');
});
5 changes: 4 additions & 1 deletion packages/remix/test/integration/test/client/pageload.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const useV2 = process.env.REMIX_VERSION === '2';

import { getFirstSentryEnvelopeRequest } from './utils/helpers';
import { test, expect } from '@playwright/test';
import { Event } from '@sentry/types';
Expand All @@ -8,5 +10,6 @@ test('should add `pageload` transaction on load.', async ({ page }) => {
expect(envelope.contexts?.trace.op).toBe('pageload');
expect(envelope.tags?.['routing.instrumentation']).toBe('remix-router');
expect(envelope.type).toBe('transaction');
expect(envelope.transaction).toBe('routes/index');

expect(envelope.transaction).toBe(useV2 ? 'root' : 'routes/index');
});
24 changes: 13 additions & 11 deletions packages/remix/test/integration/test/server/action.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { assertSentryTransaction, assertSentryEvent, RemixTestEnv } from './utils/helpers';

const useV2 = process.env.REMIX_VERSION === '2';

jest.spyOn(console, 'error').mockImplementation();

// Repeat tests for each adapter
Expand All @@ -11,22 +13,22 @@ describe.each(['builtin', 'express'])('Remix API Actions with adapter = %s', ada
const transaction = envelope[2];

assertSentryTransaction(transaction, {
transaction: 'routes/action-json-response/$id',
transaction: `routes/action-json-response${useV2 ? '.' : '/'}$id`,
spans: [
{
description: 'routes/action-json-response/$id',
description: `routes/action-json-response${useV2 ? '.' : '/'}$id`,
op: 'function.remix.action',
},
{
description: 'root',
op: 'function.remix.loader',
},
{
description: 'routes/action-json-response/$id',
description: `routes/action-json-response${useV2 ? '.' : '/'}$id`,
op: 'function.remix.loader',
},
{
description: 'routes/action-json-response/$id',
description: `routes/action-json-response${useV2 ? '.' : '/'}$id`,
op: 'function.remix.document_request',
},
],
Expand Down Expand Up @@ -102,7 +104,7 @@ describe.each(['builtin', 'express'])('Remix API Actions with adapter = %s', ada
const [event] = envelopes.filter(envelope => envelope[1].type === 'event');

assertSentryTransaction(transaction[2], {
transaction: 'routes/action-json-response/$id',
transaction: `routes/action-json-response${useV2 ? '.' : '/'}$id`,
request: {
method: 'POST',
url,
Expand Down Expand Up @@ -161,7 +163,7 @@ describe.each(['builtin', 'express'])('Remix API Actions with adapter = %s', ada
},
},
tags: {
transaction: 'routes/action-json-response/$id',
transaction: `routes/action-json-response${useV2 ? '.' : '/'}$id`,
},
});

Expand All @@ -177,7 +179,7 @@ describe.each(['builtin', 'express'])('Remix API Actions with adapter = %s', ada
},
},
tags: {
transaction: 'routes/action-json-response/$id',
transaction: `routes/action-json-response${useV2 ? '.' : '/'}$id`,
},
});

Expand Down Expand Up @@ -227,7 +229,7 @@ describe.each(['builtin', 'express'])('Remix API Actions with adapter = %s', ada
},
},
tags: {
transaction: 'routes/action-json-response/$id',
transaction: `routes/action-json-response${useV2 ? '.' : '/'}$id`,
},
});

Expand Down Expand Up @@ -277,7 +279,7 @@ describe.each(['builtin', 'express'])('Remix API Actions with adapter = %s', ada
},
},
tags: {
transaction: 'routes/action-json-response/$id',
transaction: `routes/action-json-response${useV2 ? '.' : '/'}$id`,
},
});

Expand Down Expand Up @@ -327,7 +329,7 @@ describe.each(['builtin', 'express'])('Remix API Actions with adapter = %s', ada
},
},
tags: {
transaction: 'routes/action-json-response/$id',
transaction: `routes/action-json-response${useV2 ? '.' : '/'}$id`,
},
});

Expand Down Expand Up @@ -377,7 +379,7 @@ describe.each(['builtin', 'express'])('Remix API Actions with adapter = %s', ada
},
},
tags: {
transaction: 'routes/action-json-response/$id',
transaction: `routes/action-json-response${useV2 ? '.' : '/'}$id`,
},
});

Expand Down
Loading

0 comments on commit b166664

Please sign in to comment.