From 1ce8db3ce45018f435814de47490daccfaf6ba1b Mon Sep 17 00:00:00 2001 From: Kaung Zin Hein Date: Tue, 30 Jul 2024 18:55:20 -0400 Subject: [PATCH 1/9] test(browser): Add initial setup for e2e test --- .../default-browser/.gitignore | 29 ++++++++++++ .../test-applications/default-browser/.npmrc | 2 + .../default-browser/build.mjs | 44 +++++++++++++++++++ .../default-browser/package.json | 41 +++++++++++++++++ .../default-browser/playwright.config.mjs | 7 +++ .../default-browser/src/index.js | 11 +++++ .../default-browser/start-event-proxy.mjs | 6 +++ .../default-browser/tests/errors.test.ts | 5 +++ .../default-browser/tsconfig.json | 20 +++++++++ .../react-19/tests/errors.test.ts | 1 + .../tests/send-to-sentry.test.ts | 2 +- 11 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 dev-packages/e2e-tests/test-applications/default-browser/.gitignore create mode 100644 dev-packages/e2e-tests/test-applications/default-browser/.npmrc create mode 100644 dev-packages/e2e-tests/test-applications/default-browser/build.mjs create mode 100644 dev-packages/e2e-tests/test-applications/default-browser/package.json create mode 100644 dev-packages/e2e-tests/test-applications/default-browser/playwright.config.mjs create mode 100644 dev-packages/e2e-tests/test-applications/default-browser/src/index.js create mode 100644 dev-packages/e2e-tests/test-applications/default-browser/start-event-proxy.mjs create mode 100644 dev-packages/e2e-tests/test-applications/default-browser/tests/errors.test.ts create mode 100644 dev-packages/e2e-tests/test-applications/default-browser/tsconfig.json diff --git a/dev-packages/e2e-tests/test-applications/default-browser/.gitignore b/dev-packages/e2e-tests/test-applications/default-browser/.gitignore new file mode 100644 index 000000000000..84634c973eeb --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/default-browser/.gitignore @@ -0,0 +1,29 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +/test-results/ +/playwright-report/ +/playwright/.cache/ + +!*.d.ts diff --git a/dev-packages/e2e-tests/test-applications/default-browser/.npmrc b/dev-packages/e2e-tests/test-applications/default-browser/.npmrc new file mode 100644 index 000000000000..070f80f05092 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/default-browser/.npmrc @@ -0,0 +1,2 @@ +@sentry:registry=http://127.0.0.1:4873 +@sentry-internal:registry=http://127.0.0.1:4873 diff --git a/dev-packages/e2e-tests/test-applications/default-browser/build.mjs b/dev-packages/e2e-tests/test-applications/default-browser/build.mjs new file mode 100644 index 000000000000..5121c6b062aa --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/default-browser/build.mjs @@ -0,0 +1,44 @@ +import * as path from 'path'; +import * as url from 'url'; +import webpack from 'webpack'; +import HtmlWebpackPlugin from 'html-webpack-plugin'; +import TerserPlugin from 'terser-webpack-plugin'; + +const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); + +webpack( + { + entry: path.join(__dirname, 'src/index.js'), + output: { + path: path.join(__dirname, 'build'), + filename: 'app.js', + }, + optimization: { + minimize: true, + minimizer: [new TerserPlugin()], + }, + plugins: [new webpack.EnvironmentPlugin(['E2E_TEST_DSN']), new HtmlWebpackPlugin()], + mode: 'production', + }, + (err, stats) => { + if (err) { + console.error(err.stack || err); + if (err.details) { + console.error(err.details); + } + return; + } + + const info = stats.toJson(); + + if (stats.hasErrors()) { + console.error(info.errors); + process.exit(1); + } + + if (stats.hasWarnings()) { + console.warn(info.warnings); + process.exit(1); + } + }, +); diff --git a/dev-packages/e2e-tests/test-applications/default-browser/package.json b/dev-packages/e2e-tests/test-applications/default-browser/package.json new file mode 100644 index 000000000000..d6286c2423b6 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/default-browser/package.json @@ -0,0 +1,41 @@ +{ + "name": "default-browser-test-app", + "version": "0.1.0", + "private": true, + "dependencies": { + "@sentry/browser": "latest || *", + "@types/node": "16.7.13", + "typescript": "4.9.5" + }, + "scripts": { + "start": "serve -s build", + "build": "node build.mjs", + "test": "playwright test", + "clean": "npx rimraf node_modules pnpm-lock.yaml", + "test:build": "pnpm install && npx playwright install && pnpm build", + "test:assert": "pnpm test" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "devDependencies": { + "@playwright/test": "^1.44.1", + "@sentry-internal/test-utils": "link:../../../test-utils", + "webpack": "^5.91.0", + "serve": "14.0.1", + "terser-webpack-plugin": "^5.3.10", + "html-webpack-plugin": "^5.6.0" + }, + "volta": { + "extends": "../../package.json" + } +} diff --git a/dev-packages/e2e-tests/test-applications/default-browser/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/default-browser/playwright.config.mjs new file mode 100644 index 000000000000..31f2b913b58b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/default-browser/playwright.config.mjs @@ -0,0 +1,7 @@ +import { getPlaywrightConfig } from '@sentry-internal/test-utils'; + +const config = getPlaywrightConfig({ + startCommand: `pnpm start`, +}); + +export default config; diff --git a/dev-packages/e2e-tests/test-applications/default-browser/src/index.js b/dev-packages/e2e-tests/test-applications/default-browser/src/index.js new file mode 100644 index 000000000000..f00e268219c7 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/default-browser/src/index.js @@ -0,0 +1,11 @@ +import * as Sentry from '@sentry/react'; + +Sentry.init({ + dsn: process.env.E2E_TEST_DSN, + tunnel: 'http://localhost:3031', + integrations: [Sentry.browserTracingIntegration()], +}); + +setTimeout(() => { + throw new Error('I am an error!'); +}, 2000); diff --git a/dev-packages/e2e-tests/test-applications/default-browser/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/default-browser/start-event-proxy.mjs new file mode 100644 index 000000000000..6c84e74d541b --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/default-browser/start-event-proxy.mjs @@ -0,0 +1,6 @@ +import { startEventProxyServer } from '@sentry-internal/test-utils'; + +startEventProxyServer({ + port: 3031, + proxyServerName: 'default-browser', +}); diff --git a/dev-packages/e2e-tests/test-applications/default-browser/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/default-browser/tests/errors.test.ts new file mode 100644 index 000000000000..89820af02ffc --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/default-browser/tests/errors.test.ts @@ -0,0 +1,5 @@ +import { expect, test } from '@playwright/test'; + +test('testing', () => { + expect(true).toBe(true); +}); diff --git a/dev-packages/e2e-tests/test-applications/default-browser/tsconfig.json b/dev-packages/e2e-tests/test-applications/default-browser/tsconfig.json new file mode 100644 index 000000000000..4cc95dc2689a --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/default-browser/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "es2018", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react" + }, + "include": ["src", "tests"] +} diff --git a/dev-packages/e2e-tests/test-applications/react-19/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/react-19/tests/errors.test.ts index 46e19b11a2ac..43b1f00df449 100644 --- a/dev-packages/e2e-tests/test-applications/react-19/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-19/tests/errors.test.ts @@ -7,6 +7,7 @@ test('Catches errors caught by error boundary', async ({ page }) => { }); const errorEventPromise = waitForError('react-19', event => { + //ErrorEvent's type === undefined return !event.type && event.exception?.values?.[0]?.value === 'caught error'; }); diff --git a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts index d9c3e09f2ad2..f2819a87cd20 100644 --- a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts @@ -1,7 +1,7 @@ import { expect, test } from '@playwright/test'; import { ReplayRecordingData } from './fixtures/ReplayRecordingData'; -const EVENT_POLLING_TIMEOUT = 90_000; +const EVENT_POLLING_TIMEOUT = 5_000; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; From 055fd3db56d7758b2d150daf6392ce4868bbfdbd Mon Sep 17 00:00:00 2001 From: Kaung Zin Hein Date: Tue, 30 Jul 2024 19:04:41 -0400 Subject: [PATCH 2/9] test(browser): Revert unrelated test packages to original values --- .../e2e-tests/test-applications/default-browser/src/index.js | 1 + .../e2e-tests/test-applications/react-19/tests/errors.test.ts | 1 - .../react-send-to-sentry/tests/send-to-sentry.test.ts | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/default-browser/src/index.js b/dev-packages/e2e-tests/test-applications/default-browser/src/index.js index f00e268219c7..422e76626ea5 100644 --- a/dev-packages/e2e-tests/test-applications/default-browser/src/index.js +++ b/dev-packages/e2e-tests/test-applications/default-browser/src/index.js @@ -1,6 +1,7 @@ import * as Sentry from '@sentry/react'; Sentry.init({ + release: 'e2e-test', dsn: process.env.E2E_TEST_DSN, tunnel: 'http://localhost:3031', integrations: [Sentry.browserTracingIntegration()], diff --git a/dev-packages/e2e-tests/test-applications/react-19/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/react-19/tests/errors.test.ts index 43b1f00df449..46e19b11a2ac 100644 --- a/dev-packages/e2e-tests/test-applications/react-19/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-19/tests/errors.test.ts @@ -7,7 +7,6 @@ test('Catches errors caught by error boundary', async ({ page }) => { }); const errorEventPromise = waitForError('react-19', event => { - //ErrorEvent's type === undefined return !event.type && event.exception?.values?.[0]?.value === 'caught error'; }); diff --git a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts index f2819a87cd20..d9c3e09f2ad2 100644 --- a/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts +++ b/dev-packages/e2e-tests/test-applications/react-send-to-sentry/tests/send-to-sentry.test.ts @@ -1,7 +1,7 @@ import { expect, test } from '@playwright/test'; import { ReplayRecordingData } from './fixtures/ReplayRecordingData'; -const EVENT_POLLING_TIMEOUT = 5_000; +const EVENT_POLLING_TIMEOUT = 90_000; const authToken = process.env.E2E_TEST_AUTH_TOKEN; const sentryTestOrgSlug = process.env.E2E_TEST_SENTRY_ORG_SLUG; From 6e91d7c92b8617f50270213eb201f1b572b26c0a Mon Sep 17 00:00:00 2001 From: Kaung Zin Hein Date: Tue, 30 Jul 2024 20:56:10 -0400 Subject: [PATCH 3/9] test(browser): Add error event test --- .../default-browser/build.mjs | 7 ++++- .../default-browser/public/index.html | 15 ++++++++++ .../default-browser/src/index.js | 4 +-- .../default-browser/tests/errors.test.ts | 29 +++++++++++++++++-- 4 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 dev-packages/e2e-tests/test-applications/default-browser/public/index.html diff --git a/dev-packages/e2e-tests/test-applications/default-browser/build.mjs b/dev-packages/e2e-tests/test-applications/default-browser/build.mjs index 5121c6b062aa..dc51255d7839 100644 --- a/dev-packages/e2e-tests/test-applications/default-browser/build.mjs +++ b/dev-packages/e2e-tests/test-applications/default-browser/build.mjs @@ -17,7 +17,12 @@ webpack( minimize: true, minimizer: [new TerserPlugin()], }, - plugins: [new webpack.EnvironmentPlugin(['E2E_TEST_DSN']), new HtmlWebpackPlugin()], + plugins: [ + new webpack.EnvironmentPlugin(['E2E_TEST_DSN']), + new HtmlWebpackPlugin({ + template: path.join(__dirname, 'public/index.html'), + }), + ], mode: 'production', }, (err, stats) => { diff --git a/dev-packages/e2e-tests/test-applications/default-browser/public/index.html b/dev-packages/e2e-tests/test-applications/default-browser/public/index.html new file mode 100644 index 000000000000..615f93028f8d --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/default-browser/public/index.html @@ -0,0 +1,15 @@ + + + + + + Default Browser App + + +
+ + + + + + diff --git a/dev-packages/e2e-tests/test-applications/default-browser/src/index.js b/dev-packages/e2e-tests/test-applications/default-browser/src/index.js index 422e76626ea5..648a82bfdb21 100644 --- a/dev-packages/e2e-tests/test-applications/default-browser/src/index.js +++ b/dev-packages/e2e-tests/test-applications/default-browser/src/index.js @@ -7,6 +7,6 @@ Sentry.init({ integrations: [Sentry.browserTracingIntegration()], }); -setTimeout(() => { +document.getElementById('exception-button').addEventListener('click', () => { throw new Error('I am an error!'); -}, 2000); +}); diff --git a/dev-packages/e2e-tests/test-applications/default-browser/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/default-browser/tests/errors.test.ts index 89820af02ffc..dc7fecbf6ab9 100644 --- a/dev-packages/e2e-tests/test-applications/default-browser/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/default-browser/tests/errors.test.ts @@ -1,5 +1,30 @@ import { expect, test } from '@playwright/test'; +import { waitForError } from '@sentry-internal/test-utils'; -test('testing', () => { - expect(true).toBe(true); +test('Should send correct error event', async ({ page }) => { + const errorEventPromise = waitForError('default-browser', event => { + return !event.type && event.exception?.values?.[0]?.value === 'I am an error!'; + }); + + await page.goto('/'); + + const exceptionButton = page.locator('id=exception-button'); + await exceptionButton.click(); + + const errorEvent = await errorEventPromise; + + expect(errorEvent.exception?.values).toHaveLength(1); + expect(errorEvent.exception?.values?.[0]?.value).toBe('I am an error!'); + + expect(errorEvent.transaction).toBe('/'); + + expect(errorEvent.request).toEqual({ + url: 'http://localhost:3030/', + headers: expect.any(Object), + }); + + expect(errorEvent.contexts?.trace).toEqual({ + trace_id: expect.any(String), + span_id: expect.any(String), + }); }); From 031ce47d9a0c86a78e581a8484307d9386a745c2 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Wed, 7 Aug 2024 10:21:20 +0200 Subject: [PATCH 4/9] some fixes - tracesSampleRate: 1 - environment: 'qa' - add to CI --- .github/workflows/build.yml | 1 + .../test-applications/default-browser/src/index.js | 8 +++++--- .../default-browser/tests/errors.test.ts | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d19c648e39b1..b18da4f6c43f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -867,6 +867,7 @@ jobs: 'create-remix-app-express', 'create-remix-app-express-legacy', 'create-remix-app-express-vite-dev', + 'default-browser', 'node-express-esm-loader', 'node-express-esm-preload', 'node-express-esm-without-loader', diff --git a/dev-packages/e2e-tests/test-applications/default-browser/src/index.js b/dev-packages/e2e-tests/test-applications/default-browser/src/index.js index 648a82bfdb21..54adaa17a122 100644 --- a/dev-packages/e2e-tests/test-applications/default-browser/src/index.js +++ b/dev-packages/e2e-tests/test-applications/default-browser/src/index.js @@ -1,10 +1,12 @@ -import * as Sentry from '@sentry/react'; +import * as Sentry from '@sentry/browser'; Sentry.init({ - release: 'e2e-test', dsn: process.env.E2E_TEST_DSN, - tunnel: 'http://localhost:3031', integrations: [Sentry.browserTracingIntegration()], + tracesSampleRate: 1.0, + release: 'e2e-test', + environment: 'qa', + tunnel: 'http://localhost:3031', }); document.getElementById('exception-button').addEventListener('click', () => { diff --git a/dev-packages/e2e-tests/test-applications/default-browser/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/default-browser/tests/errors.test.ts index dc7fecbf6ab9..496c0f5264cc 100644 --- a/dev-packages/e2e-tests/test-applications/default-browser/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/default-browser/tests/errors.test.ts @@ -1,7 +1,7 @@ import { expect, test } from '@playwright/test'; import { waitForError } from '@sentry-internal/test-utils'; -test('Should send correct error event', async ({ page }) => { +test('captures an error', async ({ page }) => { const errorEventPromise = waitForError('default-browser', event => { return !event.type && event.exception?.values?.[0]?.value === 'I am an error!'; }); From 3854de4598b7e68a85a336c718b8590fd7230146 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Wed, 7 Aug 2024 10:32:15 +0200 Subject: [PATCH 5/9] add performance test --- .../default-browser/tests/performance.test.ts | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 dev-packages/e2e-tests/test-applications/default-browser/tests/performance.test.ts diff --git a/dev-packages/e2e-tests/test-applications/default-browser/tests/performance.test.ts b/dev-packages/e2e-tests/test-applications/default-browser/tests/performance.test.ts new file mode 100644 index 000000000000..5ab7737e3b4a --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/default-browser/tests/performance.test.ts @@ -0,0 +1,89 @@ +import exp from 'constants'; +import { expect, test } from '@playwright/test'; +import { waitForTransaction } from '@sentry-internal/test-utils'; + +test('captures a pageload transaction', async ({ page }) => { + // `pageload` transaction + const transactionPromise = waitForTransaction('default-browser', async transactionEvent => { + return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload'; + }); + + await page.goto(`/`); + + // `waitForTransaction` hangs here because `transaction` (or `span`) event is not emitted, + // so the code past this line is never executed. + const pageLoadTransaction = await transactionPromise; + + expect(pageLoadTransaction).toEqual({ + contexts: { + trace: { + data: expect.objectContaining({ + 'sentry.idle_span_finish_reason': 'idleTimeout', + 'sentry.op': 'pageload', + 'sentry.origin': 'auto.pageload.browser', + 'sentry.sample_rate': 1, + 'sentry.source': 'url', + }), + op: 'pageload', + origin: 'auto.pageload.browser', + span_id: expect.stringMatching(/[a-f0-9]{16}/), + trace_id: expect.stringMatching(/[a-f0-9]{32}/), + }, + }, + environment: 'qa', + event_id: expect.stringMatching(/[a-f0-9]{32}/), + measurements: { + 'connection.rtt': { + unit: 'millisecond', + value: expect.any(Number), + }, + fcp: { + unit: 'millisecond', + value: expect.any(Number), + }, + fp: { + unit: 'millisecond', + value: expect.any(Number), + }, + lcp: { + unit: 'millisecond', + value: expect.any(Number), + }, + ttfb: { + unit: 'millisecond', + value: expect.any(Number), + }, + 'ttfb.requestTime': { + unit: 'millisecond', + value: expect.any(Number), + }, + }, + platform: 'javascript', + release: 'e2e-test', + request: { + headers: { + 'User-Agent': expect.any(String), + }, + url: 'http://localhost:3030/', + }, + sdk: { + integrations: expect.any(Array), + name: 'sentry.javascript.browser', + packages: [ + { + name: 'npm:@sentry/browser', + version: expect.any(String), + }, + ], + version: expect.any(String), + }, + spans: expect.any(Array), + start_timestamp: expect.any(Number), + timestamp: expect.any(Number), + transaction: '/', + transaction_info: { + source: 'url', + }, + type: 'transaction', + }); +}); From 728cc135451ab0c37e4985689d9a1a7e97d165c8 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Wed, 7 Aug 2024 10:48:19 +0200 Subject: [PATCH 6/9] fix formatting --- .../e2e-tests/test-applications/default-browser/build.mjs | 2 +- .../test-applications/default-browser/tests/performance.test.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/default-browser/build.mjs b/dev-packages/e2e-tests/test-applications/default-browser/build.mjs index dc51255d7839..aeaad894bdbd 100644 --- a/dev-packages/e2e-tests/test-applications/default-browser/build.mjs +++ b/dev-packages/e2e-tests/test-applications/default-browser/build.mjs @@ -1,8 +1,8 @@ import * as path from 'path'; import * as url from 'url'; -import webpack from 'webpack'; import HtmlWebpackPlugin from 'html-webpack-plugin'; import TerserPlugin from 'terser-webpack-plugin'; +import webpack from 'webpack'; const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); diff --git a/dev-packages/e2e-tests/test-applications/default-browser/tests/performance.test.ts b/dev-packages/e2e-tests/test-applications/default-browser/tests/performance.test.ts index 5ab7737e3b4a..84bdc7b392f4 100644 --- a/dev-packages/e2e-tests/test-applications/default-browser/tests/performance.test.ts +++ b/dev-packages/e2e-tests/test-applications/default-browser/tests/performance.test.ts @@ -1,4 +1,3 @@ -import exp from 'constants'; import { expect, test } from '@playwright/test'; import { waitForTransaction } from '@sentry-internal/test-utils'; From 5d3c21bf58af07ab2e98a07476ed1505b364bc2c Mon Sep 17 00:00:00 2001 From: Kaung Zin Hein Date: Wed, 7 Aug 2024 11:48:38 -0400 Subject: [PATCH 7/9] test(browser): Add tests for span and transaction events - Update the simple web app to include soft navigation action - Include tests for `pageload` and `navigation` transactions/spans --- .../tests/transactions.test.ts | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 dev-packages/e2e-tests/test-applications/default-browser/tests/transactions.test.ts diff --git a/dev-packages/e2e-tests/test-applications/default-browser/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/default-browser/tests/transactions.test.ts new file mode 100644 index 000000000000..a3efa90ea067 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/default-browser/tests/transactions.test.ts @@ -0,0 +1,63 @@ +import { expect, test } from '@playwright/test'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; + +test('sends a pageload transaction', async ({ page }) => { + const transactionPromise = waitForTransaction('default-browser', async transactionEvent => { + return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload'; + }); + + const errorEventPromise = waitForError('default-browser', event => { + return !event.type && event.exception?.values?.[0]?.value === 'I am an error!'; + }); + + await page.goto('/'); + const transactionEvent = await transactionPromise; + + const exceptionButton = page.locator('id=exception-button'); + await exceptionButton.click(); + + const errorEvent = await errorEventPromise; + + expect(errorEvent.exception?.values).toHaveLength(1); + expect(errorEvent.exception?.values?.[0]?.value).toBe('I am an error!'); + + expect(errorEvent.transaction).toEqual('/'); + + expect(errorEvent.contexts?.trace).toEqual({ + trace_id: transactionEvent.contexts?.trace?.trace_id, + span_id: expect.not.stringContaining(transactionEvent.contexts?.trace?.span_id || ''), + }); +}); + +test('sends a navigation transaction', async ({ page }) => { + page.on('console', msg => console.log(msg.text())); + const pageLoadTransactionPromise = waitForTransaction('default-browser', async transactionEvent => { + return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload'; + }); + + const navigationTransactionPromise = waitForTransaction('default-browser', async transactionEvent => { + return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'navigation'; + }); + + await page.goto(`/`); + await pageLoadTransactionPromise; + + const linkElement = page.locator('id=navigation-link'); + + await linkElement.click(); + + const navigationTransaction = await navigationTransactionPromise; + + expect(navigationTransaction).toMatchObject({ + contexts: { + trace: { + op: 'navigation', + origin: 'auto.navigation.browser', + }, + }, + transaction: '/', + transaction_info: { + source: 'url', + }, + }); +}); From 29ac5f5658a0bed57f1ad6a84a41a38ba086e19d Mon Sep 17 00:00:00 2001 From: Kaung Zin Hein Date: Wed, 7 Aug 2024 11:55:56 -0400 Subject: [PATCH 8/9] test(browser): Update the test app to include soft navigation action --- .../default-browser/public/index.html | 8 +++++ .../default-browser/src/index.js | 4 +++ .../default-browser/tests/errors.test.ts | 30 ++++++++++++++++++- .../tests/transactions.test.ts | 25 ++++++++-------- 4 files changed, 53 insertions(+), 14 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/default-browser/public/index.html b/dev-packages/e2e-tests/test-applications/default-browser/public/index.html index 615f93028f8d..35e91be91c84 100644 --- a/dev-packages/e2e-tests/test-applications/default-browser/public/index.html +++ b/dev-packages/e2e-tests/test-applications/default-browser/public/index.html @@ -10,6 +10,14 @@ + + diff --git a/dev-packages/e2e-tests/test-applications/default-browser/src/index.js b/dev-packages/e2e-tests/test-applications/default-browser/src/index.js index 54adaa17a122..d3eea216fe84 100644 --- a/dev-packages/e2e-tests/test-applications/default-browser/src/index.js +++ b/dev-packages/e2e-tests/test-applications/default-browser/src/index.js @@ -12,3 +12,7 @@ Sentry.init({ document.getElementById('exception-button').addEventListener('click', () => { throw new Error('I am an error!'); }); + +document.getElementById('navigation-link').addEventListener('click', () => { + document.getElementById('navigation-target').scrollIntoView({ behavior: 'smooth' }); +}); diff --git a/dev-packages/e2e-tests/test-applications/default-browser/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/default-browser/tests/errors.test.ts index 496c0f5264cc..e4f2eda9a579 100644 --- a/dev-packages/e2e-tests/test-applications/default-browser/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/default-browser/tests/errors.test.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { waitForError } from '@sentry-internal/test-utils'; +import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; test('captures an error', async ({ page }) => { const errorEventPromise = waitForError('default-browser', event => { @@ -28,3 +28,31 @@ test('captures an error', async ({ page }) => { span_id: expect.any(String), }); }); + +test('sets correct transactionName', async ({ page }) => { + const transactionPromise = waitForTransaction('default-browser', async transactionEvent => { + return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload'; + }); + + const errorEventPromise = waitForError('default-browser', event => { + return !event.type && event.exception?.values?.[0]?.value === 'I am an error!'; + }); + + await page.goto('/'); + const transactionEvent = await transactionPromise; + + const exceptionButton = page.locator('id=exception-button'); + await exceptionButton.click(); + + const errorEvent = await errorEventPromise; + + expect(errorEvent.exception?.values).toHaveLength(1); + expect(errorEvent.exception?.values?.[0]?.value).toBe('I am an error!'); + + expect(errorEvent.transaction).toEqual('/'); + + expect(errorEvent.contexts?.trace).toEqual({ + trace_id: transactionEvent.contexts?.trace?.trace_id, + span_id: expect.not.stringContaining(transactionEvent.contexts?.trace?.span_id || ''), + }); +}); diff --git a/dev-packages/e2e-tests/test-applications/default-browser/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/default-browser/tests/transactions.test.ts index a3efa90ea067..5a3ed5da41ae 100644 --- a/dev-packages/e2e-tests/test-applications/default-browser/tests/transactions.test.ts +++ b/dev-packages/e2e-tests/test-applications/default-browser/tests/transactions.test.ts @@ -11,21 +11,20 @@ test('sends a pageload transaction', async ({ page }) => { }); await page.goto('/'); - const transactionEvent = await transactionPromise; - const exceptionButton = page.locator('id=exception-button'); - await exceptionButton.click(); + const rootSpan = await transactionPromise; - const errorEvent = await errorEventPromise; - - expect(errorEvent.exception?.values).toHaveLength(1); - expect(errorEvent.exception?.values?.[0]?.value).toBe('I am an error!'); - - expect(errorEvent.transaction).toEqual('/'); - - expect(errorEvent.contexts?.trace).toEqual({ - trace_id: transactionEvent.contexts?.trace?.trace_id, - span_id: expect.not.stringContaining(transactionEvent.contexts?.trace?.span_id || ''), + expect(rootSpan).toMatchObject({ + contexts: { + trace: { + op: 'pageload', + origin: 'auto.pageload.browser', + }, + }, + transaction: '/', + transaction_info: { + source: 'url', + }, }); }); From ebf9dd94c9f5e7994b272af47e09d9a1dd6b2026 Mon Sep 17 00:00:00 2001 From: Kaung Zin Hein Date: Thu, 8 Aug 2024 09:47:30 -0400 Subject: [PATCH 9/9] test(browser): Remove redundant test --- .../default-browser/tests/performance.test.ts | 36 ++++++++++- .../tests/transactions.test.ts | 62 ------------------- 2 files changed, 33 insertions(+), 65 deletions(-) delete mode 100644 dev-packages/e2e-tests/test-applications/default-browser/tests/transactions.test.ts diff --git a/dev-packages/e2e-tests/test-applications/default-browser/tests/performance.test.ts b/dev-packages/e2e-tests/test-applications/default-browser/tests/performance.test.ts index 84bdc7b392f4..7013fb43ecef 100644 --- a/dev-packages/e2e-tests/test-applications/default-browser/tests/performance.test.ts +++ b/dev-packages/e2e-tests/test-applications/default-browser/tests/performance.test.ts @@ -2,15 +2,12 @@ import { expect, test } from '@playwright/test'; import { waitForTransaction } from '@sentry-internal/test-utils'; test('captures a pageload transaction', async ({ page }) => { - // `pageload` transaction const transactionPromise = waitForTransaction('default-browser', async transactionEvent => { return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload'; }); await page.goto(`/`); - // `waitForTransaction` hangs here because `transaction` (or `span`) event is not emitted, - // so the code past this line is never executed. const pageLoadTransaction = await transactionPromise; expect(pageLoadTransaction).toEqual({ @@ -86,3 +83,36 @@ test('captures a pageload transaction', async ({ page }) => { type: 'transaction', }); }); + +test('captures a navigation transaction', async ({ page }) => { + page.on('console', msg => console.log(msg.text())); + const pageLoadTransactionPromise = waitForTransaction('default-browser', async transactionEvent => { + return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload'; + }); + + const navigationTransactionPromise = waitForTransaction('default-browser', async transactionEvent => { + return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'navigation'; + }); + + await page.goto(`/`); + await pageLoadTransactionPromise; + + const linkElement = page.locator('id=navigation-link'); + + await linkElement.click(); + + const navigationTransaction = await navigationTransactionPromise; + + expect(navigationTransaction).toMatchObject({ + contexts: { + trace: { + op: 'navigation', + origin: 'auto.navigation.browser', + }, + }, + transaction: '/', + transaction_info: { + source: 'url', + }, + }); +}); diff --git a/dev-packages/e2e-tests/test-applications/default-browser/tests/transactions.test.ts b/dev-packages/e2e-tests/test-applications/default-browser/tests/transactions.test.ts deleted file mode 100644 index 5a3ed5da41ae..000000000000 --- a/dev-packages/e2e-tests/test-applications/default-browser/tests/transactions.test.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { expect, test } from '@playwright/test'; -import { waitForError, waitForTransaction } from '@sentry-internal/test-utils'; - -test('sends a pageload transaction', async ({ page }) => { - const transactionPromise = waitForTransaction('default-browser', async transactionEvent => { - return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload'; - }); - - const errorEventPromise = waitForError('default-browser', event => { - return !event.type && event.exception?.values?.[0]?.value === 'I am an error!'; - }); - - await page.goto('/'); - - const rootSpan = await transactionPromise; - - expect(rootSpan).toMatchObject({ - contexts: { - trace: { - op: 'pageload', - origin: 'auto.pageload.browser', - }, - }, - transaction: '/', - transaction_info: { - source: 'url', - }, - }); -}); - -test('sends a navigation transaction', async ({ page }) => { - page.on('console', msg => console.log(msg.text())); - const pageLoadTransactionPromise = waitForTransaction('default-browser', async transactionEvent => { - return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'pageload'; - }); - - const navigationTransactionPromise = waitForTransaction('default-browser', async transactionEvent => { - return !!transactionEvent?.transaction && transactionEvent.contexts?.trace?.op === 'navigation'; - }); - - await page.goto(`/`); - await pageLoadTransactionPromise; - - const linkElement = page.locator('id=navigation-link'); - - await linkElement.click(); - - const navigationTransaction = await navigationTransactionPromise; - - expect(navigationTransaction).toMatchObject({ - contexts: { - trace: { - op: 'navigation', - origin: 'auto.navigation.browser', - }, - }, - transaction: '/', - transaction_info: { - source: 'url', - }, - }); -});