Skip to content

test(e2e): Add behaviour test for Transactions in standard React E2E tests application #5912

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/e2e-tests/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const PUBLISH_PACKAGES_DOCKER_IMAGE_NAME = 'publish-packages';
const publishScriptNodeVersion = process.env.E2E_TEST_PUBLISH_SCRIPT_NODE_VERSION;

const DEFAULT_BUILD_TIMEOUT_SECONDS = 60 * 5;
const DEFAULT_TEST_TIMEOUT_SECONDS = 60;
const DEFAULT_TEST_TIMEOUT_SECONDS = 60 * 2;

if (!process.env.E2E_TEST_AUTH_TOKEN) {
console.log(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import axios, { AxiosError } from 'axios';
const SENTRY_TEST_ORG_SLUG = 'sentry-sdks';
const SENTRY_TEST_PROJECT = 'sentry-javascript-e2e-tests';

const EVENT_POLLING_TIMEOUT = 45000;
const EVENT_POLLING_RETRY_INTERVAL = 1000;
const EVENT_POLLING_TIMEOUT = 30_000;

const authToken = process.env.E2E_TEST_AUTH_TOKEN;

Expand All @@ -18,30 +17,150 @@ test('Sends an exception to Sentry', async ({ page }) => {
const exceptionIdHandle = await page.waitForFunction(() => window.capturedExceptionId);
const exceptionEventId = await exceptionIdHandle.jsonValue();

let lastErrorResponse: AxiosError | undefined;
await expect
.poll(
async () => {
try {
const response = await axios.get(
`https://sentry.io/api/0/projects/${SENTRY_TEST_ORG_SLUG}/${SENTRY_TEST_PROJECT}/events/${exceptionEventId}/`,
{ headers: { Authorization: `Bearer ${authToken}` } },
);
return response.status;
} catch (e) {
if (e instanceof AxiosError && e.response) {
if (e.response.status !== 404) {
throw e;
} else {
return e.response.status;
}
} else {
throw e;
}
}
},
{
timeout: EVENT_POLLING_TIMEOUT,
},
)
.toBe(200);
});

test('Sends a pageload transaction to Sentry', async ({ page }) => {
await page.goto('/');

const timeout = setTimeout(() => {
if (lastErrorResponse?.response?.status) {
throw new Error(
`Timeout reached while polling event. Last received status code: ${lastErrorResponse.response.status}`,
);
const recordedTransactionsHandle = await page.waitForFunction(() => {
if (window.recordedTransactions && window.recordedTransactions?.length >= 1) {
return window.recordedTransactions;
} else {
throw new Error('Timeout reached while polling event.');
return undefined;
}
}, EVENT_POLLING_TIMEOUT);

while (true) {
try {
const response = await axios.get(
`https://sentry.io/api/0/projects/${SENTRY_TEST_ORG_SLUG}/${SENTRY_TEST_PROJECT}/events/${exceptionEventId}/`,
{ headers: { Authorization: `Bearer ${authToken}` } },
);
clearTimeout(timeout);
expect(response?.status).toBe(200);
break;
} catch (e) {
lastErrorResponse = e;
await new Promise(resolve => setTimeout(resolve, EVENT_POLLING_RETRY_INTERVAL));
});
const recordedTransactionEventIds = await recordedTransactionsHandle.jsonValue();

if (recordedTransactionEventIds === undefined) {
throw new Error("Application didn't record any transaction event IDs.");
}

let hadPageLoadTransaction = false;

await Promise.all(
recordedTransactionEventIds.map(async transactionEventId => {
await expect
.poll(
async () => {
try {
const response = await axios.get(
`https://sentry.io/api/0/projects/${SENTRY_TEST_ORG_SLUG}/${SENTRY_TEST_PROJECT}/events/${transactionEventId}/`,
{ headers: { Authorization: `Bearer ${authToken}` } },
);

if (response.data.contexts.trace.op === 'pageload') {
hadPageLoadTransaction = true;
}

return response.status;
} catch (e) {
if (e instanceof AxiosError && e.response) {
if (e.response.status !== 404) {
throw e;
} else {
return e.response.status;
}
} else {
throw e;
}
}
},
{
timeout: EVENT_POLLING_TIMEOUT,
},
)
.toBe(200);
}),
);

expect(hadPageLoadTransaction).toBe(true);
});

test('Sends a navigation transaction to Sentry', async ({ page }) => {
await page.goto('/');

// Give pageload transaction time to finish
page.waitForTimeout(4000);

const linkElement = page.locator('id=navigation');
await linkElement.click();

const recordedTransactionsHandle = await page.waitForFunction(() => {
if (window.recordedTransactions && window.recordedTransactions?.length >= 2) {
return window.recordedTransactions;
} else {
return undefined;
}
});
const recordedTransactionEventIds = await recordedTransactionsHandle.jsonValue();

if (recordedTransactionEventIds === undefined) {
throw new Error("Application didn't record any transaction event IDs.");
}

let hadPageNavigationTransaction = false;

await Promise.all(
recordedTransactionEventIds.map(async transactionEventId => {
await expect
.poll(
async () => {
try {
const response = await axios.get(
`https://sentry.io/api/0/projects/${SENTRY_TEST_ORG_SLUG}/${SENTRY_TEST_PROJECT}/events/${transactionEventId}/`,
{ headers: { Authorization: `Bearer ${authToken}` } },
);

if (response.data.contexts.trace.op === 'navigation') {
hadPageNavigationTransaction = true;
}

return response.status;
} catch (e) {
if (e instanceof AxiosError && e.response) {
if (e.response.status !== 404) {
throw e;
} else {
return e.response.status;
}
} else {
throw e;
}
}
},
{
timeout: EVENT_POLLING_TIMEOUT,
},
)
.toBe(200);
}),
);

expect(hadPageNavigationTransaction).toBe(true);
});
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@
"noEmit": true,
"jsx": "react"
},
"include": ["src"]
"include": ["src", "tests"]
}