Skip to content

Commit 49cfc13

Browse files
test(remix): Add client-side integration tests. (#5477)
Adds the initial set of client-side integration tests for Remix SDK. Covers: - [x] `sentry-trace` and `baggage` injected inside `<meta>`. - [x] `captureException` works - [x] `captureMessage` works - [x] `ErrorBoundary` works - [x] Manually created transactions are reported - [x] Parameterized routes are reported Co-authored-by: Abhijeet Prasad <[email protected]>
1 parent d8313f3 commit 49cfc13

File tree

9 files changed

+159
-0
lines changed

9 files changed

+159
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import * as Sentry from '@sentry/remix';
2+
3+
export default function ErrorBoundaryCapture() {
4+
Sentry.captureException(new Error('Sentry Manually Captured Error'));
5+
6+
return <div></div>;
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import * as Sentry from '@sentry/remix';
2+
3+
export default function ErrorBoundaryCapture() {
4+
Sentry.captureMessage('Sentry Manually Captured Message');
5+
6+
return <div/>;
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { useState } from 'react';
2+
3+
export default function ErrorBoundaryCapture() {
4+
const [count, setCount] = useState(0);
5+
6+
if (count > 0) {
7+
throw new Error('Sentry React Component Error');
8+
} else {
9+
setTimeout(() => setCount(count + 1), 0);
10+
}
11+
12+
return <div>{count}</div>;
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import * as Sentry from '@sentry/remix';
2+
3+
export default function ManualTracing() {
4+
const transaction = Sentry.startTransaction({ name: 'test_transaction_1' });
5+
transaction.finish();
6+
return <div/>;
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { getMultipleSentryEnvelopeRequests } from './utils/helpers';
2+
import { test, expect } from '@playwright/test';
3+
import { Event } from '@sentry/types';
4+
5+
test('should report a manually captured error.', async ({ page }) => {
6+
const envelopes = await getMultipleSentryEnvelopeRequests<Event>(page, 2, { url: '/capture-exception' });
7+
8+
const [errorEnvelope, pageloadEnvelope] = envelopes;
9+
10+
expect(errorEnvelope.level).toBe('error');
11+
expect(errorEnvelope.tags?.transaction).toBe('/capture-exception');
12+
expect(errorEnvelope.exception?.values).toMatchObject([
13+
{
14+
type: 'Error',
15+
value: 'Sentry Manually Captured Error',
16+
stacktrace: { frames: expect.any(Array) },
17+
mechanism: { type: 'generic', handled: true },
18+
},
19+
]);
20+
21+
expect(pageloadEnvelope.contexts?.trace.op).toBe('pageload');
22+
expect(pageloadEnvelope.tags?.['routing.instrumentation']).toBe('remix-router');
23+
expect(pageloadEnvelope.type).toBe('transaction');
24+
expect(pageloadEnvelope.transaction).toBe('routes/capture-exception');
25+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { getMultipleSentryEnvelopeRequests } from './utils/helpers';
2+
import { test, expect } from '@playwright/test';
3+
import { Event } from '@sentry/types';
4+
5+
test('should report a manually captured message.', async ({ page }) => {
6+
const envelopes = await getMultipleSentryEnvelopeRequests<Event>(page, 2, { url: '/capture-message' });
7+
8+
const [messageEnvelope, pageloadEnvelope] = envelopes;
9+
10+
expect(messageEnvelope.level).toBe('info');
11+
expect(messageEnvelope.tags?.transaction).toBe('/capture-message');
12+
expect(messageEnvelope.message).toBe('Sentry Manually Captured Message');
13+
14+
expect(pageloadEnvelope.contexts?.trace.op).toBe('pageload');
15+
expect(pageloadEnvelope.tags?.['routing.instrumentation']).toBe('remix-router');
16+
expect(pageloadEnvelope.type).toBe('transaction');
17+
expect(pageloadEnvelope.transaction).toBe('routes/capture-message');
18+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { getMultipleSentryEnvelopeRequests } from './utils/helpers';
2+
import { test, expect } from '@playwright/test';
3+
import { Event } from '@sentry/types';
4+
5+
test('should capture React component errors.', async ({ page }) => {
6+
const envelopes = await getMultipleSentryEnvelopeRequests<Event>(page, 2, {
7+
url: '/error-boundary-capture/0',
8+
});
9+
10+
const [pageloadEnvelope, errorEnvelope] = envelopes;
11+
12+
expect(pageloadEnvelope.contexts?.trace.op).toBe('pageload');
13+
expect(pageloadEnvelope.tags?.['routing.instrumentation']).toBe('remix-router');
14+
expect(pageloadEnvelope.type).toBe('transaction');
15+
expect(pageloadEnvelope.transaction).toBe('routes/error-boundary-capture/$id');
16+
17+
expect(errorEnvelope.level).toBe('error');
18+
expect(errorEnvelope.sdk?.name).toBe('sentry.javascript.remix');
19+
expect(errorEnvelope.exception?.values).toMatchObject([
20+
{
21+
type: 'React ErrorBoundary Error',
22+
value: 'Sentry React Component Error',
23+
stacktrace: { frames: expect.any(Array) },
24+
},
25+
{
26+
type: 'Error',
27+
value: 'Sentry React Component Error',
28+
stacktrace: { frames: expect.any(Array) },
29+
mechanism: { type: 'generic', handled: true },
30+
},
31+
]);
32+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { getMultipleSentryEnvelopeRequests } from './utils/helpers';
2+
import { test, expect } from '@playwright/test';
3+
import { Event } from '@sentry/types';
4+
5+
test('should report a manually created / finished transaction.', async ({ page }) => {
6+
const envelopes = await getMultipleSentryEnvelopeRequests<Event>(page, 2, {
7+
url: '/manual-tracing/0',
8+
});
9+
10+
const [manualTransactionEnvelope, pageloadEnvelope] = envelopes;
11+
12+
expect(manualTransactionEnvelope.transaction).toBe('test_transaction_1');
13+
expect(manualTransactionEnvelope.sdk?.name).toBe('sentry.javascript.remix');
14+
expect(manualTransactionEnvelope.start_timestamp).toBeDefined();
15+
expect(manualTransactionEnvelope.timestamp).toBeDefined();
16+
17+
expect(pageloadEnvelope.contexts?.trace.op).toBe('pageload');
18+
expect(pageloadEnvelope.tags?.['routing.instrumentation']).toBe('remix-router');
19+
expect(pageloadEnvelope.type).toBe('transaction');
20+
expect(pageloadEnvelope.transaction).toBe('routes/manual-tracing/$id');
21+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { test, expect } from '@playwright/test';
2+
3+
test('should inject `sentry-trace` and `baggage` meta tags inside the root page.', async ({ page }) => {
4+
await page.goto('/');
5+
6+
const sentryTraceTag = await page.$('meta[name="sentry-trace"]');
7+
const sentryTraceContent = await sentryTraceTag?.getAttribute('content');
8+
9+
expect(sentryTraceContent).toEqual(expect.any(String));
10+
11+
const sentryBaggageTag = await page.$('meta[name="baggage"]');
12+
const sentryBaggageContent = await sentryBaggageTag?.getAttribute('content');
13+
14+
expect(sentryBaggageContent).toEqual(expect.any(String));
15+
});
16+
17+
test('should inject `sentry-trace` and `baggage` meta tags inside a parameterized route.', async ({ page }) => {
18+
await page.goto('/loader-json-response/0');
19+
20+
const sentryTraceTag = await page.$('meta[name="sentry-trace"]');
21+
const sentryTraceContent = await sentryTraceTag?.getAttribute('content');
22+
23+
expect(sentryTraceContent).toEqual(expect.any(String));
24+
25+
const sentryBaggageTag = await page.$('meta[name="baggage"]');
26+
const sentryBaggageContent = await sentryBaggageTag?.getAttribute('content');
27+
28+
expect(sentryBaggageContent).toEqual(expect.any(String));
29+
});

0 commit comments

Comments
 (0)