From 8c8a6015558c169fa23259d03945fd145837362e Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Thu, 2 Mar 2023 13:52:42 +0000 Subject: [PATCH 01/44] feat(nextjs): Connect traces for server components --- packages/nextjs/src/common/types.ts | 2 ++ .../src/config/loaders/wrappingLoader.ts | 2 +- .../serverComponentWrapperTemplate.ts | 30 +++++++++++++++++-- .../server/wrapServerComponentWithSentry.ts | 9 ++++++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/packages/nextjs/src/common/types.ts b/packages/nextjs/src/common/types.ts index d21f3fa92880..cfac0c460a84 100644 --- a/packages/nextjs/src/common/types.ts +++ b/packages/nextjs/src/common/types.ts @@ -1,4 +1,6 @@ export type ServerComponentContext = { componentRoute: string; componentType: string; + sentryTraceHeader?: string; + baggageHeader?: string; }; diff --git a/packages/nextjs/src/config/loaders/wrappingLoader.ts b/packages/nextjs/src/config/loaders/wrappingLoader.ts index 879855cafa08..fb3e76be72f0 100644 --- a/packages/nextjs/src/config/loaders/wrappingLoader.ts +++ b/packages/nextjs/src/config/loaders/wrappingLoader.ts @@ -119,7 +119,7 @@ export default function wrappingLoader( // https://github.com/vercel/next.js/blob/295f9da393f7d5a49b0c2e15a2f46448dbdc3895/packages/next/build/analysis/get-page-static-info.ts#L37 // https://github.com/vercel/next.js/blob/a1c15d84d906a8adf1667332a3f0732be615afa0/packages/next-swc/crates/core/src/react_server_components.rs#L247 // We do not want to wrap client components - if (userCode.includes('/* __next_internal_client_entry_do_not_use__ */')) { + if (userCode.includes('__next_internal_client_entry_do_not_use__')) { this.callback(null, userCode, userModuleSourceMap); return; } diff --git a/packages/nextjs/src/config/templates/serverComponentWrapperTemplate.ts b/packages/nextjs/src/config/templates/serverComponentWrapperTemplate.ts index 74e8e1a5b1c3..61eba1aa2353 100644 --- a/packages/nextjs/src/config/templates/serverComponentWrapperTemplate.ts +++ b/packages/nextjs/src/config/templates/serverComponentWrapperTemplate.ts @@ -11,6 +11,9 @@ import * as wrapee from '__SENTRY_WRAPPING_TARGET_FILE__'; // eslint-disable-next-line import/no-extraneous-dependencies import * as Sentry from '@sentry/nextjs'; +// @ts-ignore TODO +// eslint-disable-next-line import/no-unresolved +import { headers } from 'next/headers'; type ServerComponentModule = { default: unknown; @@ -22,9 +25,30 @@ const serverComponent = serverComponentModule.default; let wrappedServerComponent; if (typeof serverComponent === 'function') { - wrappedServerComponent = Sentry.wrapServerComponentWithSentry(serverComponent, { - componentRoute: '__ROUTE__', - componentType: '__COMPONENT_TYPE__', + // TODO: explain why this code needs to be in this file + wrappedServerComponent = new Proxy(serverComponent, { + apply: (originalFunction, thisArg, args) => { + let sentryTraceHeader: string | undefined = undefined; + let baggageHeader: string | undefined = undefined; + + if (process.env.NEXT_PHASE !== 'phase-production-build') { + // @ts-ignore TODO + // eslint-disable-next-line import/no-unresolved + // const { headers } = await import('next/headers'); + const headersList = headers(); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + sentryTraceHeader = headersList.get('sentry-trace'); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + baggageHeader = headersList.get('baggage'); + } + + return Sentry.wrapServerComponentWithSentry(originalFunction, { + componentRoute: '__ROUTE__', + componentType: '__COMPONENT_TYPE__', + sentryTraceHeader, + baggageHeader, + }).apply(thisArg, args); + }, }); } else { wrappedServerComponent = serverComponent; diff --git a/packages/nextjs/src/server/wrapServerComponentWithSentry.ts b/packages/nextjs/src/server/wrapServerComponentWithSentry.ts index 05c17c6bede3..eac6a9405ac6 100644 --- a/packages/nextjs/src/server/wrapServerComponentWithSentry.ts +++ b/packages/nextjs/src/server/wrapServerComponentWithSentry.ts @@ -1,4 +1,5 @@ import { captureException, getCurrentHub, startTransaction } from '@sentry/core'; +import { baggageHeaderToDynamicSamplingContext, extractTraceparentData } from '@sentry/utils'; import * as domain from 'domain'; import type { ServerComponentContext } from '../common/types'; @@ -20,12 +21,20 @@ export function wrapServerComponentWithSentry any> return domain.create().bind(() => { let maybePromiseResult; + const traceparentData = context.sentryTraceHeader + ? extractTraceparentData(context.sentryTraceHeader) + : undefined; + + const dynamicSamplingContext = baggageHeaderToDynamicSamplingContext(context.baggageHeader); + const transaction = startTransaction({ op: 'function.nextjs', name: `${componentType} Server Component (${componentRoute})`, status: 'ok', + ...traceparentData, metadata: { source: 'component', + dynamicSamplingContext: traceparentData && !dynamicSamplingContext ? {} : dynamicSamplingContext, }, }); From 621a8e35e5d5e39e912a67d9e1b16c103ef1efae Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Thu, 2 Mar 2023 15:05:25 +0000 Subject: [PATCH 02/44] . --- .../test-applications/nextjs-13-app-dir/app/layout.tsx | 7 ++++++- .../test-applications/nextjs-13-app-dir/app/not-found.tsx | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 packages/e2e-tests/test-applications/nextjs-13-app-dir/app/not-found.tsx diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/layout.tsx b/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/layout.tsx index f3ef34cd8b91..a6d9db153d90 100644 --- a/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/layout.tsx +++ b/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/layout.tsx @@ -1,7 +1,12 @@ export default function RootLayout({ children }: { children: React.ReactNode }) { return ( - {children} + +
+

Root layout

+ {children} +
+ ); } diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/not-found.tsx b/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/not-found.tsx new file mode 100644 index 000000000000..e8dd53dd85a0 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/not-found.tsx @@ -0,0 +1,3 @@ +export default function NotFound() { + return

Not found

; +} From c2d6cc7a14ac9be8381f1e1102c920774f6d126b Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Fri, 3 Mar 2023 13:10:11 +0000 Subject: [PATCH 03/44] ref(e2e): Make app dir tests more thorough --- .../app/client-component/page.tsx | 17 - .../nextjs-13-app-dir/app/layout.tsx | 12 - .../nextjs-13-app-dir/app/not-found.tsx | 3 - .../nextjs-13-app-dir/app/page.tsx | 22 - .../nextjs-13-app-dir/app/user/[id]/page.tsx | 4 - .../nextjs-13-app-dir/yarn.lock | 369 -------- .../.gitignore | 0 .../.npmrc | 0 .../parameter/[...parameters]/error.tsx | 11 + .../parameter/[...parameters]/layout.tsx | 8 + .../parameter/[...parameters]/loading.tsx | 7 + .../parameter/[...parameters]/not-found.tsx | 7 + .../parameter/[...parameters]/page.tsx | 12 + .../parameter/[parameter]/error.tsx | 11 + .../parameter/[parameter]/layout.tsx | 8 + .../parameter/[parameter]/loading.tsx | 7 + .../parameter/[parameter]/not-found.tsx | 7 + .../parameter/[parameter]/page.tsx | 10 + .../client-component/render-error/error.tsx | 11 + .../client-component/render-error/layout.tsx | 10 + .../client-component/render-error/loading.tsx | 7 + .../render-error/not-found.tsx | 7 + .../client-component/render-error/page.tsx | 10 + .../nextjs-app-dir/app/error.tsx | 11 + .../nextjs-app-dir/app/layout.tsx | 32 + .../nextjs-app-dir/app/loading.tsx | 7 + .../nextjs-app-dir/app/not-found.tsx | 7 + .../nextjs-app-dir/app/page.tsx | 10 + .../components/client-error-debug-tools.tsx | 89 ++ .../components/transaction-context.tsx | 32 + .../globals.d.ts | 0 .../next-env.d.ts | 2 +- .../next.config.js | 0 .../package.json | 0 .../nextjs-app-dir/pages/api/edge-endpoint.ts | 3 + .../nextjs-app-dir/pages/api/endpoint.ts | 9 + .../playwright.config.ts | 0 .../sentry.client.config.ts | 0 .../sentry.edge.config.ts | 0 .../sentry.server.config.ts | 0 .../start-event-proxy.ts | 0 .../test-recipe.json | 0 .../tests/devErrorSymbolification.test.ts | 0 .../tests/exceptions.test.ts | 0 .../tests/transactions.test.ts | 0 .../tsconfig.json | 0 .../nextjs-app-dir/yarn.lock | 804 ++++++++++++++++++ 47 files changed, 1138 insertions(+), 428 deletions(-) delete mode 100644 packages/e2e-tests/test-applications/nextjs-13-app-dir/app/client-component/page.tsx delete mode 100644 packages/e2e-tests/test-applications/nextjs-13-app-dir/app/layout.tsx delete mode 100644 packages/e2e-tests/test-applications/nextjs-13-app-dir/app/not-found.tsx delete mode 100644 packages/e2e-tests/test-applications/nextjs-13-app-dir/app/page.tsx delete mode 100644 packages/e2e-tests/test-applications/nextjs-13-app-dir/app/user/[id]/page.tsx delete mode 100644 packages/e2e-tests/test-applications/nextjs-13-app-dir/yarn.lock rename packages/e2e-tests/test-applications/{nextjs-13-app-dir => nextjs-app-dir}/.gitignore (100%) rename packages/e2e-tests/test-applications/{nextjs-13-app-dir => nextjs-app-dir}/.npmrc (100%) create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/error.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/layout.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/loading.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/not-found.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/page.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/error.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/layout.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/loading.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/not-found.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/page.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/error.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/layout.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/loading.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/not-found.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/page.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/error.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/layout.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/loading.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/not-found.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/page.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/components/client-error-debug-tools.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/components/transaction-context.tsx rename packages/e2e-tests/test-applications/{nextjs-13-app-dir => nextjs-app-dir}/globals.d.ts (100%) rename packages/e2e-tests/test-applications/{nextjs-13-app-dir => nextjs-app-dir}/next-env.d.ts (75%) rename packages/e2e-tests/test-applications/{nextjs-13-app-dir => nextjs-app-dir}/next.config.js (100%) rename packages/e2e-tests/test-applications/{nextjs-13-app-dir => nextjs-app-dir}/package.json (100%) create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/pages/api/edge-endpoint.ts create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/pages/api/endpoint.ts rename packages/e2e-tests/test-applications/{nextjs-13-app-dir => nextjs-app-dir}/playwright.config.ts (100%) rename packages/e2e-tests/test-applications/{nextjs-13-app-dir => nextjs-app-dir}/sentry.client.config.ts (100%) rename packages/e2e-tests/test-applications/{nextjs-13-app-dir => nextjs-app-dir}/sentry.edge.config.ts (100%) rename packages/e2e-tests/test-applications/{nextjs-13-app-dir => nextjs-app-dir}/sentry.server.config.ts (100%) rename packages/e2e-tests/test-applications/{nextjs-13-app-dir => nextjs-app-dir}/start-event-proxy.ts (100%) rename packages/e2e-tests/test-applications/{nextjs-13-app-dir => nextjs-app-dir}/test-recipe.json (100%) rename packages/e2e-tests/test-applications/{nextjs-13-app-dir => nextjs-app-dir}/tests/devErrorSymbolification.test.ts (100%) rename packages/e2e-tests/test-applications/{nextjs-13-app-dir => nextjs-app-dir}/tests/exceptions.test.ts (100%) rename packages/e2e-tests/test-applications/{nextjs-13-app-dir => nextjs-app-dir}/tests/transactions.test.ts (100%) rename packages/e2e-tests/test-applications/{nextjs-13-app-dir => nextjs-app-dir}/tsconfig.json (100%) create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/yarn.lock diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/client-component/page.tsx b/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/client-component/page.tsx deleted file mode 100644 index b1d7f708cfae..000000000000 --- a/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/client-component/page.tsx +++ /dev/null @@ -1,17 +0,0 @@ -'use client'; - -export default function Page() { - return ( -
-

Press to throw:

- -
- ); -} diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/layout.tsx b/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/layout.tsx deleted file mode 100644 index a6d9db153d90..000000000000 --- a/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/layout.tsx +++ /dev/null @@ -1,12 +0,0 @@ -export default function RootLayout({ children }: { children: React.ReactNode }) { - return ( - - -
-

Root layout

- {children} -
- - - ); -} diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/not-found.tsx b/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/not-found.tsx deleted file mode 100644 index e8dd53dd85a0..000000000000 --- a/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/not-found.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function NotFound() { - return

Not found

; -} diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/page.tsx b/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/page.tsx deleted file mode 100644 index 1caf96ed7786..000000000000 --- a/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/page.tsx +++ /dev/null @@ -1,22 +0,0 @@ -'use client'; - -import * as Sentry from '@sentry/nextjs'; -import Link from 'next/link'; - -export default function Home() { - return ( -
- { - Sentry.captureException(new Error('I am a click error!')); - }} - /> - - navigate - -
- ); -} diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/user/[id]/page.tsx b/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/user/[id]/page.tsx deleted file mode 100644 index bdb52ea5547a..000000000000 --- a/packages/e2e-tests/test-applications/nextjs-13-app-dir/app/user/[id]/page.tsx +++ /dev/null @@ -1,4 +0,0 @@ -export default async function Home() { - const dynamid = await (await fetch('http://example.com', { cache: 'no-store' })).text(); // do a fetch request so that this server component is always rendered when requested - return

I am a blank page :) {dynamid}

; -} diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/yarn.lock b/packages/e2e-tests/test-applications/nextjs-13-app-dir/yarn.lock deleted file mode 100644 index 14727ded24f5..000000000000 --- a/packages/e2e-tests/test-applications/nextjs-13-app-dir/yarn.lock +++ /dev/null @@ -1,369 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@cspotcode/source-map-support@^0.8.0": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" - integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== - dependencies: - "@jridgewell/trace-mapping" "0.3.9" - -"@jridgewell/resolve-uri@^3.0.3": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== - -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@next/env@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/env/-/env-13.2.1.tgz#082d42cfc0c794e9185d7b4133d71440ba2e795d" - integrity sha512-Hq+6QZ6kgmloCg8Kgrix+4F0HtvLqVK3FZAnlAoS0eonaDemHe1Km4kwjSWRE3JNpJNcKxFHF+jsZrYo0SxWoQ== - -"@next/font@13.0.7": - version "13.0.7" - resolved "https://registry.yarnpkg.com/@next/font/-/font-13.0.7.tgz#e0046376edb0ce592d9cfddea8f4ab321eb1515a" - integrity sha512-39SzuoMI6jbrIzPs3KtXdKX03OrVp6Y7kRHcoVmOg69spiBzruPJ5x5DQSfN+OXqznbvVBNZBXnmdnSqs3qXiA== - -"@next/swc-android-arm-eabi@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.2.1.tgz#67f2580fbbe05ee006220688972c5e3a555fc741" - integrity sha512-Yua7mUpEd1wzIT6Jjl3dpRizIfGp9NR4F2xeRuQv+ae+SDI1Em2WyM9m46UL+oeW5GpMiEHoaBagr47RScZFmQ== - -"@next/swc-android-arm64@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-13.2.1.tgz#460a02b69eb23bb5f402266bcea9cadae59415c1" - integrity sha512-Bifcr2f6VwInOdq1uH/9lp8fH7Nf7XGkIx4XceVd32LPJqG2c6FZU8ZRBvTdhxzXVpt5TPtuXhOP4Ij9UPqsVw== - -"@next/swc-darwin-arm64@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.2.1.tgz#8b8530ff417802027471aee2419f78a58a863ccb" - integrity sha512-gvqm+fGMYxAkwBapH0Vvng5yrb6HTkIvZfY4oEdwwYrwuLdkjqnJygCMgpNqIFmAHSXgtlWxfYv1VC8sjN81Kw== - -"@next/swc-darwin-x64@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.2.1.tgz#80aebb3329a1e4568a28de1ee177780b3d50330c" - integrity sha512-HGqVqmaZWj6zomqOZUVbO5NhlABL0iIaxTmd0O5B0MoMa5zpDGoaHSG+fxgcWMXcGcxmUNchv1NfNOYiTKoHOg== - -"@next/swc-freebsd-x64@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.2.1.tgz#250ea2ab7e1734f22d11c677c463fab9ac33a516" - integrity sha512-N/a4JarAq+E+g+9K2ywJUmDIgU2xs2nA+BBldH0oq4zYJMRiUhL0iaN9G4e72VmGOJ61L/3W6VN8RIUOwTLoqQ== - -"@next/swc-linux-arm-gnueabihf@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.2.1.tgz#fe6bb29ed348a5f8ecae3740df22a8d8130c474a" - integrity sha512-WaFoerF/eRbhbE57TaIGJXbQAERADZ/RZ45u6qox9beb5xnWsyYgzX+WuN7Tkhyvga0/aMuVYFzS9CEay7D+bw== - -"@next/swc-linux-arm64-gnu@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.2.1.tgz#4781b927fc5e421f3cea2b29e5d38e5e4837b198" - integrity sha512-R+Jhc1/RJTnncE9fkePboHDNOCm1WJ8daanWbjKhfPySMyeniKYRwGn5SLYW3S8YlRS0QVdZaaszDSZWgUcsmA== - -"@next/swc-linux-arm64-musl@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.2.1.tgz#c2ba0a121b0255ba62450916bc70e6d0e26cbc98" - integrity sha512-oI1UfZPidGAVddlL2eOTmfsuKV9EaT1aktIzVIxIAgxzQSdwsV371gU3G55ggkurzfdlgF3GThFePDWF0d8dmw== - -"@next/swc-linux-x64-gnu@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.2.1.tgz#573c220f8b087e5d131d1fba58d3e1a670b220ad" - integrity sha512-PCygPwrQmS+7WUuAWWioWMZCzZm4PG91lfRxToLDg7yIm/3YfAw5N2EK2TaM9pzlWdvHQAqRMX/oLvv027xUiA== - -"@next/swc-linux-x64-musl@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.2.1.tgz#950b5bb920b322ca7b447efbd12a9c7a10c3a642" - integrity sha512-sUAKxo7CFZYGHNxheGh9nIBElLYBM6md/liEGfOTwh/xna4/GTTcmkGWkF7PdnvaYNgcPIQgHIMYiAa6yBKAVw== - -"@next/swc-win32-arm64-msvc@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.2.1.tgz#dbff3c4f5a3812a7059dac05804148a0f98682db" - integrity sha512-qDmyEjDBpl/vBXxuOOKKWmPQOcARcZIMach1s7kjzaien0SySut/PHRlj56sosa81Wt4hTGhfhZ1R7g1n7+B8w== - -"@next/swc-win32-ia32-msvc@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.2.1.tgz#7d2c17be7b8d9963984f5c15cc2588127101f620" - integrity sha512-2joqFQ81ZYPg6DcikIzQn3DgjKglNhPAozx6dL5sCNkr1CPMD0YIkJgT3CnYyMHQ04Qi3Npv0XX3MD6LJO8OCA== - -"@next/swc-win32-x64-msvc@13.2.1": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.2.1.tgz#09713c6a925461f414e89422851326d1625bd4d2" - integrity sha512-r3+0fSaIZT6N237iMzwUhfNwjhAFvXjqB+4iuW+wcpxW+LHm1g/IoxN8eSRcb8jPItC86JxjAxpke0QL97qd6g== - -"@playwright/test@^1.27.1": - version "1.31.1" - resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.31.1.tgz#39d6873dc46af135f12451d79707db7d1357455d" - integrity sha512-IsytVZ+0QLDh1Hj83XatGp/GsI1CDJWbyDaBGbainsh0p2zC7F4toUocqowmjS6sQff2NGT3D9WbDj/3K2CJiA== - dependencies: - "@types/node" "*" - playwright-core "1.31.1" - optionalDependencies: - fsevents "2.3.2" - -"@swc/helpers@0.4.14": - version "0.4.14" - resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.14.tgz#1352ac6d95e3617ccb7c1498ff019654f1e12a74" - integrity sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw== - dependencies: - tslib "^2.4.0" - -"@tsconfig/node10@^1.0.7": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" - integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== - -"@tsconfig/node12@^1.0.7": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" - integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== - -"@tsconfig/node14@^1.0.0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" - integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== - -"@tsconfig/node16@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" - integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== - -"@types/node@*": - version "18.14.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.14.1.tgz#90dad8476f1e42797c49d6f8b69aaf9f876fc69f" - integrity sha512-QH+37Qds3E0eDlReeboBxfHbX9omAcBCXEzswCu6jySP642jiM3cYSIkU/REqwhCUqXdonHFuBfJDiAJxMNhaQ== - -"@types/node@18.11.17": - version "18.11.17" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.17.tgz#5c009e1d9c38f4a2a9d45c0b0c493fe6cdb4bcb5" - integrity sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng== - -"@types/prop-types@*": - version "15.7.5" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" - integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== - -"@types/react-dom@18.0.9": - version "18.0.9" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.9.tgz#ffee5e4bfc2a2f8774b15496474f8e7fe8d0b504" - integrity sha512-qnVvHxASt/H7i+XG1U1xMiY5t+IHcPGUK7TDMDzom08xa7e86eCeKOiLZezwCKVxJn6NEiiy2ekgX8aQssjIKg== - dependencies: - "@types/react" "*" - -"@types/react@*": - version "18.0.28" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.28.tgz#accaeb8b86f4908057ad629a26635fe641480065" - integrity sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" - -"@types/react@18.0.26": - version "18.0.26" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.26.tgz#8ad59fc01fef8eaf5c74f4ea392621749f0b7917" - integrity sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" - -"@types/scheduler@*": - version "0.16.2" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" - integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== - -acorn-walk@^8.1.1: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== - -acorn@^8.4.1: - version "8.8.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" - integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== - -arg@^4.1.0: - version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== - -caniuse-lite@^1.0.30001406: - version "1.0.30001457" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001457.tgz#6af34bb5d720074e2099432aa522c21555a18301" - integrity sha512-SDIV6bgE1aVbK6XyxdURbUE89zY7+k1BBBaOwYwkNCglXlel/E7mELiHC64HQ+W0xSKlqWhV9Wh7iHxUjMs4fA== - -client-only@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" - integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== - -create-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - -csstype@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" - integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== - -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - -fsevents@2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -"js-tokens@^3.0.0 || ^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -loose-envify@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -make-error@^1.1.1: - version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== - -nanoid@^3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" - integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== - -next@13.2.1: - version "13.2.1" - resolved "https://registry.yarnpkg.com/next/-/next-13.2.1.tgz#34d823f518632b36379863228ed9f861c335b9c0" - integrity sha512-qhgJlDtG0xidNViJUPeQHLGJJoT4zDj/El7fP3D3OzpxJDUfxsm16cK4WTMyvSX1ciIfAq05u+0HqFAa+VJ+Hg== - dependencies: - "@next/env" "13.2.1" - "@swc/helpers" "0.4.14" - caniuse-lite "^1.0.30001406" - postcss "8.4.14" - styled-jsx "5.1.1" - optionalDependencies: - "@next/swc-android-arm-eabi" "13.2.1" - "@next/swc-android-arm64" "13.2.1" - "@next/swc-darwin-arm64" "13.2.1" - "@next/swc-darwin-x64" "13.2.1" - "@next/swc-freebsd-x64" "13.2.1" - "@next/swc-linux-arm-gnueabihf" "13.2.1" - "@next/swc-linux-arm64-gnu" "13.2.1" - "@next/swc-linux-arm64-musl" "13.2.1" - "@next/swc-linux-x64-gnu" "13.2.1" - "@next/swc-linux-x64-musl" "13.2.1" - "@next/swc-win32-arm64-msvc" "13.2.1" - "@next/swc-win32-ia32-msvc" "13.2.1" - "@next/swc-win32-x64-msvc" "13.2.1" - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -playwright-core@1.31.1: - version "1.31.1" - resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.31.1.tgz#4deeebbb8fb73b512593fe24bea206d8fd85ff7f" - integrity sha512-JTyX4kV3/LXsvpHkLzL2I36aCdml4zeE35x+G5aPc4bkLsiRiQshU5lWeVpHFAuC8xAcbI6FDcw/8z3q2xtJSQ== - -postcss@8.4.14: - version "8.4.14" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf" - integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig== - dependencies: - nanoid "^3.3.4" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -react-dom@18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" - integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== - dependencies: - loose-envify "^1.1.0" - scheduler "^0.23.0" - -react@18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" - integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== - dependencies: - loose-envify "^1.1.0" - -scheduler@^0.23.0: - version "0.23.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" - integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== - dependencies: - loose-envify "^1.1.0" - -source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== - -styled-jsx@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f" - integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw== - dependencies: - client-only "0.0.1" - -ts-node@10.9.1: - version "10.9.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" - integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== - dependencies: - "@cspotcode/source-map-support" "^0.8.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - v8-compile-cache-lib "^3.0.1" - yn "3.1.1" - -tslib@^2.4.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" - integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== - -typescript@4.9.4: - version "4.9.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.4.tgz#a2a3d2756c079abda241d75f149df9d561091e78" - integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg== - -v8-compile-cache-lib@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" - integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== - -yn@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/.gitignore b/packages/e2e-tests/test-applications/nextjs-app-dir/.gitignore similarity index 100% rename from packages/e2e-tests/test-applications/nextjs-13-app-dir/.gitignore rename to packages/e2e-tests/test-applications/nextjs-app-dir/.gitignore diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/.npmrc b/packages/e2e-tests/test-applications/nextjs-app-dir/.npmrc similarity index 100% rename from packages/e2e-tests/test-applications/nextjs-13-app-dir/.npmrc rename to packages/e2e-tests/test-applications/nextjs-app-dir/.npmrc diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/error.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/error.tsx new file mode 100644 index 000000000000..8c52619b80b1 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/error.tsx @@ -0,0 +1,11 @@ +'use client'; + +export default function Error({ error, reset }: { error: Error; reset: () => void }) { + return ( +
+

Error (/client-component/[...parameters])

+ + Error: {error.toString()} +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/layout.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/layout.tsx new file mode 100644 index 000000000000..9150d773cf7f --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/layout.tsx @@ -0,0 +1,8 @@ +export default function Layout({ children }: { children: React.ReactNode }) { + return ( +
+

Layout (/client-component/[...parameters])

+ {children} +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/loading.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/loading.tsx new file mode 100644 index 000000000000..1c89093040e8 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+

Loading (/)

+
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/not-found.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/not-found.tsx new file mode 100644 index 000000000000..c56f5aa409f5 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/not-found.tsx @@ -0,0 +1,7 @@ +export default function NotFound() { + return ( +
+

Not found (/client-component/[...parameters])

; +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/page.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/page.tsx new file mode 100644 index 000000000000..2079f995761f --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/page.tsx @@ -0,0 +1,12 @@ +'use client'; + +import { ClientErrorDebugTools } from '../../../../components/client-error-debug-tools'; + +export default function Page() { + return ( +
+

Page (/client-component/[...parameters])

+ +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/error.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/error.tsx new file mode 100644 index 000000000000..92948207a2fe --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/error.tsx @@ -0,0 +1,11 @@ +'use client'; + +export default function Error({ error, reset }: { error: Error; reset: () => void }) { + return ( +
+

Error (/client-component/[parameter])

+ + Error: {error.toString()} +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/layout.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/layout.tsx new file mode 100644 index 000000000000..f2ffd2306d06 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/layout.tsx @@ -0,0 +1,8 @@ +export default function Layout({ children }: { children: React.ReactNode }) { + return ( +
+

Layout (/client-component/[parameter])

+ {children} +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/loading.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/loading.tsx new file mode 100644 index 000000000000..94ad013d3986 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+

Loading (/client-component/[parameter])

+
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/not-found.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/not-found.tsx new file mode 100644 index 000000000000..48c215c930e2 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/not-found.tsx @@ -0,0 +1,7 @@ +export default function NotFound() { + return ( +
+

Not found (/client-component/[parameter])

; +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/page.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/page.tsx new file mode 100644 index 000000000000..59bcc6fb5653 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/page.tsx @@ -0,0 +1,10 @@ +import { ClientErrorDebugTools } from '../../../../components/client-error-debug-tools'; + +export default function Page() { + return ( +
+

Page (/client-component/[parameter])

+ +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/error.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/error.tsx new file mode 100644 index 000000000000..765178323209 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/error.tsx @@ -0,0 +1,11 @@ +'use client'; + +export default function Error({ error, reset }: { error: Error; reset: () => void }) { + return ( +
+

Error (/client-component/render-error)

+ + Error: {error.toString()} +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/layout.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/layout.tsx new file mode 100644 index 000000000000..ab443e2db74d --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/layout.tsx @@ -0,0 +1,10 @@ +import Link from 'next/link'; + +export default function Layout({ children }: { children: React.ReactNode }) { + return ( +
+

Layout (/client-component/render-error)

+ {children} +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/loading.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/loading.tsx new file mode 100644 index 000000000000..1cb3e68a4206 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+

Loading (/client-component/render-error)

+
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/not-found.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/not-found.tsx new file mode 100644 index 000000000000..235740492e05 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/not-found.tsx @@ -0,0 +1,7 @@ +export default function NotFound() { + return ( +
+

Not found (/client-component/render-error)

; +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/page.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/page.tsx new file mode 100644 index 000000000000..ec06b578f60a --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/page.tsx @@ -0,0 +1,10 @@ +import { ClientErrorDebugTools } from '../../../components/client-error-debug-tools'; + +export default function Page() { + return ( +
+

Page (/client-component/render-error)

+ +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/error.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/error.tsx new file mode 100644 index 000000000000..02a192259aec --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/error.tsx @@ -0,0 +1,11 @@ +'use client'; + +export default function Error({ error, reset }: { error: Error; reset: () => void }) { + return ( +
+

Error (/)

+ + Error: {error.toString()} +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/layout.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/layout.tsx new file mode 100644 index 000000000000..361eb304f2d0 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/layout.tsx @@ -0,0 +1,32 @@ +import { TransactionContextProvider } from '../components/transaction-context'; +import Link from 'next/link'; + +export default function Layout({ children }: { children: React.ReactNode }) { + return ( + + +
+

Layout (/)

+
    +
  • + /client-component/parameter/foo/bar/baz +
  • +
  • + /client-component/parameter/1/2 +
  • +
  • + /client-component/parameter/1/2 +
  • +
  • + /client-component/parameter/1/2 +
  • +
  • + /client-component/parameter/1/2 +
  • +
+ {children} +
+ + + ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/loading.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/loading.tsx new file mode 100644 index 000000000000..1c89093040e8 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/loading.tsx @@ -0,0 +1,7 @@ +export default function Loading() { + return ( +
+

Loading (/)

+
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/not-found.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/not-found.tsx new file mode 100644 index 000000000000..5e7b156553a6 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/not-found.tsx @@ -0,0 +1,7 @@ +export default function NotFound() { + return ( +
+

Not found (/)

; +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/page.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/page.tsx new file mode 100644 index 000000000000..edaffa368ace --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/page.tsx @@ -0,0 +1,10 @@ +import { ClientErrorDebugTools } from '../components/client-error-debug-tools'; + +export default function Page() { + return ( +
+

Page (/)

+ +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/components/client-error-debug-tools.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/components/client-error-debug-tools.tsx new file mode 100644 index 000000000000..8c1a744f211e --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/components/client-error-debug-tools.tsx @@ -0,0 +1,89 @@ +'use client'; + +import { useContext, useState } from 'react'; +import { TransactionContext } from './transaction-context'; +import { captureException } from '@sentry/nextjs'; + +export function ClientErrorDebugTools() { + const { transactionActive, toggle } = useContext(TransactionContext); + + const [isFetchingAPIRoute, setIsFetchingAPIRoute] = useState(); + const [isFetchingEdgeAPIRoute, setIsFetchingEdgeAPIRoute] = useState(); + const [isFetchingExternalAPIRoute, setIsFetchingExternalAPIRoute] = useState(); + + return ( +
+ +
+
+ +
+ +
+
+ +
+ +
+ +
+
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/components/transaction-context.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/components/transaction-context.tsx new file mode 100644 index 000000000000..2c0b851bda73 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/components/transaction-context.tsx @@ -0,0 +1,32 @@ +'use client'; + +import { createContext, PropsWithChildren, useState } from 'react'; +import { Transaction } from '@sentry/types'; +import { startTransaction } from '@sentry/nextjs'; + +export const TransactionContext = createContext<{ transactionActive: boolean; toggle: () => void }>({ + transactionActive: false, + toggle: () => undefined, +}); + +export function TransactionContextProvider({ children }: PropsWithChildren) { + const [transaction, setTransaction] = useState(undefined); + + return ( + { + if (transaction) { + transaction.finish(); + setTransaction(undefined); + } else { + setTransaction(startTransaction({ name: 'Manual Transaction' })); + } + }, + }} + > + {children} + + ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/globals.d.ts b/packages/e2e-tests/test-applications/nextjs-app-dir/globals.d.ts similarity index 100% rename from packages/e2e-tests/test-applications/nextjs-13-app-dir/globals.d.ts rename to packages/e2e-tests/test-applications/nextjs-app-dir/globals.d.ts diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/next-env.d.ts b/packages/e2e-tests/test-applications/nextjs-app-dir/next-env.d.ts similarity index 75% rename from packages/e2e-tests/test-applications/nextjs-13-app-dir/next-env.d.ts rename to packages/e2e-tests/test-applications/nextjs-app-dir/next-env.d.ts index 7aa8e8ef74e1..fd36f9494e2c 100644 --- a/packages/e2e-tests/test-applications/nextjs-13-app-dir/next-env.d.ts +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -/// +/// // NOTE: This file should not be edited // see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/next.config.js b/packages/e2e-tests/test-applications/nextjs-app-dir/next.config.js similarity index 100% rename from packages/e2e-tests/test-applications/nextjs-13-app-dir/next.config.js rename to packages/e2e-tests/test-applications/nextjs-app-dir/next.config.js diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/package.json b/packages/e2e-tests/test-applications/nextjs-app-dir/package.json similarity index 100% rename from packages/e2e-tests/test-applications/nextjs-13-app-dir/package.json rename to packages/e2e-tests/test-applications/nextjs-app-dir/package.json diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/pages/api/edge-endpoint.ts b/packages/e2e-tests/test-applications/nextjs-app-dir/pages/api/edge-endpoint.ts new file mode 100644 index 000000000000..d8af89f2e9d5 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/pages/api/edge-endpoint.ts @@ -0,0 +1,3 @@ +export const config = { runtime: 'edge' }; + +export default () => new Response('Hello world!'); diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/pages/api/endpoint.ts b/packages/e2e-tests/test-applications/nextjs-app-dir/pages/api/endpoint.ts new file mode 100644 index 000000000000..2ca75a33ba7e --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/pages/api/endpoint.ts @@ -0,0 +1,9 @@ +import type { NextApiRequest, NextApiResponse } from 'next'; + +type Data = { + name: string; +}; + +export default function handler(req: NextApiRequest, res: NextApiResponse) { + res.status(200).json({ name: 'John Doe' }); +} diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/playwright.config.ts b/packages/e2e-tests/test-applications/nextjs-app-dir/playwright.config.ts similarity index 100% rename from packages/e2e-tests/test-applications/nextjs-13-app-dir/playwright.config.ts rename to packages/e2e-tests/test-applications/nextjs-app-dir/playwright.config.ts diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/sentry.client.config.ts b/packages/e2e-tests/test-applications/nextjs-app-dir/sentry.client.config.ts similarity index 100% rename from packages/e2e-tests/test-applications/nextjs-13-app-dir/sentry.client.config.ts rename to packages/e2e-tests/test-applications/nextjs-app-dir/sentry.client.config.ts diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/sentry.edge.config.ts b/packages/e2e-tests/test-applications/nextjs-app-dir/sentry.edge.config.ts similarity index 100% rename from packages/e2e-tests/test-applications/nextjs-13-app-dir/sentry.edge.config.ts rename to packages/e2e-tests/test-applications/nextjs-app-dir/sentry.edge.config.ts diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/sentry.server.config.ts b/packages/e2e-tests/test-applications/nextjs-app-dir/sentry.server.config.ts similarity index 100% rename from packages/e2e-tests/test-applications/nextjs-13-app-dir/sentry.server.config.ts rename to packages/e2e-tests/test-applications/nextjs-app-dir/sentry.server.config.ts diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/start-event-proxy.ts b/packages/e2e-tests/test-applications/nextjs-app-dir/start-event-proxy.ts similarity index 100% rename from packages/e2e-tests/test-applications/nextjs-13-app-dir/start-event-proxy.ts rename to packages/e2e-tests/test-applications/nextjs-app-dir/start-event-proxy.ts diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/test-recipe.json b/packages/e2e-tests/test-applications/nextjs-app-dir/test-recipe.json similarity index 100% rename from packages/e2e-tests/test-applications/nextjs-13-app-dir/test-recipe.json rename to packages/e2e-tests/test-applications/nextjs-app-dir/test-recipe.json diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/tests/devErrorSymbolification.test.ts b/packages/e2e-tests/test-applications/nextjs-app-dir/tests/devErrorSymbolification.test.ts similarity index 100% rename from packages/e2e-tests/test-applications/nextjs-13-app-dir/tests/devErrorSymbolification.test.ts rename to packages/e2e-tests/test-applications/nextjs-app-dir/tests/devErrorSymbolification.test.ts diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/tests/exceptions.test.ts b/packages/e2e-tests/test-applications/nextjs-app-dir/tests/exceptions.test.ts similarity index 100% rename from packages/e2e-tests/test-applications/nextjs-13-app-dir/tests/exceptions.test.ts rename to packages/e2e-tests/test-applications/nextjs-app-dir/tests/exceptions.test.ts diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/tests/transactions.test.ts b/packages/e2e-tests/test-applications/nextjs-app-dir/tests/transactions.test.ts similarity index 100% rename from packages/e2e-tests/test-applications/nextjs-13-app-dir/tests/transactions.test.ts rename to packages/e2e-tests/test-applications/nextjs-app-dir/tests/transactions.test.ts diff --git a/packages/e2e-tests/test-applications/nextjs-13-app-dir/tsconfig.json b/packages/e2e-tests/test-applications/nextjs-app-dir/tsconfig.json similarity index 100% rename from packages/e2e-tests/test-applications/nextjs-13-app-dir/tsconfig.json rename to packages/e2e-tests/test-applications/nextjs-app-dir/tsconfig.json diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/yarn.lock b/packages/e2e-tests/test-applications/nextjs-app-dir/yarn.lock new file mode 100644 index 000000000000..af750e94199a --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/yarn.lock @@ -0,0 +1,804 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@next/env@13.2.1": + version "13.2.1" + resolved "https://registry.yarnpkg.com/@next/env/-/env-13.2.1.tgz#082d42cfc0c794e9185d7b4133d71440ba2e795d" + integrity sha512-Hq+6QZ6kgmloCg8Kgrix+4F0HtvLqVK3FZAnlAoS0eonaDemHe1Km4kwjSWRE3JNpJNcKxFHF+jsZrYo0SxWoQ== + +"@next/font@13.0.7": + version "13.0.7" + resolved "https://registry.yarnpkg.com/@next/font/-/font-13.0.7.tgz#e0046376edb0ce592d9cfddea8f4ab321eb1515a" + integrity sha512-39SzuoMI6jbrIzPs3KtXdKX03OrVp6Y7kRHcoVmOg69spiBzruPJ5x5DQSfN+OXqznbvVBNZBXnmdnSqs3qXiA== + +"@next/swc-android-arm-eabi@13.2.1": + version "13.2.1" + resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.2.1.tgz#67f2580fbbe05ee006220688972c5e3a555fc741" + integrity sha512-Yua7mUpEd1wzIT6Jjl3dpRizIfGp9NR4F2xeRuQv+ae+SDI1Em2WyM9m46UL+oeW5GpMiEHoaBagr47RScZFmQ== + +"@next/swc-android-arm64@13.2.1": + version "13.2.1" + resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-13.2.1.tgz#460a02b69eb23bb5f402266bcea9cadae59415c1" + integrity sha512-Bifcr2f6VwInOdq1uH/9lp8fH7Nf7XGkIx4XceVd32LPJqG2c6FZU8ZRBvTdhxzXVpt5TPtuXhOP4Ij9UPqsVw== + +"@next/swc-darwin-arm64@13.2.1": + version "13.2.1" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.2.1.tgz#8b8530ff417802027471aee2419f78a58a863ccb" + integrity sha512-gvqm+fGMYxAkwBapH0Vvng5yrb6HTkIvZfY4oEdwwYrwuLdkjqnJygCMgpNqIFmAHSXgtlWxfYv1VC8sjN81Kw== + +"@next/swc-darwin-x64@13.2.1": + version "13.2.1" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.2.1.tgz#80aebb3329a1e4568a28de1ee177780b3d50330c" + integrity sha512-HGqVqmaZWj6zomqOZUVbO5NhlABL0iIaxTmd0O5B0MoMa5zpDGoaHSG+fxgcWMXcGcxmUNchv1NfNOYiTKoHOg== + +"@next/swc-freebsd-x64@13.2.1": + version "13.2.1" + resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.2.1.tgz#250ea2ab7e1734f22d11c677c463fab9ac33a516" + integrity sha512-N/a4JarAq+E+g+9K2ywJUmDIgU2xs2nA+BBldH0oq4zYJMRiUhL0iaN9G4e72VmGOJ61L/3W6VN8RIUOwTLoqQ== + +"@next/swc-linux-arm-gnueabihf@13.2.1": + version "13.2.1" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.2.1.tgz#fe6bb29ed348a5f8ecae3740df22a8d8130c474a" + integrity sha512-WaFoerF/eRbhbE57TaIGJXbQAERADZ/RZ45u6qox9beb5xnWsyYgzX+WuN7Tkhyvga0/aMuVYFzS9CEay7D+bw== + +"@next/swc-linux-arm64-gnu@13.2.1": + version "13.2.1" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.2.1.tgz#4781b927fc5e421f3cea2b29e5d38e5e4837b198" + integrity sha512-R+Jhc1/RJTnncE9fkePboHDNOCm1WJ8daanWbjKhfPySMyeniKYRwGn5SLYW3S8YlRS0QVdZaaszDSZWgUcsmA== + +"@next/swc-linux-arm64-musl@13.2.1": + version "13.2.1" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.2.1.tgz#c2ba0a121b0255ba62450916bc70e6d0e26cbc98" + integrity sha512-oI1UfZPidGAVddlL2eOTmfsuKV9EaT1aktIzVIxIAgxzQSdwsV371gU3G55ggkurzfdlgF3GThFePDWF0d8dmw== + +"@next/swc-linux-x64-gnu@13.2.1": + version "13.2.1" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.2.1.tgz#573c220f8b087e5d131d1fba58d3e1a670b220ad" + integrity sha512-PCygPwrQmS+7WUuAWWioWMZCzZm4PG91lfRxToLDg7yIm/3YfAw5N2EK2TaM9pzlWdvHQAqRMX/oLvv027xUiA== + +"@next/swc-linux-x64-musl@13.2.1": + version "13.2.1" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.2.1.tgz#950b5bb920b322ca7b447efbd12a9c7a10c3a642" + integrity sha512-sUAKxo7CFZYGHNxheGh9nIBElLYBM6md/liEGfOTwh/xna4/GTTcmkGWkF7PdnvaYNgcPIQgHIMYiAa6yBKAVw== + +"@next/swc-win32-arm64-msvc@13.2.1": + version "13.2.1" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.2.1.tgz#dbff3c4f5a3812a7059dac05804148a0f98682db" + integrity sha512-qDmyEjDBpl/vBXxuOOKKWmPQOcARcZIMach1s7kjzaien0SySut/PHRlj56sosa81Wt4hTGhfhZ1R7g1n7+B8w== + +"@next/swc-win32-ia32-msvc@13.2.1": + version "13.2.1" + resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.2.1.tgz#7d2c17be7b8d9963984f5c15cc2588127101f620" + integrity sha512-2joqFQ81ZYPg6DcikIzQn3DgjKglNhPAozx6dL5sCNkr1CPMD0YIkJgT3CnYyMHQ04Qi3Npv0XX3MD6LJO8OCA== + +"@next/swc-win32-x64-msvc@13.2.1": + version "13.2.1" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.2.1.tgz#09713c6a925461f414e89422851326d1625bd4d2" + integrity sha512-r3+0fSaIZT6N237iMzwUhfNwjhAFvXjqB+4iuW+wcpxW+LHm1g/IoxN8eSRcb8jPItC86JxjAxpke0QL97qd6g== + +"@playwright/test@^1.27.1": + version "1.31.1" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.31.1.tgz#39d6873dc46af135f12451d79707db7d1357455d" + integrity sha512-IsytVZ+0QLDh1Hj83XatGp/GsI1CDJWbyDaBGbainsh0p2zC7F4toUocqowmjS6sQff2NGT3D9WbDj/3K2CJiA== + dependencies: + "@types/node" "*" + playwright-core "1.31.1" + optionalDependencies: + fsevents "2.3.2" + +"@rollup/plugin-commonjs@24.0.0": + version "24.0.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-24.0.0.tgz#fb7cf4a6029f07ec42b25daa535c75b05a43f75c" + integrity sha512-0w0wyykzdyRRPHOb0cQt14mIBLujfAv6GgP6g8nvg/iBxEm112t3YPPq+Buqe2+imvElTka+bjNlJ/gB56TD8g== + dependencies: + "@rollup/pluginutils" "^5.0.1" + commondir "^1.0.1" + estree-walker "^2.0.2" + glob "^8.0.3" + is-reference "1.2.1" + magic-string "^0.27.0" + +"@rollup/pluginutils@^5.0.1": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.2.tgz#012b8f53c71e4f6f9cb317e311df1404f56e7a33" + integrity sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA== + dependencies: + "@types/estree" "^1.0.0" + estree-walker "^2.0.2" + picomatch "^2.3.1" + +"@sentry/browser@7.39.0": + version "7.39.0" + resolved "http://localhost:4873/@sentry%2fbrowser/-/browser-7.39.0.tgz#e52669f0105257aeac799394df7b9a9bbb186449" + integrity sha512-LSa89bLDfGK33ArrgutVU8p4UDb809BgOn29qe/YPUL/Wor+cO59XoEmKVmXEqMZYEVjsaUVoBanUoxXKSlYgw== + dependencies: + "@sentry/core" "7.39.0" + "@sentry/replay" "7.39.0" + "@sentry/types" "7.39.0" + "@sentry/utils" "7.39.0" + tslib "^1.9.3" + +"@sentry/cli@^1.74.6": + version "1.75.0" + resolved "http://localhost:4873/@sentry%2fcli/-/cli-1.75.0.tgz#4a5e71b5619cd4e9e6238cc77857c66f6b38d86a" + integrity sha512-vT8NurHy00GcN8dNqur4CMIYvFH3PaKdkX3qllVvi4syybKqjwoz+aWRCvprbYv0knweneFkLt1SmBWqazUMfA== + dependencies: + https-proxy-agent "^5.0.0" + mkdirp "^0.5.5" + node-fetch "^2.6.7" + progress "^2.0.3" + proxy-from-env "^1.1.0" + which "^2.0.2" + +"@sentry/core@7.39.0": + version "7.39.0" + resolved "http://localhost:4873/@sentry%2fcore/-/core-7.39.0.tgz#501febb80832f7a5160b9c30883a7f985bd3fdd0" + integrity sha512-45WJIcWWCQnZ8zhHtcrkJjQ4YydmzMWY4pmRuBG7Qp+zrCT6ISoyODcjY+SCHFdvXkiYFi8+bFZa1qG3YQnnYw== + dependencies: + "@sentry/types" "7.39.0" + "@sentry/utils" "7.39.0" + tslib "^1.9.3" + +"@sentry/integrations@7.39.0": + version "7.39.0" + resolved "http://localhost:4873/@sentry%2fintegrations/-/integrations-7.39.0.tgz#532ccab5732e48602392f4b0cdbec24cf8f182ec" + integrity sha512-NJzPSAI8/YqlHj0ZbrIQrRRb4CE0IhH2UAmp96HbSqXyfiSBrGrEjPurgjKPjkYiWDpUiSolN5bhAxRG5xbe/w== + dependencies: + "@sentry/types" "7.39.0" + "@sentry/utils" "7.39.0" + localforage "^1.8.1" + tslib "^1.9.3" + +"@sentry/nextjs@*": + version "7.39.0" + resolved "http://localhost:4873/@sentry%2fnextjs/-/nextjs-7.39.0.tgz#7a79f8a9af93880b68ca2a63ed4dcbcf4f243b06" + integrity sha512-qeCM3hPJwMWhDYHzIPrTSF8s9ZRCjv4JueZCNVoH+vm2x678+7C1LjnCAg7sAKdzqnT8WnEh/6fqm/z6Bph42Q== + dependencies: + "@rollup/plugin-commonjs" "24.0.0" + "@sentry/core" "7.39.0" + "@sentry/integrations" "7.39.0" + "@sentry/node" "7.39.0" + "@sentry/react" "7.39.0" + "@sentry/tracing" "7.39.0" + "@sentry/types" "7.39.0" + "@sentry/utils" "7.39.0" + "@sentry/webpack-plugin" "1.20.0" + chalk "3.0.0" + rollup "2.78.0" + stacktrace-parser "^0.1.10" + tslib "^1.9.3" + +"@sentry/node@7.39.0": + version "7.39.0" + resolved "http://localhost:4873/@sentry%2fnode/-/node-7.39.0.tgz#feeceb2940b108879a1f3889d9fb4c31e3c9adb2" + integrity sha512-ORIW+sFhzAdYZ/3dVqVgpaEEHbjY16hJERTLihOo1AAb07D3PWO7s3bSNwQy/B6bmxjBAVq57WJDF9lA8UEjDQ== + dependencies: + "@sentry/core" "7.39.0" + "@sentry/types" "7.39.0" + "@sentry/utils" "7.39.0" + cookie "^0.4.1" + https-proxy-agent "^5.0.0" + lru_map "^0.3.3" + tslib "^1.9.3" + +"@sentry/react@7.39.0": + version "7.39.0" + resolved "http://localhost:4873/@sentry%2freact/-/react-7.39.0.tgz#73a0090035a48acc64d17385c9efc27463512905" + integrity sha512-1O5g3qTC0Zveswm7UmtVpbd1Tdjfv/0KEEhc53PfAUAJ6+4gr5Tw+fkFiyO/BMP2PT0u7FIOyMEZA8I/MgKODw== + dependencies: + "@sentry/browser" "7.39.0" + "@sentry/types" "7.39.0" + "@sentry/utils" "7.39.0" + hoist-non-react-statics "^3.3.2" + tslib "^1.9.3" + +"@sentry/replay@7.39.0": + version "7.39.0" + resolved "http://localhost:4873/@sentry%2freplay/-/replay-7.39.0.tgz#3ce2af873207c1229d79401c123d7be737bfbee2" + integrity sha512-+4JtWC6DHUo9VBGB87mDsvlW2aaToyxvKUbTgGLDgILoIcPDR4+vB3dp2BDkqy4h+0XM05RjXqVQDPiGe3BRRQ== + dependencies: + "@sentry/core" "7.39.0" + "@sentry/types" "7.39.0" + "@sentry/utils" "7.39.0" + +"@sentry/tracing@7.39.0": + version "7.39.0" + resolved "http://localhost:4873/@sentry%2ftracing/-/tracing-7.39.0.tgz#f871b10acdf6c77de54c828444199df6417d14a4" + integrity sha512-U0MduB0rOytBy8WAc4lteaDH3eqzf9XQ4pBUUCS4rT2XpqGpAv+kVxoLXxEaSVslqdc+daHDrP2DWvVoC/Omrg== + dependencies: + "@sentry/core" "7.39.0" + "@sentry/types" "7.39.0" + "@sentry/utils" "7.39.0" + tslib "^1.9.3" + +"@sentry/types@7.39.0": + version "7.39.0" + resolved "http://localhost:4873/@sentry%2ftypes/-/types-7.39.0.tgz#06c51d94ebb3446615f109352648d4b8c0b35ad0" + integrity sha512-5Y83Y8O3dT5zT2jTKEIPMcpn5lUm05KRMaCXuw0sRsv4r9TbBUKeqiSU1LjowT8rB/XNy8m7DHav8+NmogPaJw== + +"@sentry/utils@7.39.0": + version "7.39.0" + resolved "http://localhost:4873/@sentry%2futils/-/utils-7.39.0.tgz#0e28a5fab2f24cd532f08f01dbd3461f0a966c8a" + integrity sha512-k8P9uAd2kz2J6UGVMm0LNWXrj7cNYtnazrOuR82Pqwb3f/gSTOBHauIppxNXHsbiM8qrhwjGUfD3uA7+Nk58VA== + dependencies: + "@sentry/types" "7.39.0" + tslib "^1.9.3" + +"@sentry/webpack-plugin@1.20.0": + version "1.20.0" + resolved "http://localhost:4873/@sentry%2fwebpack-plugin/-/webpack-plugin-1.20.0.tgz#e7add76122708fb6b4ee7951294b521019720e58" + integrity sha512-Ssj1mJVFsfU6vMCOM2d+h+KQR7QHSfeIP16t4l20Uq/neqWXZUQ2yvQfe4S3BjdbJXz/X4Rw8Hfy1Sd0ocunYw== + dependencies: + "@sentry/cli" "^1.74.6" + webpack-sources "^2.0.0 || ^3.0.0" + +"@swc/helpers@0.4.14": + version "0.4.14" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.14.tgz#1352ac6d95e3617ccb7c1498ff019654f1e12a74" + integrity sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw== + dependencies: + tslib "^2.4.0" + +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" + integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== + +"@types/estree@*", "@types/estree@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== + +"@types/node@*": + version "18.14.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.14.1.tgz#90dad8476f1e42797c49d6f8b69aaf9f876fc69f" + integrity sha512-QH+37Qds3E0eDlReeboBxfHbX9omAcBCXEzswCu6jySP642jiM3cYSIkU/REqwhCUqXdonHFuBfJDiAJxMNhaQ== + +"@types/node@18.11.17": + version "18.11.17" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.17.tgz#5c009e1d9c38f4a2a9d45c0b0c493fe6cdb4bcb5" + integrity sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng== + +"@types/prop-types@*": + version "15.7.5" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" + integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== + +"@types/react-dom@18.0.9": + version "18.0.9" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.9.tgz#ffee5e4bfc2a2f8774b15496474f8e7fe8d0b504" + integrity sha512-qnVvHxASt/H7i+XG1U1xMiY5t+IHcPGUK7TDMDzom08xa7e86eCeKOiLZezwCKVxJn6NEiiy2ekgX8aQssjIKg== + dependencies: + "@types/react" "*" + +"@types/react@*": + version "18.0.28" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.28.tgz#accaeb8b86f4908057ad629a26635fe641480065" + integrity sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +"@types/react@18.0.26": + version "18.0.26" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.26.tgz#8ad59fc01fef8eaf5c74f4ea392621749f0b7917" + integrity sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +"@types/scheduler@*": + version "0.16.2" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" + integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.4.1: + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +caniuse-lite@^1.0.30001406: + version "1.0.30001457" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001457.tgz#6af34bb5d720074e2099432aa522c21555a18301" + integrity sha512-SDIV6bgE1aVbK6XyxdURbUE89zY7+k1BBBaOwYwkNCglXlel/E7mELiHC64HQ+W0xSKlqWhV9Wh7iHxUjMs4fA== + +chalk@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +client-only@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" + integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + +cookie@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +csstype@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" + integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== + +debug@4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@2.3.2, fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +glob@^8.0.3: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +immediate@~3.0.5: + version "3.0.6" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" + integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-reference@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" + integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== + dependencies: + "@types/estree" "*" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +lie@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e" + integrity sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw== + dependencies: + immediate "~3.0.5" + +localforage@^1.8.1: + version "1.10.0" + resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.10.0.tgz#5c465dc5f62b2807c3a84c0c6a1b1b3212781dd4" + integrity sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg== + dependencies: + lie "3.1.1" + +loose-envify@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lru_map@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" + integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== + +magic-string@^0.27.0: + version "0.27.0" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.27.0.tgz#e4a3413b4bab6d98d2becffd48b4a257effdbbf3" + integrity sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.13" + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +mkdirp@^0.5.5: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +nanoid@^3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" + integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== + +next@13.2.1: + version "13.2.1" + resolved "https://registry.yarnpkg.com/next/-/next-13.2.1.tgz#34d823f518632b36379863228ed9f861c335b9c0" + integrity sha512-qhgJlDtG0xidNViJUPeQHLGJJoT4zDj/El7fP3D3OzpxJDUfxsm16cK4WTMyvSX1ciIfAq05u+0HqFAa+VJ+Hg== + dependencies: + "@next/env" "13.2.1" + "@swc/helpers" "0.4.14" + caniuse-lite "^1.0.30001406" + postcss "8.4.14" + styled-jsx "5.1.1" + optionalDependencies: + "@next/swc-android-arm-eabi" "13.2.1" + "@next/swc-android-arm64" "13.2.1" + "@next/swc-darwin-arm64" "13.2.1" + "@next/swc-darwin-x64" "13.2.1" + "@next/swc-freebsd-x64" "13.2.1" + "@next/swc-linux-arm-gnueabihf" "13.2.1" + "@next/swc-linux-arm64-gnu" "13.2.1" + "@next/swc-linux-arm64-musl" "13.2.1" + "@next/swc-linux-x64-gnu" "13.2.1" + "@next/swc-linux-x64-musl" "13.2.1" + "@next/swc-win32-arm64-msvc" "13.2.1" + "@next/swc-win32-ia32-msvc" "13.2.1" + "@next/swc-win32-x64-msvc" "13.2.1" + +node-fetch@^2.6.7: + version "2.6.9" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" + integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== + dependencies: + whatwg-url "^5.0.0" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +playwright-core@1.31.1: + version "1.31.1" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.31.1.tgz#4deeebbb8fb73b512593fe24bea206d8fd85ff7f" + integrity sha512-JTyX4kV3/LXsvpHkLzL2I36aCdml4zeE35x+G5aPc4bkLsiRiQshU5lWeVpHFAuC8xAcbI6FDcw/8z3q2xtJSQ== + +postcss@8.4.14: + version "8.4.14" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf" + integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig== + dependencies: + nanoid "^3.3.4" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +progress@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +react-dom@18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" + integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== + dependencies: + loose-envify "^1.1.0" + scheduler "^0.23.0" + +react-is@^16.7.0: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react@18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" + integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== + dependencies: + loose-envify "^1.1.0" + +rollup@2.78.0: + version "2.78.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.78.0.tgz#00995deae70c0f712ea79ad904d5f6b033209d9e" + integrity sha512-4+YfbQC9QEVvKTanHhIAFVUFSRsezvQF8vFOJwtGfb9Bb+r014S+qryr9PSmw8x6sMnPkmFBGAvIFVQxvJxjtg== + optionalDependencies: + fsevents "~2.3.2" + +scheduler@^0.23.0: + version "0.23.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" + integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== + dependencies: + loose-envify "^1.1.0" + +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +stacktrace-parser@^0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" + integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== + dependencies: + type-fest "^0.7.1" + +styled-jsx@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f" + integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw== + dependencies: + client-only "0.0.1" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +ts-node@10.9.1: + version "10.9.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.4.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" + integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== + +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + +typescript@4.9.4: + version "4.9.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.4.tgz#a2a3d2756c079abda241d75f149df9d561091e78" + integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +"webpack-sources@^2.0.0 || ^3.0.0": + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== From e996bc8705200c196f68355818f4e3c122ed9fbd Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Fri, 3 Mar 2023 15:53:16 +0000 Subject: [PATCH 04/44] . --- .../{render-error => }/error.tsx | 2 +- .../{render-error => }/layout.tsx | 4 ++-- .../{render-error => }/loading.tsx | 2 +- .../{render-error => }/not-found.tsx | 2 +- .../client-component/{render-error => }/page.tsx | 6 ++++-- .../parameter/[...parameters]/layout.tsx | 2 ++ .../parameter/[...parameters]/loading.tsx | 2 +- .../parameter/[...parameters]/page.tsx | 9 ++++++--- .../parameter/[parameter]/layout.tsx | 2 ++ .../parameter/[parameter]/page.tsx | 7 ++++++- .../nextjs-app-dir/app/layout.tsx | 16 +++++++++++----- .../app/server-component/error.tsx | 11 +++++++++++ .../app/server-component/layout.tsx | 8 ++++++++ .../app/server-component/loading.tsx | 7 +++++++ .../app/server-component/not-found.tsx | 7 +++++++ .../nextjs-app-dir/app/server-component/page.tsx | 12 ++++++++++++ .../parameter/[...parameters]/error.tsx | 11 +++++++++++ .../parameter/[...parameters]/layout.tsx | 8 ++++++++ .../parameter/[...parameters]/loading.tsx | 7 +++++++ .../parameter/[...parameters]/not-found.tsx | 7 +++++++ .../parameter/[...parameters]/page.tsx | 13 +++++++++++++ .../parameter/[parameter]/error.tsx | 11 +++++++++++ .../parameter/[parameter]/layout.tsx | 8 ++++++++ .../parameter/[parameter]/loading.tsx | 7 +++++++ .../parameter/[parameter]/not-found.tsx | 7 +++++++ .../parameter/[parameter]/page.tsx | 13 +++++++++++++ .../components/client-error-debug-tools.tsx | 13 +++++++++++++ .../components/transaction-context.tsx | 6 ++++-- .../tests/devErrorSymbolification.test.ts | 6 +++--- 29 files changed, 194 insertions(+), 22 deletions(-) rename packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/{render-error => }/error.tsx (84%) rename packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/{render-error => }/layout.tsx (69%) rename packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/{render-error => }/loading.tsx (70%) rename packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/{render-error => }/not-found.tsx (69%) rename packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/{render-error => }/page.tsx (54%) create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/error.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/layout.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/loading.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/not-found.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/page.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/error.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/layout.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/loading.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/not-found.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/page.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/error.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/layout.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/loading.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/not-found.tsx create mode 100644 packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/page.tsx diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/error.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/error.tsx similarity index 84% rename from packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/error.tsx rename to packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/error.tsx index 765178323209..c1e3874f7ea8 100644 --- a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/error.tsx +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/error.tsx @@ -3,7 +3,7 @@ export default function Error({ error, reset }: { error: Error; reset: () => void }) { return (
-

Error (/client-component/render-error)

+

Error (/client-component)

Error: {error.toString()}
diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/layout.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/layout.tsx similarity index 69% rename from packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/layout.tsx rename to packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/layout.tsx index ab443e2db74d..7b447d23cbf8 100644 --- a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/layout.tsx +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/layout.tsx @@ -1,9 +1,9 @@ -import Link from 'next/link'; +'use client'; export default function Layout({ children }: { children: React.ReactNode }) { return (
-

Layout (/client-component/render-error)

+

Layout (/client-component)

{children}
); diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/loading.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/loading.tsx similarity index 70% rename from packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/loading.tsx rename to packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/loading.tsx index 1cb3e68a4206..9b6cf994d322 100644 --- a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/loading.tsx +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/loading.tsx @@ -1,7 +1,7 @@ export default function Loading() { return (
-

Loading (/client-component/render-error)

+

Loading (/client-component)

); } diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/not-found.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/not-found.tsx similarity index 69% rename from packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/not-found.tsx rename to packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/not-found.tsx index 235740492e05..deef8f3078b4 100644 --- a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/not-found.tsx +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/not-found.tsx @@ -1,7 +1,7 @@ export default function NotFound() { return (
-

Not found (/client-component/render-error)

; +

Not found (/client-component)

;
); } diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/page.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/page.tsx similarity index 54% rename from packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/page.tsx rename to packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/page.tsx index ec06b578f60a..64012f948278 100644 --- a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/render-error/page.tsx +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/page.tsx @@ -1,9 +1,11 @@ -import { ClientErrorDebugTools } from '../../../components/client-error-debug-tools'; +'use client'; + +import { ClientErrorDebugTools } from '../../components/client-error-debug-tools'; export default function Page() { return (
-

Page (/client-component/render-error)

+

Page (/client-component)

); diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/layout.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/layout.tsx index 9150d773cf7f..a387722a8fcf 100644 --- a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/layout.tsx +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/layout.tsx @@ -1,3 +1,5 @@ +'use client'; + export default function Layout({ children }: { children: React.ReactNode }) { return (
diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/loading.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/loading.tsx index 1c89093040e8..27a8d577240e 100644 --- a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/loading.tsx +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/loading.tsx @@ -1,7 +1,7 @@ export default function Loading() { return (
-

Loading (/)

+

Loading (/client-component/parameter/[...parameters])

); } diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/page.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/page.tsx index 2079f995761f..31fa4ee21be5 100644 --- a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/page.tsx +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/page.tsx @@ -1,12 +1,15 @@ -'use client'; - import { ClientErrorDebugTools } from '../../../../components/client-error-debug-tools'; -export default function Page() { +export default function Page({ params }: { params: Record }) { return (

Page (/client-component/[...parameters])

+

Params: {JSON.stringify(params['parameters'])}

); } + +export async function generateStaticParams() { + return [{ parameters: ['foo', 'bar', 'baz'] }]; +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/layout.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/layout.tsx index f2ffd2306d06..0d13dbc6bcac 100644 --- a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/layout.tsx +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/layout.tsx @@ -1,3 +1,5 @@ +'use client'; + export default function Layout({ children }: { children: React.ReactNode }) { return (
diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/page.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/page.tsx index 59bcc6fb5653..2b9c28b922ac 100644 --- a/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/page.tsx +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/page.tsx @@ -1,10 +1,15 @@ import { ClientErrorDebugTools } from '../../../../components/client-error-debug-tools'; -export default function Page() { +export default function Page({ params }: { params: Record }) { return (

Page (/client-component/[parameter])

+

Parameter: {JSON.stringify(params['parameter'])}

); } + +export async function generateStaticParams() { + return [{ parameter: '42' }]; +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/layout.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/layout.tsx index 361eb304f2d0..35c4704735e7 100644 --- a/packages/e2e-tests/test-applications/nextjs-app-dir/app/layout.tsx +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/layout.tsx @@ -9,19 +9,25 @@ export default function Layout({ children }: { children: React.ReactNode }) {

Layout (/)

  • - /client-component/parameter/foo/bar/baz + / +
  • +
  • + /client-component
  • - /client-component/parameter/1/2 + /client-component/parameter/42 +
  • +
  • + /client-component/parameter/foo/bar/baz
  • - /client-component/parameter/1/2 + /server-component
  • - /client-component/parameter/1/2 + /server-component/parameter/42
  • - /client-component/parameter/1/2 + /server-component/parameter/foo/bar/baz
{children} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/error.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/error.tsx new file mode 100644 index 000000000000..8c728017a4c9 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/error.tsx @@ -0,0 +1,11 @@ +'use client'; + +export default function Error({ error, reset }: { error: Error; reset: () => void }) { + return ( +
+

Error (/server-component)

+ + Error: {error.toString()} +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/layout.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/layout.tsx new file mode 100644 index 000000000000..3e6a95d2bc49 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/layout.tsx @@ -0,0 +1,8 @@ +export default async function Layout({ children }: { children: React.ReactNode }) { + return ( +
+

Layout (/server-component)

+ {children} +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/loading.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/loading.tsx new file mode 100644 index 000000000000..70deffd9dea6 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/loading.tsx @@ -0,0 +1,7 @@ +export default async function Loading() { + return ( +
+

Loading (/server-component)

+
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/not-found.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/not-found.tsx new file mode 100644 index 000000000000..57b040b4210d --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/not-found.tsx @@ -0,0 +1,7 @@ +export default function NotFound() { + return ( +
+

Not found (/server-component)

; +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/page.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/page.tsx new file mode 100644 index 000000000000..d318ee23968d --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/page.tsx @@ -0,0 +1,12 @@ +import { ClientErrorDebugTools } from '../../components/client-error-debug-tools'; + +export const dynamic = 'force-dynamic'; + +export default function Page() { + return ( +
+

Page (/server-component)

+ +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/error.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/error.tsx new file mode 100644 index 000000000000..44c78430b2aa --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/error.tsx @@ -0,0 +1,11 @@ +'use client'; + +export default function Error({ error, reset }: { error: Error; reset: () => void }) { + return ( +
+

Error (/server-component/[...parameters])

+ + Error: {error.toString()} +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/layout.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/layout.tsx new file mode 100644 index 000000000000..b34d5a11488f --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/layout.tsx @@ -0,0 +1,8 @@ +export default async function Layout({ children }: { children: React.ReactNode }) { + return ( +
+

Layout (/server-component/[...parameters])

+ {children} +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/loading.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/loading.tsx new file mode 100644 index 000000000000..f0fa262fa780 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/loading.tsx @@ -0,0 +1,7 @@ +export default async function Loading() { + return ( +
+

Loading (/server-component/[...parameters])

+
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/not-found.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/not-found.tsx new file mode 100644 index 000000000000..30da42c88a17 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/not-found.tsx @@ -0,0 +1,7 @@ +export default function NotFound() { + return ( +
+

Not found (/server-component/[...parameters])

; +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/page.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/page.tsx new file mode 100644 index 000000000000..5d9d6c8262c5 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/page.tsx @@ -0,0 +1,13 @@ +import { ClientErrorDebugTools } from '../../../../components/client-error-debug-tools'; + +export const dynamic = 'force-dynamic'; + +export default async function Page({ params }: { params: Record }) { + return ( +
+

Page (/server-component/[...parameters])

+

Params: {JSON.stringify(params['parameters'])}

+ +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/error.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/error.tsx new file mode 100644 index 000000000000..37ba7515505f --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/error.tsx @@ -0,0 +1,11 @@ +'use client'; + +export default function Error({ error, reset }: { error: Error; reset: () => void }) { + return ( +
+

Error (/server-component/[parameter])

+ + Error: {error.toString()} +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/layout.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/layout.tsx new file mode 100644 index 000000000000..013b62f15ff5 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/layout.tsx @@ -0,0 +1,8 @@ +export default async function Layout({ children }: { children: React.ReactNode }) { + return ( +
+

Layout (/server-component/[parameter])

+ {children} +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/loading.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/loading.tsx new file mode 100644 index 000000000000..6fb1e6e9d479 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/loading.tsx @@ -0,0 +1,7 @@ +export default async function Loading() { + return ( +
+

Loading (/server-component/[parameter])

+
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/not-found.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/not-found.tsx new file mode 100644 index 000000000000..9150cdeca2ad --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/not-found.tsx @@ -0,0 +1,7 @@ +export default function NotFound() { + return ( +
+

Not found (/server-component/[parameter])

; +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/page.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/page.tsx new file mode 100644 index 000000000000..f88fe1cd4a06 --- /dev/null +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/page.tsx @@ -0,0 +1,13 @@ +import { ClientErrorDebugTools } from '../../../../components/client-error-debug-tools'; + +export const dynamic = 'force-dynamic'; + +export default async function Page({ params }: { params: Record }) { + return ( +
+

Page (/server-component/[parameter])

+

Parameter: {JSON.stringify(params['parameter'])}

+ +
+ ); +} diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/components/client-error-debug-tools.tsx b/packages/e2e-tests/test-applications/nextjs-app-dir/components/client-error-debug-tools.tsx index 8c1a744f211e..4e7572a3fb3f 100644 --- a/packages/e2e-tests/test-applications/nextjs-app-dir/components/client-error-debug-tools.tsx +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/components/client-error-debug-tools.tsx @@ -10,6 +10,11 @@ export function ClientErrorDebugTools() { const [isFetchingAPIRoute, setIsFetchingAPIRoute] = useState(); const [isFetchingEdgeAPIRoute, setIsFetchingEdgeAPIRoute] = useState(); const [isFetchingExternalAPIRoute, setIsFetchingExternalAPIRoute] = useState(); + const [renderError, setRenderError] = useState(); + + if (renderError) { + throw new Error('Render Error'); + } return (
@@ -38,6 +43,14 @@ export function ClientErrorDebugTools() { Throw promise rejection
+ +

+ {transactionContextValue.transactionActive ? ( + + ) : ( + <> + { + setTransactionName(e.target.value); + }} + /> + + + )}

+ + + diff --git a/packages/integration-tests/suites/replay/sessionExpiry/test.ts b/packages/integration-tests/suites/replay/sessionExpiry/test.ts new file mode 100644 index 000000000000..38927478dea6 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionExpiry/test.ts @@ -0,0 +1,98 @@ +import { expect } from '@playwright/test'; + +import { sentryTest } from '../../../utils/fixtures'; +import { getExpectedReplayEvent } from '../../../utils/replayEventTemplates'; +import { + getFullRecordingSnapshots, + getIncrementalRecordingSnapshots, + getReplayEvent, + getReplaySnapshot, + normalize, + shouldSkipReplayTest, + waitForReplayRequest, +} from '../../../utils/replayHelpers'; + +// Session should expire after 2s - keep in sync with init.js +const SESSION_TIMEOUT = 2000; + +sentryTest('handles an expired session RUN', async ({ getLocalTestPath, page }) => { + if (shouldSkipReplayTest()) { + sentryTest.skip(); + } + + const reqPromise0 = waitForReplayRequest(page, 0); + const reqPromise1 = waitForReplayRequest(page, 1); + + await page.route('https://dsn.ingest.sentry.io/**/*', route => { + return route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ id: 'test-id' }), + }); + }); + + const url = await getLocalTestPath({ testDir: __dirname }); + + await page.goto(url); + const req0 = await reqPromise0; + + const replayEvent0 = getReplayEvent(req0); + expect(replayEvent0).toEqual(getExpectedReplayEvent({})); + + const fullSnapshots0 = getFullRecordingSnapshots(req0); + expect(fullSnapshots0.length).toEqual(1); + const stringifiedSnapshot = normalize(fullSnapshots0[0]); + expect(stringifiedSnapshot).toMatchSnapshot('snapshot-0.json'); + + // We wait for another segment 0 + const reqPromise2 = waitForReplayRequest(page, 0); + + await page.click('#button1'); + const req1 = await reqPromise1; + + const replayEvent1 = getReplayEvent(req1); + expect(replayEvent1).toEqual(getExpectedReplayEvent({ replay_start_timestamp: undefined, segment_id: 1, urls: [] })); + + const fullSnapshots1 = getFullRecordingSnapshots(req1); + expect(fullSnapshots1.length).toEqual(0); + + const incrementalSnapshots1 = getIncrementalRecordingSnapshots(req1); + // The number of incremental snapshots depends on the browser + expect(incrementalSnapshots1.length).toBeGreaterThanOrEqual(4); + + expect(incrementalSnapshots1).toEqual( + expect.arrayContaining([ + { + source: 1, + positions: [ + { + id: 9, + timeOffset: expect.any(Number), + x: expect.any(Number), + y: expect.any(Number), + }, + ], + }, + ]), + ); + + const replay = await getReplaySnapshot(page); + const oldSessionId = replay.session?.id; + + await new Promise(resolve => setTimeout(resolve, SESSION_TIMEOUT)); + + await page.click('#button2'); + const req2 = await reqPromise2; + + const replay2 = await getReplaySnapshot(page); + + expect(replay2.session?.id).not.toEqual(oldSessionId); + + const replayEvent2 = getReplayEvent(req2); + expect(replayEvent2).toEqual(getExpectedReplayEvent({})); + + const fullSnapshots2 = getFullRecordingSnapshots(req2); + expect(fullSnapshots2.length).toEqual(1); + const stringifiedSnapshot2 = normalize(fullSnapshots2[0]); + expect(stringifiedSnapshot2).toMatchSnapshot('snapshot-2.json'); +}); diff --git a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-chromium.json b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-chromium.json new file mode 100644 index 000000000000..a4ad4ac4d60a --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-chromium.json @@ -0,0 +1,109 @@ +{ + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-firefox.json b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-firefox.json new file mode 100644 index 000000000000..a4ad4ac4d60a --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-firefox.json @@ -0,0 +1,109 @@ +{ + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-webkit.json b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-webkit.json new file mode 100644 index 000000000000..a4ad4ac4d60a --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-webkit.json @@ -0,0 +1,109 @@ +{ + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0.json b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0.json new file mode 100644 index 000000000000..a4ad4ac4d60a --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0.json @@ -0,0 +1,109 @@ +{ + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-chromium.json b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-chromium.json new file mode 100644 index 000000000000..a4ad4ac4d60a --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-chromium.json @@ -0,0 +1,109 @@ +{ + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-firefox.json b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-firefox.json new file mode 100644 index 000000000000..a4ad4ac4d60a --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-firefox.json @@ -0,0 +1,109 @@ +{ + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-webkit.json b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-webkit.json new file mode 100644 index 000000000000..a4ad4ac4d60a --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-webkit.json @@ -0,0 +1,109 @@ +{ + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2.json b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2.json new file mode 100644 index 000000000000..a4ad4ac4d60a --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2.json @@ -0,0 +1,109 @@ +{ + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionInactive/init.js b/packages/integration-tests/suites/replay/sessionInactive/init.js new file mode 100644 index 000000000000..f1b0345e71d7 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionInactive/init.js @@ -0,0 +1,22 @@ +import * as Sentry from '@sentry/browser'; + +window.Sentry = Sentry; +window.Replay = new Sentry.Replay({ + flushMinDelay: 500, + flushMaxDelay: 500, +}); + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + sampleRate: 0, + replaysSessionSampleRate: 1.0, + replaysOnErrorSampleRate: 0.0, + debug: true, + + integrations: [window.Replay], +}); + +window.Replay._replay.timeouts = { + sessionIdle: 300000, // default: 5min + maxSessionLife: 2000, // this is usually 60min, but we want to test this with shorter times +}; diff --git a/packages/integration-tests/suites/replay/sessionInactive/template.html b/packages/integration-tests/suites/replay/sessionInactive/template.html new file mode 100644 index 000000000000..7223a20f82ba --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionInactive/template.html @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/packages/integration-tests/suites/replay/sessionInactive/test.ts b/packages/integration-tests/suites/replay/sessionInactive/test.ts new file mode 100644 index 000000000000..e4a1e6d8b243 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionInactive/test.ts @@ -0,0 +1,88 @@ +import { expect } from '@playwright/test'; + +import { sentryTest } from '../../../utils/fixtures'; +import { getExpectedReplayEvent } from '../../../utils/replayEventTemplates'; +import { + getFullRecordingSnapshots, + getReplayEvent, + getReplaySnapshot, + normalize, + shouldSkipReplayTest, + waitForReplayRequest, +} from '../../../utils/replayHelpers'; + +// Session should expire after 2s - keep in sync with init.js +const SESSION_TIMEOUT = 2000; + +sentryTest('handles an inactive session', async ({ getLocalTestPath, page }) => { + if (shouldSkipReplayTest()) { + sentryTest.skip(); + } + + const reqPromise0 = waitForReplayRequest(page, 0); + + await page.route('https://dsn.ingest.sentry.io/**/*', route => { + return route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ id: 'test-id' }), + }); + }); + + const url = await getLocalTestPath({ testDir: __dirname }); + + await page.goto(url); + const req0 = await reqPromise0; + + const replayEvent0 = getReplayEvent(req0); + expect(replayEvent0).toEqual(getExpectedReplayEvent({})); + + const fullSnapshots0 = getFullRecordingSnapshots(req0); + expect(fullSnapshots0.length).toEqual(1); + const stringifiedSnapshot = normalize(fullSnapshots0[0]); + expect(stringifiedSnapshot).toMatchSnapshot('snapshot-0.json'); + + await page.click('#button1'); + + // We wait for another segment 0 + const reqPromise1 = waitForReplayRequest(page, 0); + + // Now we wait for the session timeout, nothing should be sent in the meanwhile + await new Promise(resolve => setTimeout(resolve, SESSION_TIMEOUT)); + + // nothing happened because no activity/inactivity was detected + const replay = await getReplaySnapshot(page); + // @ts-ignore private api + expect(replay._isEnabled).toEqual(true); + // @ts-ignore private api + expect(replay._isPaused).toEqual(false); + + // Now we trigger a blur event, which should move the session to paused mode + await page.evaluate(() => { + window.dispatchEvent(new Event('blur')); + }); + + const replay2 = await getReplaySnapshot(page); + // @ts-ignore private api + expect(replay2._isEnabled).toEqual(true); + // @ts-ignore private api + expect(replay2._isPaused).toEqual(true); + + // Trigger an action, should re-start the recording + await page.click('#button2'); + const req1 = await reqPromise1; + + const replay3 = await getReplaySnapshot(page); + // @ts-ignore private api + expect(replay3._isEnabled).toEqual(true); + // @ts-ignore private api + expect(replay3._isPaused).toEqual(false); + + const replayEvent1 = getReplayEvent(req1); + expect(replayEvent1).toEqual(getExpectedReplayEvent({})); + + const fullSnapshots1 = getFullRecordingSnapshots(req1); + expect(fullSnapshots1.length).toEqual(1); + const stringifiedSnapshot1 = normalize(fullSnapshots1[0]); + expect(stringifiedSnapshot1).toMatchSnapshot('snapshot-1.json'); +}); diff --git a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-chromium.json b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-chromium.json new file mode 100644 index 000000000000..a4ad4ac4d60a --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-chromium.json @@ -0,0 +1,109 @@ +{ + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-firefox.json b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-firefox.json new file mode 100644 index 000000000000..a4ad4ac4d60a --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-firefox.json @@ -0,0 +1,109 @@ +{ + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-webkit.json b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-webkit.json new file mode 100644 index 000000000000..a4ad4ac4d60a --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-webkit.json @@ -0,0 +1,109 @@ +{ + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0.json b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0.json new file mode 100644 index 000000000000..a4ad4ac4d60a --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0.json @@ -0,0 +1,109 @@ +{ + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-chromium.json b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-chromium.json new file mode 100644 index 000000000000..a4ad4ac4d60a --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-chromium.json @@ -0,0 +1,109 @@ +{ + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-firefox.json b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-firefox.json new file mode 100644 index 000000000000..a4ad4ac4d60a --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-firefox.json @@ -0,0 +1,109 @@ +{ + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-webkit.json b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-webkit.json new file mode 100644 index 000000000000..a4ad4ac4d60a --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-webkit.json @@ -0,0 +1,109 @@ +{ + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1.json b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1.json new file mode 100644 index 000000000000..a4ad4ac4d60a --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1.json @@ -0,0 +1,109 @@ +{ + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ No newline at end of file diff --git a/packages/integration-tests/utils/replayHelpers.ts b/packages/integration-tests/utils/replayHelpers.ts index 236431a75ee6..b68e74708916 100644 --- a/packages/integration-tests/utils/replayHelpers.ts +++ b/packages/integration-tests/utils/replayHelpers.ts @@ -138,7 +138,7 @@ export function getFullRecordingSnapshots(resOrReq: Request | Response): Recordi return events.filter(event => event.type === 2).map(event => event.data as RecordingSnapshot); } -function getIncrementalRecordingSnapshots(resOrReq: Request | Response): RecordingSnapshot[] { +export function getIncrementalRecordingSnapshots(resOrReq: Request | Response): RecordingSnapshot[] { const replayRequest = getRequest(resOrReq); const events = getDecompressedRecordingEvents(replayRequest) as RecordingEvent[]; return events.filter(event => event.type === 3).map(event => event.data as RecordingSnapshot); diff --git a/packages/replay/package.json b/packages/replay/package.json index dc607ff7b0f1..c1a783a0e763 100644 --- a/packages/replay/package.json +++ b/packages/replay/package.json @@ -25,7 +25,7 @@ "fix:prettier": "prettier --write \"{src,test,scripts}/**/*.ts\"", "lint": "run-s lint:prettier lint:eslint", "lint:eslint": "eslint . --format stylish", - "lint:prettier": "prettier --check \"{src,test,scripts,worker}/**/*.ts\"", + "lint:prettier": "prettier --check \"{src,test,scripts}/**/*.ts\"", "test": "jest", "test:watch": "jest --watch", "bootstrap:demo": "cd demo && yarn", diff --git a/packages/replay/src/replay.ts b/packages/replay/src/replay.ts index 505d53410d1f..544052172017 100644 --- a/packages/replay/src/replay.ts +++ b/packages/replay/src/replay.ts @@ -21,6 +21,7 @@ import type { ReplayContainer as ReplayContainerInterface, ReplayPluginOptions, Session, + Timeouts, } from './types'; import { addEvent } from './util/addEvent'; import { addGlobalListeners } from './util/addGlobalListeners'; @@ -54,6 +55,15 @@ export class ReplayContainer implements ReplayContainerInterface { */ public recordingMode: ReplayRecordingMode = 'session'; + /** + * These are here so we can overwrite them in tests etc. + * @hidden + */ + public readonly timeouts: Timeouts = { + sessionIdle: SESSION_IDLE_DURATION, + maxSessionLife: MAX_SESSION_LIFE, + } as const; + /** * Options to pass to `rrweb.record()` */ @@ -368,7 +378,7 @@ export class ReplayContainer implements ReplayContainerInterface { // MAX_SESSION_LIFE. Otherwise non-user activity can trigger a new // session+recording. This creates noisy replays that do not have much // content in them. - if (this._lastActivity && isExpired(this._lastActivity, MAX_SESSION_LIFE)) { + if (this._lastActivity && isExpired(this._lastActivity, this.timeouts.maxSessionLife)) { // Pause recording this.pause(); return; @@ -408,7 +418,7 @@ export class ReplayContainer implements ReplayContainerInterface { */ private _loadAndCheckSession(): boolean { const { type, session } = getSession({ - expiry: SESSION_IDLE_DURATION, + timeouts: this.timeouts, stickySession: Boolean(this._options.stickySession), currentSession: this.session, sessionSampleRate: this._options.sessionSampleRate, @@ -517,7 +527,7 @@ export class ReplayContainer implements ReplayContainerInterface { ) => { // If this is false, it means session is expired, create and a new session and wait for checkout if (!this.checkAndHandleExpiredSession()) { - __DEBUG_BUILD__ && logger.error('[Replay] Received replay event after session expired.'); + __DEBUG_BUILD__ && logger.warn('[Replay] Received replay event after session expired.'); return; } @@ -620,7 +630,7 @@ export class ReplayContainer implements ReplayContainerInterface { return; } - const expired = isSessionExpired(this.session, SESSION_IDLE_DURATION); + const expired = isSessionExpired(this.session, this.timeouts); if (breadcrumb && !expired) { this._createCustomBreadcrumb(breadcrumb); diff --git a/packages/replay/src/session/getSession.ts b/packages/replay/src/session/getSession.ts index 54b16d9a5414..150fbe12c871 100644 --- a/packages/replay/src/session/getSession.ts +++ b/packages/replay/src/session/getSession.ts @@ -1,16 +1,13 @@ import { logger } from '@sentry/utils'; -import type { Session, SessionOptions } from '../types'; +import type { Session, SessionOptions, Timeouts } from '../types'; import { isSessionExpired } from '../util/isSessionExpired'; import { createSession } from './createSession'; import { fetchSession } from './fetchSession'; import { makeSession } from './Session'; interface GetSessionParams extends SessionOptions { - /** - * The length of time (in ms) which we will consider the session to be expired. - */ - expiry: number; + timeouts: Timeouts; /** * The current session (e.g. if stickySession is off) @@ -22,7 +19,7 @@ interface GetSessionParams extends SessionOptions { * Get or create a session */ export function getSession({ - expiry, + timeouts, currentSession, stickySession, sessionSampleRate, @@ -35,7 +32,7 @@ export function getSession({ // If there is a session, check if it is valid (e.g. "last activity" time // should be within the "session idle time", and "session started" time is // within "max session time"). - const isExpired = isSessionExpired(session, expiry); + const isExpired = isSessionExpired(session, timeouts); if (!isExpired) { return { type: 'saved', session }; diff --git a/packages/replay/src/types.ts b/packages/replay/src/types.ts index 174f1da240f8..b91e8be36129 100644 --- a/packages/replay/src/types.ts +++ b/packages/replay/src/types.ts @@ -18,6 +18,11 @@ export interface SendReplayData { options: ReplayPluginOptions; } +export interface Timeouts { + sessionIdle: number; + maxSessionLife: number; +} + /** * The request payload to worker */ @@ -289,6 +294,10 @@ export interface ReplayContainer { performanceEvents: AllPerformanceEntry[]; session: Session | undefined; recordingMode: ReplayRecordingMode; + timeouts: { + sessionIdle: number; + maxSessionLife: number; + }; isEnabled(): boolean; isPaused(): boolean; getContext(): InternalEventContext; diff --git a/packages/replay/src/util/addEvent.ts b/packages/replay/src/util/addEvent.ts index 5cf351fd6f9c..8b2918656518 100644 --- a/packages/replay/src/util/addEvent.ts +++ b/packages/replay/src/util/addEvent.ts @@ -1,7 +1,6 @@ import { getCurrentHub } from '@sentry/core'; import { logger } from '@sentry/utils'; -import { SESSION_IDLE_DURATION } from '../constants'; import type { AddEventResult, RecordingEvent, ReplayContainer } from '../types'; /** @@ -31,7 +30,7 @@ export async function addEvent( // page has been left open and idle for a long period of time and user // comes back to trigger a new session. The performance entries rely on // `performance.timeOrigin`, which is when the page first opened. - if (timestampInMs + SESSION_IDLE_DURATION < new Date().getTime()) { + if (timestampInMs + replay.timeouts.sessionIdle < new Date().getTime()) { return null; } diff --git a/packages/replay/src/util/isSessionExpired.ts b/packages/replay/src/util/isSessionExpired.ts index a9d529f0986a..b7025a19cbf6 100644 --- a/packages/replay/src/util/isSessionExpired.ts +++ b/packages/replay/src/util/isSessionExpired.ts @@ -1,16 +1,15 @@ -import { MAX_SESSION_LIFE } from '../constants'; -import type { Session } from '../types'; +import type { Session, Timeouts } from '../types'; import { isExpired } from './isExpired'; /** * Checks to see if session is expired */ -export function isSessionExpired(session: Session, idleTimeout: number, targetTime: number = +new Date()): boolean { +export function isSessionExpired(session: Session, timeouts: Timeouts, targetTime: number = +new Date()): boolean { return ( // First, check that maximum session length has not been exceeded - isExpired(session.started, MAX_SESSION_LIFE, targetTime) || + isExpired(session.started, timeouts.maxSessionLife, targetTime) || // check that the idle timeout has not been exceeded (i.e. user has // performed an action within the last `idleTimeout` ms) - isExpired(session.lastActivity, idleTimeout, targetTime) + isExpired(session.lastActivity, timeouts.sessionIdle, targetTime) ); } diff --git a/packages/replay/test/unit/session/getSession.test.ts b/packages/replay/test/unit/session/getSession.test.ts index 54c259fb7772..4ac92b148e75 100644 --- a/packages/replay/test/unit/session/getSession.test.ts +++ b/packages/replay/test/unit/session/getSession.test.ts @@ -1,4 +1,4 @@ -import { WINDOW } from '../../../src/constants'; +import { MAX_SESSION_LIFE, SESSION_IDLE_DURATION, WINDOW } from '../../../src/constants'; import * as CreateSession from '../../../src/session/createSession'; import * as FetchSession from '../../../src/session/fetchSession'; import { getSession } from '../../../src/session/getSession'; @@ -42,7 +42,10 @@ describe('Unit | session | getSession', () => { it('creates a non-sticky session when one does not exist', function () { const { session } = getSession({ - expiry: 900000, + timeouts: { + sessionIdle: SESSION_IDLE_DURATION, + maxSessionLife: MAX_SESSION_LIFE, + }, stickySession: false, ...SAMPLE_RATES, }); @@ -66,7 +69,10 @@ describe('Unit | session | getSession', () => { saveSession(createMockSession(new Date().getTime() - 10000)); const { session } = getSession({ - expiry: 1000, + timeouts: { + sessionIdle: 1000, + maxSessionLife: MAX_SESSION_LIFE, + }, stickySession: false, ...SAMPLE_RATES, }); @@ -79,7 +85,10 @@ describe('Unit | session | getSession', () => { it('creates a non-sticky session, when one is expired', function () { const { session } = getSession({ - expiry: 1000, + timeouts: { + sessionIdle: 1000, + maxSessionLife: MAX_SESSION_LIFE, + }, stickySession: false, ...SAMPLE_RATES, currentSession: makeSession({ @@ -102,7 +111,10 @@ describe('Unit | session | getSession', () => { expect(FetchSession.fetchSession()).toBe(null); const { session } = getSession({ - expiry: 900000, + timeouts: { + sessionIdle: SESSION_IDLE_DURATION, + maxSessionLife: MAX_SESSION_LIFE, + }, stickySession: true, sessionSampleRate: 1.0, errorSampleRate: 0.0, @@ -134,7 +146,10 @@ describe('Unit | session | getSession', () => { saveSession(createMockSession(now)); const { session } = getSession({ - expiry: 1000, + timeouts: { + sessionIdle: 1000, + maxSessionLife: MAX_SESSION_LIFE, + }, stickySession: true, sessionSampleRate: 1.0, errorSampleRate: 0.0, @@ -157,7 +172,10 @@ describe('Unit | session | getSession', () => { saveSession(createMockSession(new Date().getTime() - 2000)); const { session } = getSession({ - expiry: 1000, + timeouts: { + sessionIdle: 1000, + maxSessionLife: MAX_SESSION_LIFE, + }, stickySession: true, ...SAMPLE_RATES, }); @@ -173,7 +191,10 @@ describe('Unit | session | getSession', () => { it('fetches a non-expired non-sticky session', function () { const { session } = getSession({ - expiry: 1000, + timeouts: { + sessionIdle: 1000, + maxSessionLife: MAX_SESSION_LIFE, + }, stickySession: false, ...SAMPLE_RATES, currentSession: makeSession({ diff --git a/packages/replay/test/unit/util/isSessionExpired.test.ts b/packages/replay/test/unit/util/isSessionExpired.test.ts index 381b8ffe6428..627105d322f0 100644 --- a/packages/replay/test/unit/util/isSessionExpired.test.ts +++ b/packages/replay/test/unit/util/isSessionExpired.test.ts @@ -1,3 +1,4 @@ +import { MAX_SESSION_LIFE } from '../../../src/constants'; import { makeSession } from '../../../src/session/Session'; import { isSessionExpired } from '../../../src/util/isSessionExpired'; @@ -14,18 +15,28 @@ function createSession(extra?: Record) { describe('Unit | util | isSessionExpired', () => { it('session last activity is older than expiry time', function () { - expect(isSessionExpired(createSession(), 100, 200)).toBe(true); // Session expired at ts = 100 + expect(isSessionExpired(createSession(), { maxSessionLife: MAX_SESSION_LIFE, sessionIdle: 100 }, 200)).toBe(true); // Session expired at ts = 100 }); it('session last activity is not older than expiry time', function () { - expect(isSessionExpired(createSession({ lastActivity: 100 }), 150, 200)).toBe(false); // Session expires at ts >= 250 + expect( + isSessionExpired( + createSession({ lastActivity: 100 }), + { maxSessionLife: MAX_SESSION_LIFE, sessionIdle: 150 }, + 200, + ), + ).toBe(false); // Session expires at ts >= 250 }); it('session age is not older than max session life', function () { - expect(isSessionExpired(createSession(), 1_800_000, 50_000)).toBe(false); + expect( + isSessionExpired(createSession(), { maxSessionLife: MAX_SESSION_LIFE, sessionIdle: 1_800_000 }, 50_000), + ).toBe(false); }); it('session age is older than max session life', function () { - expect(isSessionExpired(createSession(), 1_800_000, 1_800_001)).toBe(true); // Session expires at ts >= 1_800_000 + expect( + isSessionExpired(createSession(), { maxSessionLife: MAX_SESSION_LIFE, sessionIdle: 1_800_000 }, 1_800_001), + ).toBe(true); // Session expires at ts >= 1_800_000 }); }); diff --git a/rollup/plugins/bundlePlugins.js b/rollup/plugins/bundlePlugins.js index be91a495fc1e..752b3908f2e8 100644 --- a/rollup/plugins/bundlePlugins.js +++ b/rollup/plugins/bundlePlugins.js @@ -116,9 +116,10 @@ export function makeTerserPlugin() { '_driver', '_initStorage', '_support', - // We want to keept he _replay and _isEnabled variable unmangled to enable integration tests to access it + // We want to keep some replay fields unmangled to enable integration tests to access them '_replay', '_isEnabled', + '_isPaused', // We also can't mangle rrweb private fields when bundling rrweb in the replay CDN bundles '_cssText', // We want to keep the _integrations variable unmangled to send all installed integrations from replay From 04d551e8f1d179e71a42d1a1a65b0c31071a7435 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Tue, 7 Mar 2023 10:18:35 +0100 Subject: [PATCH 21/44] feat(replay): Update rrweb to 1.105.0 & add breadcrumb when encountering large mutation (#7314) --------- Co-authored-by: Billy Vong --- CHANGELOG.md | 2 ++ packages/replay/package.json | 2 +- packages/replay/src/replay.ts | 17 +++++++++++++++++ packages/replay/src/types.ts | 1 + packages/replay/test/integration/rrweb.test.ts | 1 + yarn.lock | 18 +++++++++--------- 6 files changed, 31 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f1da348c3fb..2e30b3c97422 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ - "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott +- fix(replay): Ensure `` is masked ([#69](https://github.com/getsentry/rrweb/pull/69)) + ## 7.41.0 - feat: Ensure we use the same default `environment` everywhere (#7327) diff --git a/packages/replay/package.json b/packages/replay/package.json index c1a783a0e763..d98abcce9f61 100644 --- a/packages/replay/package.json +++ b/packages/replay/package.json @@ -44,7 +44,7 @@ "devDependencies": { "@babel/core": "^7.17.5", "@sentry-internal/replay-worker": "7.41.0", - "@sentry-internal/rrweb": "1.104.1", + "@sentry-internal/rrweb": "1.105.0", "jsdom-worker": "^0.2.1", "tslib": "^1.9.3" }, diff --git a/packages/replay/src/replay.ts b/packages/replay/src/replay.ts index 544052172017..f96252f01d43 100644 --- a/packages/replay/src/replay.ts +++ b/packages/replay/src/replay.ts @@ -208,6 +208,23 @@ export class ReplayContainer implements ReplayContainerInterface { // instead, we'll always keep the last 60 seconds of replay before an error happened ...(this.recordingMode === 'error' && { checkoutEveryNms: ERROR_CHECKOUT_TIME }), emit: this._handleRecordingEmit, + onMutation: (mutations: unknown[]) => { + if (this._options._experiments.captureMutationSize) { + const count = mutations.length; + + if (count > 500) { + const breadcrumb = createBreadcrumb({ + category: 'replay.mutations', + data: { + count, + }, + }); + this._createCustomBreadcrumb(breadcrumb); + } + } + // `true` means we use the regular mutation handling by rrweb + return true; + }, }); } catch (err) { this._handleException(err); diff --git a/packages/replay/src/types.ts b/packages/replay/src/types.ts index b91e8be36129..15c03e228b83 100644 --- a/packages/replay/src/types.ts +++ b/packages/replay/src/types.ts @@ -110,6 +110,7 @@ export interface ReplayPluginOptions extends SessionOptions { _experiments: Partial<{ captureExceptions: boolean; traceInternals: boolean; + captureMutationSize: boolean; }>; } diff --git a/packages/replay/test/integration/rrweb.test.ts b/packages/replay/test/integration/rrweb.test.ts index 6d324d96208e..3e37df5f2910 100644 --- a/packages/replay/test/integration/rrweb.test.ts +++ b/packages/replay/test/integration/rrweb.test.ts @@ -32,6 +32,7 @@ describe('Integration | rrweb', () => { "maskInputSelector": ".sentry-mask,[data-sentry-mask]", "maskTextFn": undefined, "maskTextSelector": ".sentry-mask,[data-sentry-mask]", + "onMutation": [Function], "slimDOMOptions": "all", "unblockSelector": ".sentry-unblock,[data-sentry-unblock]", "unmaskInputSelector": ".sentry-unmask,[data-sentry-unmask]", diff --git a/yarn.lock b/yarn.lock index aa778db88c85..6de62b92a4ea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3917,17 +3917,17 @@ semver "7.3.2" semver-intersect "1.4.0" -"@sentry-internal/rrweb-snapshot@1.104.1": - version "1.104.1" - resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb-snapshot/-/rrweb-snapshot-1.104.1.tgz#baa1e951be432b8b8345833f5ed926144c62601f" - integrity sha512-IefNuRsyG8xoo6RNqTRoIaaarhjV1NO7JPiohYyyeSWDu26hK4mKlwDLlY41A5fRq8i49fiISoLU1EKueYFGOA== +"@sentry-internal/rrweb-snapshot@1.105.0": + version "1.105.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb-snapshot/-/rrweb-snapshot-1.105.0.tgz#b95d056e3602ab075049b31354942051137f3de2" + integrity sha512-UsrCVB5PVKTd3nXidUQSFQPjMHi2p5RzcujdBVuZfOJmRAqkHW6fN3CM4H6vJh0L5bgs+O/MFTNSv+iiAyVrBQ== -"@sentry-internal/rrweb@1.104.1": - version "1.104.1" - resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb/-/rrweb-1.104.1.tgz#a4c25f8daf59327d528540f872d301f4bc866dcc" - integrity sha512-kdf/tfMsIr3mr6IGZwpBcrS05GWyKbkAhv/4GkFevw9VSeHozTn2pPx6gU9M4WskN7NiZp4wvJ+4uLgwWdZSwg== +"@sentry-internal/rrweb@1.105.0": + version "1.105.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb/-/rrweb-1.105.0.tgz#c4238692753ed910d0fc23887361cc4d5d5112ab" + integrity sha512-RwJiQXaYzvLhqkAJtvwxu6WuO3OnedTpWtfdJX73kYujleSzoIBRNUXBs03Ir9E48UN5gzKu/eRG76QdH+e8Ow== dependencies: - "@sentry-internal/rrweb-snapshot" "1.104.1" + "@sentry-internal/rrweb-snapshot" "1.105.0" "@types/css-font-loading-module" "0.0.7" "@xstate/fsm" "^1.4.0" base64-arraybuffer "^1.0.1" From 231e3110af28c891e40d1e08ebbebb90709d09c7 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Tue, 7 Mar 2023 11:02:56 +0000 Subject: [PATCH 22/44] uuids suck as transactions --- .../test-applications/nextjs-app-dir/tests/trace.test.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/e2e-tests/test-applications/nextjs-app-dir/tests/trace.test.ts b/packages/e2e-tests/test-applications/nextjs-app-dir/tests/trace.test.ts index d8cc0fc1d81a..99d03266d01f 100644 --- a/packages/e2e-tests/test-applications/nextjs-app-dir/tests/trace.test.ts +++ b/packages/e2e-tests/test-applications/nextjs-app-dir/tests/trace.test.ts @@ -1,13 +1,12 @@ import { test } from '@playwright/test'; -import * as crypto from 'crypto'; import { waitForTransaction } from '../../../test-utils/event-proxy-server'; if (process.env.TEST_ENV === 'production') { // TODO: Fix that this is flakey on dev server - might be an SDK bug - test('Sends connected traces for server components', async ({ page }) => { + test('Sends connected traces for server components', async ({ page }, testInfo) => { await page.goto('/client-component'); - const clientTransactionName = crypto.randomUUID(); + const clientTransactionName = `e2e-next-js-app-dir: ${testInfo.title}`; const serverComponentTransaction = waitForTransaction('nextjs-13-app-dir', async transactionEvent => { return ( From dc696c05c0eddc1684a8e46b50bcd6bc6f147369 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Tue, 7 Mar 2023 12:45:22 +0100 Subject: [PATCH 23/44] ref(tracing): Re-organize exports for node/browser (#7345) --- packages/tracing/.eslintrc.js | 2 +- packages/tracing/package.json | 32 ++++++++++++- packages/tracing/rollup.npm.config.js | 1 + packages/tracing/src/browser/index.ts | 2 + packages/tracing/src/exports/index.ts | 15 +++++++ packages/tracing/src/extensions.ts | 8 ++-- packages/tracing/src/index.ts | 29 ++++-------- packages/tracing/src/integrations/index.ts | 11 ----- packages/tracing/src/node/index.ts | 3 ++ .../node => node/integrations}/apollo.ts | 0 .../node => node/integrations}/express.ts | 0 .../node => node/integrations}/graphql.ts | 0 .../tracing/src/node/integrations/index.ts | 11 +++++ .../node => node/integrations}/mongo.ts | 0 .../node => node/integrations}/mysql.ts | 0 .../node => node/integrations}/postgres.ts | 0 .../node => node/integrations}/prisma.ts | 0 .../integrations}/utils/node-utils.ts | 0 .../test/integrations/apollo-nestjs.test.ts | 2 +- .../tracing/test/integrations/apollo.test.ts | 2 +- .../tracing/test/integrations/graphql.test.ts | 2 +- .../test/integrations/node/mongo.test.ts | 2 +- .../test/integrations/node/postgres.test.ts | 2 +- .../test/integrations/node/prisma.test.ts | 2 +- scripts/prepack.ts | 45 ++++++++++++++++--- 25 files changed, 123 insertions(+), 48 deletions(-) create mode 100644 packages/tracing/src/exports/index.ts delete mode 100644 packages/tracing/src/integrations/index.ts create mode 100644 packages/tracing/src/node/index.ts rename packages/tracing/src/{integrations/node => node/integrations}/apollo.ts (100%) rename packages/tracing/src/{integrations/node => node/integrations}/express.ts (100%) rename packages/tracing/src/{integrations/node => node/integrations}/graphql.ts (100%) create mode 100644 packages/tracing/src/node/integrations/index.ts rename packages/tracing/src/{integrations/node => node/integrations}/mongo.ts (100%) rename packages/tracing/src/{integrations/node => node/integrations}/mysql.ts (100%) rename packages/tracing/src/{integrations/node => node/integrations}/postgres.ts (100%) rename packages/tracing/src/{integrations/node => node/integrations}/prisma.ts (100%) rename packages/tracing/src/{integrations/node => node/integrations}/utils/node-utils.ts (100%) diff --git a/packages/tracing/.eslintrc.js b/packages/tracing/.eslintrc.js index 3cabb2be4d99..7a937173064e 100644 --- a/packages/tracing/.eslintrc.js +++ b/packages/tracing/.eslintrc.js @@ -2,7 +2,7 @@ module.exports = { extends: ['../../.eslintrc.js'], overrides: [ { - files: ['src/integrations/node/**'], + files: ['src/node/**'], rules: { '@sentry-internal/sdk/no-optional-chaining': 'off', }, diff --git a/packages/tracing/package.json b/packages/tracing/package.json index 8188cb842f5e..6187925a799e 100644 --- a/packages/tracing/package.json +++ b/packages/tracing/package.json @@ -1,7 +1,7 @@ { "name": "@sentry/tracing", "version": "7.41.0", - "description": "Extensions for Sentry AM", + "description": "Sentry Performance Monitoring Package", "repository": "git://github.com/getsentry/sentry-javascript.git", "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/tracing", "author": "Sentry", @@ -12,6 +12,36 @@ "main": "build/npm/cjs/index.js", "module": "build/npm/esm/index.js", "types": "build/npm/types/index.d.ts", + "exports": { + ".": { + "import": "./build/npm/esm/index.js", + "require": "./build/npm/cjs/index.js", + "types": "./build/npm/types/index.d.ts" + }, + "./node": { + "import": "./build/npm/esm/node/index.js", + "require": "./build/npm/cjs/node/index.js", + "types": "./build/npm/types/node/index.d.ts" + }, + "./browser": { + "import": "./build/npm/esm/browser/index.js", + "require": "./build/npm/cjs/browser/index.js", + "types": "./build/npm/types/browser/index.d.ts" + } + }, + "typesVersions": { + "*": { + "*": [ + "./build/npm/types/index.d.ts" + ], + "node": [ + "./build/npm/types/node/index.d.ts" + ], + "browser": [ + "./build/npm/types/browser/index.d.ts" + ] + } + }, "publishConfig": { "access": "public" }, diff --git a/packages/tracing/rollup.npm.config.js b/packages/tracing/rollup.npm.config.js index 4ffa8b9396d8..a7588e2a9538 100644 --- a/packages/tracing/rollup.npm.config.js +++ b/packages/tracing/rollup.npm.config.js @@ -2,6 +2,7 @@ import { makeBaseNPMConfig, makeNPMConfigVariants } from '../../rollup/index.js' export default makeNPMConfigVariants( makeBaseNPMConfig({ + entrypoints: ['src/browser/index.ts', 'src/node/index.ts', 'src/index.ts'], // packages with bundles have a different build directory structure hasBundles: true, }), diff --git a/packages/tracing/src/browser/index.ts b/packages/tracing/src/browser/index.ts index dcf4a08270fd..3ed465eea6ca 100644 --- a/packages/tracing/src/browser/index.ts +++ b/packages/tracing/src/browser/index.ts @@ -1,3 +1,5 @@ +export * from '../exports'; + export type { RequestInstrumentationOptions } from './request'; export { BrowserTracing, BROWSER_TRACING_INTEGRATION_ID } from './browsertracing'; diff --git a/packages/tracing/src/exports/index.ts b/packages/tracing/src/exports/index.ts new file mode 100644 index 000000000000..12c6e451e5a5 --- /dev/null +++ b/packages/tracing/src/exports/index.ts @@ -0,0 +1,15 @@ +export { + extractTraceparentData, + getActiveTransaction, + hasTracingEnabled, + IdleTransaction, + Span, + // eslint-disable-next-line deprecation/deprecation + SpanStatus, + spanStatusfromHttpCode, + startIdleTransaction, + stripUrlQueryAndFragment, + TRACEPARENT_REGEXP, + Transaction, +} from '@sentry/core'; +export type { SpanStatusType } from '@sentry/core'; diff --git a/packages/tracing/src/extensions.ts b/packages/tracing/src/extensions.ts index d6c0298dbbd7..e3c2ab511804 100644 --- a/packages/tracing/src/extensions.ts +++ b/packages/tracing/src/extensions.ts @@ -15,25 +15,25 @@ function _autoloadDatabaseIntegrations(): void { const packageToIntegrationMapping: Record Integration> = { mongodb() { - const integration = dynamicRequire(module, './integrations/node/mongo') as { + const integration = dynamicRequire(module, './node/integrations/mongo') as { Mongo: IntegrationClass; }; return new integration.Mongo(); }, mongoose() { - const integration = dynamicRequire(module, './integrations/node/mongo') as { + const integration = dynamicRequire(module, './node/integrations/mongo') as { Mongo: IntegrationClass; }; return new integration.Mongo({ mongoose: true }); }, mysql() { - const integration = dynamicRequire(module, './integrations/node/mysql') as { + const integration = dynamicRequire(module, './node/integrations/mysql') as { Mysql: IntegrationClass; }; return new integration.Mysql(); }, pg() { - const integration = dynamicRequire(module, './integrations/node/postgres') as { + const integration = dynamicRequire(module, './node/integrations/postgres') as { Postgres: IntegrationClass; }; return new integration.Postgres(); diff --git a/packages/tracing/src/index.ts b/packages/tracing/src/index.ts index b8cb377ffdfe..b8456bc6b017 100644 --- a/packages/tracing/src/index.ts +++ b/packages/tracing/src/index.ts @@ -1,23 +1,7 @@ -export { - extractTraceparentData, - getActiveTransaction, - hasTracingEnabled, - IdleTransaction, - Span, - // eslint-disable-next-line deprecation/deprecation - SpanStatus, - spanStatusfromHttpCode, - startIdleTransaction, - stripUrlQueryAndFragment, - TRACEPARENT_REGEXP, - Transaction, -} from '@sentry/core'; -export type { SpanStatusType } from '@sentry/core'; +export * from './exports'; import { addExtensionMethods } from './extensions'; -import * as Integrations from './integrations'; - -export type { RequestInstrumentationOptions } from './browser'; +import * as Integrations from './node/integrations'; export { Integrations }; @@ -37,9 +21,14 @@ export { Integrations }; // const instance = new BrowserTracing(); // // For an example of of the new usage of BrowserTracing, see @sentry/nextjs index.client.ts -export { BrowserTracing, BROWSER_TRACING_INTEGRATION_ID } from './browser'; +export { + BrowserTracing, + BROWSER_TRACING_INTEGRATION_ID, + instrumentOutgoingRequests, + defaultRequestInstrumentationOptions, +} from './browser'; -export { instrumentOutgoingRequests, defaultRequestInstrumentationOptions } from './browser'; +export type { RequestInstrumentationOptions } from './browser'; // Treeshakable guard to remove all code related to tracing declare const __SENTRY_TRACING__: boolean; diff --git a/packages/tracing/src/integrations/index.ts b/packages/tracing/src/integrations/index.ts deleted file mode 100644 index 7522599aa4cf..000000000000 --- a/packages/tracing/src/integrations/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -export { Express } from './node/express'; -export { Postgres } from './node/postgres'; -export { Mysql } from './node/mysql'; -export { Mongo } from './node/mongo'; -export { Prisma } from './node/prisma'; -export { GraphQL } from './node/graphql'; -export { Apollo } from './node/apollo'; - -// TODO(v7): Remove this export -// Please see `src/index.ts` for more details. -export { BrowserTracing } from '../browser'; diff --git a/packages/tracing/src/node/index.ts b/packages/tracing/src/node/index.ts new file mode 100644 index 000000000000..eac5910c32c7 --- /dev/null +++ b/packages/tracing/src/node/index.ts @@ -0,0 +1,3 @@ +export * from '../exports'; + +export * from './integrations'; diff --git a/packages/tracing/src/integrations/node/apollo.ts b/packages/tracing/src/node/integrations/apollo.ts similarity index 100% rename from packages/tracing/src/integrations/node/apollo.ts rename to packages/tracing/src/node/integrations/apollo.ts diff --git a/packages/tracing/src/integrations/node/express.ts b/packages/tracing/src/node/integrations/express.ts similarity index 100% rename from packages/tracing/src/integrations/node/express.ts rename to packages/tracing/src/node/integrations/express.ts diff --git a/packages/tracing/src/integrations/node/graphql.ts b/packages/tracing/src/node/integrations/graphql.ts similarity index 100% rename from packages/tracing/src/integrations/node/graphql.ts rename to packages/tracing/src/node/integrations/graphql.ts diff --git a/packages/tracing/src/node/integrations/index.ts b/packages/tracing/src/node/integrations/index.ts new file mode 100644 index 000000000000..91554d84fccd --- /dev/null +++ b/packages/tracing/src/node/integrations/index.ts @@ -0,0 +1,11 @@ +export { Express } from './express'; +export { Postgres } from './postgres'; +export { Mysql } from './mysql'; +export { Mongo } from './mongo'; +export { Prisma } from './prisma'; +export { GraphQL } from './graphql'; +export { Apollo } from './apollo'; + +// TODO(v8): Remove this export +// Please see `src/index.ts` for more details. +export { BrowserTracing } from '../../browser'; diff --git a/packages/tracing/src/integrations/node/mongo.ts b/packages/tracing/src/node/integrations/mongo.ts similarity index 100% rename from packages/tracing/src/integrations/node/mongo.ts rename to packages/tracing/src/node/integrations/mongo.ts diff --git a/packages/tracing/src/integrations/node/mysql.ts b/packages/tracing/src/node/integrations/mysql.ts similarity index 100% rename from packages/tracing/src/integrations/node/mysql.ts rename to packages/tracing/src/node/integrations/mysql.ts diff --git a/packages/tracing/src/integrations/node/postgres.ts b/packages/tracing/src/node/integrations/postgres.ts similarity index 100% rename from packages/tracing/src/integrations/node/postgres.ts rename to packages/tracing/src/node/integrations/postgres.ts diff --git a/packages/tracing/src/integrations/node/prisma.ts b/packages/tracing/src/node/integrations/prisma.ts similarity index 100% rename from packages/tracing/src/integrations/node/prisma.ts rename to packages/tracing/src/node/integrations/prisma.ts diff --git a/packages/tracing/src/integrations/node/utils/node-utils.ts b/packages/tracing/src/node/integrations/utils/node-utils.ts similarity index 100% rename from packages/tracing/src/integrations/node/utils/node-utils.ts rename to packages/tracing/src/node/integrations/utils/node-utils.ts diff --git a/packages/tracing/test/integrations/apollo-nestjs.test.ts b/packages/tracing/test/integrations/apollo-nestjs.test.ts index 4eb173b9958a..981693875d7a 100644 --- a/packages/tracing/test/integrations/apollo-nestjs.test.ts +++ b/packages/tracing/test/integrations/apollo-nestjs.test.ts @@ -3,7 +3,7 @@ import { Hub, Scope } from '@sentry/core'; import { logger } from '@sentry/utils'; import { Span } from '../../src'; -import { Apollo } from '../../src/integrations/node/apollo'; +import { Apollo } from '../../src/node/integrations/apollo'; import { getTestClient } from '../testutils'; type ApolloResolverGroup = { diff --git a/packages/tracing/test/integrations/apollo.test.ts b/packages/tracing/test/integrations/apollo.test.ts index 4a79fe227c9d..910c866505e8 100644 --- a/packages/tracing/test/integrations/apollo.test.ts +++ b/packages/tracing/test/integrations/apollo.test.ts @@ -3,7 +3,7 @@ import { Hub, Scope } from '@sentry/core'; import { logger } from '@sentry/utils'; import { Span } from '../../src'; -import { Apollo } from '../../src/integrations/node/apollo'; +import { Apollo } from '../../src/node/integrations/apollo'; import { getTestClient } from '../testutils'; type ApolloResolverGroup = { diff --git a/packages/tracing/test/integrations/graphql.test.ts b/packages/tracing/test/integrations/graphql.test.ts index db59187a6c7b..5d61a4acd5cb 100644 --- a/packages/tracing/test/integrations/graphql.test.ts +++ b/packages/tracing/test/integrations/graphql.test.ts @@ -3,7 +3,7 @@ import { Hub, Scope } from '@sentry/core'; import { logger } from '@sentry/utils'; import { Span } from '../../src'; -import { GraphQL } from '../../src/integrations/node/graphql'; +import { GraphQL } from '../../src/node/integrations/graphql'; import { getTestClient } from '../testutils'; const GQLExecute = { diff --git a/packages/tracing/test/integrations/node/mongo.test.ts b/packages/tracing/test/integrations/node/mongo.test.ts index 84b1071c2f3c..5c3dd11255c4 100644 --- a/packages/tracing/test/integrations/node/mongo.test.ts +++ b/packages/tracing/test/integrations/node/mongo.test.ts @@ -3,7 +3,7 @@ import { Hub, Scope } from '@sentry/core'; import { logger } from '@sentry/utils'; import { Span } from '../../../src'; -import { Mongo } from '../../../src/integrations/node/mongo'; +import { Mongo } from '../../../src/node/integrations/mongo'; import { getTestClient } from '../../testutils'; class Collection { diff --git a/packages/tracing/test/integrations/node/postgres.test.ts b/packages/tracing/test/integrations/node/postgres.test.ts index 57e655bd1a99..08aa64cf368d 100644 --- a/packages/tracing/test/integrations/node/postgres.test.ts +++ b/packages/tracing/test/integrations/node/postgres.test.ts @@ -3,7 +3,7 @@ import { Hub, Scope } from '@sentry/core'; import { logger } from '@sentry/utils'; import { Span } from '../../../src'; -import { Postgres } from '../../../src/integrations/node/postgres'; +import { Postgres } from '../../../src/node/integrations/postgres'; import { getTestClient } from '../../testutils'; class PgClient { diff --git a/packages/tracing/test/integrations/node/prisma.test.ts b/packages/tracing/test/integrations/node/prisma.test.ts index b4866c31f15f..95892f9c1686 100644 --- a/packages/tracing/test/integrations/node/prisma.test.ts +++ b/packages/tracing/test/integrations/node/prisma.test.ts @@ -3,7 +3,7 @@ import { Hub, Scope } from '@sentry/core'; import { logger } from '@sentry/utils'; import { Span } from '../../../src'; -import { Prisma } from '../../../src/integrations/node/prisma'; +import { Prisma } from '../../../src/node/integrations/prisma'; import { getTestClient } from '../../testutils'; type PrismaMiddleware = (params: unknown, next: (params?: unknown) => Promise) => Promise; diff --git a/scripts/prepack.ts b/scripts/prepack.ts index ace6846db457..bcad9dee0ef8 100644 --- a/scripts/prepack.ts +++ b/scripts/prepack.ts @@ -13,14 +13,33 @@ const NPM_BUILD_DIR = 'build/npm'; const BUILD_DIR = 'build'; const NPM_IGNORE = fs.existsSync('.npmignore') ? '.npmignore' : '../../.npmignore'; -const ASSETS = ['README.md', 'LICENSE', 'package.json', NPM_IGNORE]; -const ENTRY_POINTS = ['main', 'module', 'types', 'browser']; +const ASSETS = ['README.md', 'LICENSE', 'package.json', NPM_IGNORE] as const; +const ENTRY_POINTS = ['main', 'module', 'types', 'browser'] as const; +const EXPORT_MAP_ENTRY_POINT = 'exports'; +const TYPES_VERSIONS_ENTRY_POINT = 'typesVersions'; const packageWithBundles = process.argv.includes('--bundles'); const buildDir = packageWithBundles ? NPM_BUILD_DIR : BUILD_DIR; +type PackageJsonEntryPoints = Record; + +interface PackageJson extends Record, PackageJsonEntryPoints { + [EXPORT_MAP_ENTRY_POINT]: { + [key: string]: { + import: string; + require: string; + types: string; + }; + }; + [TYPES_VERSIONS_ENTRY_POINT]: { + [key: string]: { + [key: string]: string[]; + }; + }; +} + // eslint-disable-next-line @typescript-eslint/no-var-requires -const pkgJson: { [key: string]: unknown } = require(path.resolve('package.json')); +const pkgJson: PackageJson = require(path.resolve('package.json')); // check if build dir exists if (!fs.existsSync(path.resolve(buildDir))) { @@ -44,13 +63,29 @@ ASSETS.forEach(asset => { // package.json modifications const newPackageJsonPath = path.resolve(buildDir, 'package.json'); // eslint-disable-next-line @typescript-eslint/no-var-requires -const newPkgJson: { [key: string]: unknown } = require(newPackageJsonPath); +const newPkgJson: PackageJson = require(newPackageJsonPath); // modify entry points to point to correct paths (i.e. strip out the build directory) ENTRY_POINTS.filter(entryPoint => newPkgJson[entryPoint]).forEach(entryPoint => { - newPkgJson[entryPoint] = (newPkgJson[entryPoint] as string).replace(`${buildDir}/`, ''); + newPkgJson[entryPoint] = newPkgJson[entryPoint].replace(`${buildDir}/`, ''); }); +if (newPkgJson[EXPORT_MAP_ENTRY_POINT]) { + Object.entries(newPkgJson[EXPORT_MAP_ENTRY_POINT]).forEach(([key, val]) => { + newPkgJson[EXPORT_MAP_ENTRY_POINT][key] = Object.entries(val).reduce((acc, [key, val]) => { + return { ...acc, [key]: val.replace(`${buildDir}/`, '') }; + }, {} as typeof val); + }); +} + +if (newPkgJson[TYPES_VERSIONS_ENTRY_POINT]) { + Object.entries(newPkgJson[TYPES_VERSIONS_ENTRY_POINT]).forEach(([key, val]) => { + newPkgJson[TYPES_VERSIONS_ENTRY_POINT][key] = Object.entries(val).reduce((acc, [key, val]) => { + return { ...acc, [key]: val.map(v => v.replace(`${buildDir}/`, '')) }; + }, {}); + }); +} + delete newPkgJson.scripts; delete newPkgJson.volta; delete newPkgJson.jest; From 9bf840a6d192151908ca06cef9342b6e0b7f12c0 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Tue, 7 Mar 2023 13:13:14 +0100 Subject: [PATCH 24/44] fix: Ensure `originalException` has type `unknown` (#7361) This used to be typed as `Error | string | null` which is not correct, as technically _anything_ can be thrown. To reflect this existing reality, we have to broaden this type. Note that this _could_ lead to problems for users that currently depend on this type, but any potential issues arising because of this would actually be valid problems that should actually be fixed in the user code (e.g. relying on `error.message` to be present, for example). --- packages/core/src/baseclient.ts | 2 +- packages/core/src/hub.ts | 3 +-- packages/node/src/integrations/onunhandledrejection.ts | 3 +-- packages/types/src/event.ts | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/core/src/baseclient.ts b/packages/core/src/baseclient.ts index 7a90b07925f6..b551cfafb8e8 100644 --- a/packages/core/src/baseclient.ts +++ b/packages/core/src/baseclient.ts @@ -560,7 +560,7 @@ export abstract class BaseClient implements Client { data: { __sentry__: true, }, - originalException: reason as Error, + originalException: reason, }); throw new SentryError( `Event processing pipeline threw an error, original event will not be sent. Details have been sent as a new event.\nReason: ${reason}`, diff --git a/packages/core/src/hub.ts b/packages/core/src/hub.ts index 5a3f99937042..c150c05eaef9 100644 --- a/packages/core/src/hub.ts +++ b/packages/core/src/hub.ts @@ -183,8 +183,7 @@ export class Hub implements HubInterface { /** * @inheritDoc */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types - public captureException(exception: any, hint?: EventHint): string { + public captureException(exception: unknown, hint?: EventHint): string { const eventId = (this._lastEventId = hint && hint.event_id ? hint.event_id : uuid4()); const syntheticException = new Error('Sentry syntheticException'); this._withClient((client, scope) => { diff --git a/packages/node/src/integrations/onunhandledrejection.ts b/packages/node/src/integrations/onunhandledrejection.ts index aa3916931ba7..1504b6dee6e0 100644 --- a/packages/node/src/integrations/onunhandledrejection.ts +++ b/packages/node/src/integrations/onunhandledrejection.ts @@ -44,8 +44,7 @@ export class OnUnhandledRejection implements Integration { * @param reason string * @param promise promise */ - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any - public sendUnhandledPromise(reason: any, promise: any): void { + public sendUnhandledPromise(reason: unknown, promise: unknown): void { const hub = getCurrentHub(); if (hub.getIntegration(OnUnhandledRejection)) { hub.withScope((scope: Scope) => { diff --git a/packages/types/src/event.ts b/packages/types/src/event.ts index 7d21456d8044..61783ef9361b 100644 --- a/packages/types/src/event.ts +++ b/packages/types/src/event.ts @@ -75,7 +75,7 @@ export interface EventHint { event_id?: string; captureContext?: CaptureContext; syntheticException?: Error | null; - originalException?: Error | string | null; + originalException?: unknown; attachments?: Attachment[]; data?: any; integrations?: string[]; From f8b56b0eb70d4c33e49e68b41e7ab8d5a434d24a Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Tue, 7 Mar 2023 15:16:21 +0100 Subject: [PATCH 25/44] test(replay): Make tests less flaky (#7368) --- .../test.ts-snapshots/seg-0-snap-full | 206 +++--- .../seg-0-snap-full-chromium | 206 +++--- .../test.ts-snapshots/seg-1-snap-incremental | 63 +- .../seg-1-snap-incremental-chromium | 63 +- .../test.ts-snapshots/seg-2-snap-full | 206 +++--- .../seg-2-snap-full-chromium | 206 +++--- .../test.ts-snapshots/seg-3-snap-incremental | 63 +- .../seg-3-snap-incremental-chromium | 63 +- .../test.ts-snapshots/seg-4-snap-full | 290 ++++----- .../seg-4-snap-full-chromium | 290 ++++----- .../test.ts-snapshots/seg-5-snap-incremental | 63 +- .../seg-5-snap-incremental-chromium | 63 +- .../test.ts-snapshots/seg-6-snap-incremental | 73 ++- .../seg-6-snap-incremental-chromium | 73 ++- .../test.ts-snapshots/seg-7-snap-incremental | 73 ++- .../seg-7-snap-incremental-chromium | 73 ++- .../test.ts-snapshots/seg-8-snap-full | 206 +++--- .../seg-8-snap-full-chromium | 206 +++--- .../test.ts-snapshots/seg-9-snap-incremental | 63 +- .../seg-9-snap-incremental-chromium | 63 +- .../test.ts-snapshots/privacy-chromium.json | 602 +++++++++--------- .../test.ts-snapshots/privacy-firefox.json | 602 +++++++++--------- .../test.ts-snapshots/privacy-webkit.json | 602 +++++++++--------- .../test.ts-snapshots/privacy.json | 602 +++++++++--------- .../test.ts-snapshots/privacy-chromium.json | 522 +++++++-------- .../test.ts-snapshots/privacy-firefox.json | 522 +++++++-------- .../test.ts-snapshots/privacy-webkit.json | 522 +++++++-------- .../test.ts-snapshots/privacy.json | 522 +++++++-------- .../suites/replay/sessionExpiry/test.ts | 24 - .../snapshot-0-chromium.json | 210 +++--- .../test.ts-snapshots/snapshot-0-firefox.json | 210 +++--- .../test.ts-snapshots/snapshot-0-webkit.json | 210 +++--- .../test.ts-snapshots/snapshot-0.json | 210 +++--- .../snapshot-2-chromium.json | 210 +++--- .../test.ts-snapshots/snapshot-2-firefox.json | 210 +++--- .../test.ts-snapshots/snapshot-2-webkit.json | 210 +++--- .../test.ts-snapshots/snapshot-2.json | 210 +++--- .../snapshot-0-chromium.json | 210 +++--- .../test.ts-snapshots/snapshot-0-firefox.json | 210 +++--- .../test.ts-snapshots/snapshot-0-webkit.json | 210 +++--- .../test.ts-snapshots/snapshot-0.json | 210 +++--- .../snapshot-1-chromium.json | 210 +++--- .../test.ts-snapshots/snapshot-1-firefox.json | 210 +++--- .../test.ts-snapshots/snapshot-1-webkit.json | 210 +++--- .../test.ts-snapshots/snapshot-1.json | 210 +++--- .../unicode-compressed-chromium.json | 240 +++---- .../unicode-compressed-firefox.json | 240 +++---- .../unicode-compressed-webkit.json | 240 +++---- .../test.ts-snapshots/unicode-compressed.json | 240 +++---- .../unicode-uncompressed-chromium.json | 240 +++---- .../unicode-uncompressed-firefox.json | 240 +++---- .../unicode-uncompressed-webkit.json | 240 +++---- .../unicode-uncompressed.json | 240 +++---- .../integration-tests/utils/replayHelpers.ts | 37 +- 54 files changed, 6333 insertions(+), 6116 deletions(-) diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-0-snap-full b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-0-snap-full index cfd7928e8d9d..fdccbb1b9387 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-0-snap-full +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-0-snap-full @@ -1,109 +1,113 @@ [ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "id": "go-background" + { + "type": 2, + "tagName": "button", + "attributes": { + "id": "go-background" + }, + "childNodes": [ + { + "type": 3, + "textContent": "*** ***", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "*** ***", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "a", - "attributes": { - "href": "/page-0.html" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "** ** *** ****", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "a", + "attributes": { + "href": "/page-0.html" + }, + "childNodes": [ + { + "type": 3, + "textContent": "** ** *** ****", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-0-snap-full-chromium b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-0-snap-full-chromium index cfd7928e8d9d..fdccbb1b9387 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-0-snap-full-chromium +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-0-snap-full-chromium @@ -1,109 +1,113 @@ [ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "id": "go-background" + { + "type": 2, + "tagName": "button", + "attributes": { + "id": "go-background" + }, + "childNodes": [ + { + "type": 3, + "textContent": "*** ***", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "*** ***", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "a", - "attributes": { - "href": "/page-0.html" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "** ** *** ****", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "a", + "attributes": { + "href": "/page-0.html" + }, + "childNodes": [ + { + "type": 3, + "textContent": "** ** *** ****", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-1-snap-incremental b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-1-snap-incremental index 29620a33392b..f612eadc8f80 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-1-snap-incremental +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-1-snap-incremental @@ -1,39 +1,44 @@ [ { - "source": 1, - "positions": [ - { - "x": 41, - "y": 18, - "id": 9, - "timeOffset": [timeOffset] - } - ] + "type": 3, + "data": { + "source": 2, + "type": 1, + "id": 9, + "x": 41, + "y": 18 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 1, - "id": 9, - "x": 41, - "y": 18 + "type": 3, + "data": { + "source": 2, + "type": 5, + "id": 9 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 5, - "id": 9 + "type": 3, + "data": { + "source": 2, + "type": 0, + "id": 9, + "x": 41, + "y": 18 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 0, - "id": 9, - "x": 41, - "y": 18 - }, - { - "source": 2, - "type": 2, - "id": 9, - "x": 41, - "y": 18 + "type": 3, + "data": { + "source": 2, + "type": 2, + "id": 9, + "x": 41, + "y": 18 + }, + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-1-snap-incremental-chromium b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-1-snap-incremental-chromium index 29620a33392b..f612eadc8f80 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-1-snap-incremental-chromium +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-1-snap-incremental-chromium @@ -1,39 +1,44 @@ [ { - "source": 1, - "positions": [ - { - "x": 41, - "y": 18, - "id": 9, - "timeOffset": [timeOffset] - } - ] + "type": 3, + "data": { + "source": 2, + "type": 1, + "id": 9, + "x": 41, + "y": 18 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 1, - "id": 9, - "x": 41, - "y": 18 + "type": 3, + "data": { + "source": 2, + "type": 5, + "id": 9 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 5, - "id": 9 + "type": 3, + "data": { + "source": 2, + "type": 0, + "id": 9, + "x": 41, + "y": 18 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 0, - "id": 9, - "x": 41, - "y": 18 - }, - { - "source": 2, - "type": 2, - "id": 9, - "x": 41, - "y": 18 + "type": 3, + "data": { + "source": 2, + "type": 2, + "id": 9, + "x": 41, + "y": 18 + }, + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-2-snap-full b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-2-snap-full index cfd7928e8d9d..fdccbb1b9387 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-2-snap-full +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-2-snap-full @@ -1,109 +1,113 @@ [ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "id": "go-background" + { + "type": 2, + "tagName": "button", + "attributes": { + "id": "go-background" + }, + "childNodes": [ + { + "type": 3, + "textContent": "*** ***", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "*** ***", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "a", - "attributes": { - "href": "/page-0.html" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "** ** *** ****", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "a", + "attributes": { + "href": "/page-0.html" + }, + "childNodes": [ + { + "type": 3, + "textContent": "** ** *** ****", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-2-snap-full-chromium b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-2-snap-full-chromium index cfd7928e8d9d..fdccbb1b9387 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-2-snap-full-chromium +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-2-snap-full-chromium @@ -1,109 +1,113 @@ [ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "id": "go-background" + { + "type": 2, + "tagName": "button", + "attributes": { + "id": "go-background" + }, + "childNodes": [ + { + "type": 3, + "textContent": "*** ***", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "*** ***", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "a", - "attributes": { - "href": "/page-0.html" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "** ** *** ****", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "a", + "attributes": { + "href": "/page-0.html" + }, + "childNodes": [ + { + "type": 3, + "textContent": "** ** *** ****", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-3-snap-incremental b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-3-snap-incremental index 29620a33392b..f612eadc8f80 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-3-snap-incremental +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-3-snap-incremental @@ -1,39 +1,44 @@ [ { - "source": 1, - "positions": [ - { - "x": 41, - "y": 18, - "id": 9, - "timeOffset": [timeOffset] - } - ] + "type": 3, + "data": { + "source": 2, + "type": 1, + "id": 9, + "x": 41, + "y": 18 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 1, - "id": 9, - "x": 41, - "y": 18 + "type": 3, + "data": { + "source": 2, + "type": 5, + "id": 9 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 5, - "id": 9 + "type": 3, + "data": { + "source": 2, + "type": 0, + "id": 9, + "x": 41, + "y": 18 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 0, - "id": 9, - "x": 41, - "y": 18 - }, - { - "source": 2, - "type": 2, - "id": 9, - "x": 41, - "y": 18 + "type": 3, + "data": { + "source": 2, + "type": 2, + "id": 9, + "x": 41, + "y": 18 + }, + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-3-snap-incremental-chromium b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-3-snap-incremental-chromium index 29620a33392b..f612eadc8f80 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-3-snap-incremental-chromium +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-3-snap-incremental-chromium @@ -1,39 +1,44 @@ [ { - "source": 1, - "positions": [ - { - "x": 41, - "y": 18, - "id": 9, - "timeOffset": [timeOffset] - } - ] + "type": 3, + "data": { + "source": 2, + "type": 1, + "id": 9, + "x": 41, + "y": 18 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 1, - "id": 9, - "x": 41, - "y": 18 + "type": 3, + "data": { + "source": 2, + "type": 5, + "id": 9 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 5, - "id": 9 + "type": 3, + "data": { + "source": 2, + "type": 0, + "id": 9, + "x": 41, + "y": 18 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 0, - "id": 9, - "x": 41, - "y": 18 - }, - { - "source": 2, - "type": 2, - "id": 9, - "x": 41, - "y": 18 + "type": 3, + "data": { + "source": 2, + "type": 2, + "id": 9, + "x": 41, + "y": 18 + }, + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-4-snap-full b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-4-snap-full index a6c4b9f7c908..b0aeb348b388 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-4-snap-full +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-4-snap-full @@ -1,152 +1,156 @@ [ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "h1", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "********* ****", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "id": "go-background" + { + "type": 2, + "tagName": "h1", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "********* ****", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "*** ***", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "id": "spa-navigation" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** * *** **********", - "id": 16 - } - ], - "id": 15 - }, - { - "type": 3, - "textContent": "\n ", - "id": 17 - }, - { - "type": 3, - "textContent": "\n ", - "id": 18 - }, - { - "type": 2, - "tagName": "a", - "attributes": { - "href": "/index.html" + { + "type": 2, + "tagName": "button", + "attributes": { + "id": "go-background" + }, + "childNodes": [ + { + "type": 3, + "textContent": "*** ***", + "id": 13 + } + ], + "id": 12 }, - "childNodes": [ - { - "type": 3, - "textContent": "** **** ** ***** ****", - "id": 20 - } - ], - "id": 19 - }, - { - "type": 3, - "textContent": "\n ", - "id": 21 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 22 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "id": "spa-navigation" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** * *** **********", + "id": 16 + } + ], + "id": 15 + }, + { + "type": 3, + "textContent": "\n ", + "id": 17 + }, + { + "type": 3, + "textContent": "\n ", + "id": 18 + }, + { + "type": 2, + "tagName": "a", + "attributes": { + "href": "/index.html" + }, + "childNodes": [ + { + "type": 3, + "textContent": "** **** ** ***** ****", + "id": 20 + } + ], + "id": 19 + }, + { + "type": 3, + "textContent": "\n ", + "id": 21 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 22 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-4-snap-full-chromium b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-4-snap-full-chromium index a6c4b9f7c908..b0aeb348b388 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-4-snap-full-chromium +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-4-snap-full-chromium @@ -1,152 +1,156 @@ [ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "h1", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "********* ****", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "id": "go-background" + { + "type": 2, + "tagName": "h1", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "********* ****", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "*** ***", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "id": "spa-navigation" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** * *** **********", - "id": 16 - } - ], - "id": 15 - }, - { - "type": 3, - "textContent": "\n ", - "id": 17 - }, - { - "type": 3, - "textContent": "\n ", - "id": 18 - }, - { - "type": 2, - "tagName": "a", - "attributes": { - "href": "/index.html" + { + "type": 2, + "tagName": "button", + "attributes": { + "id": "go-background" + }, + "childNodes": [ + { + "type": 3, + "textContent": "*** ***", + "id": 13 + } + ], + "id": 12 }, - "childNodes": [ - { - "type": 3, - "textContent": "** **** ** ***** ****", - "id": 20 - } - ], - "id": 19 - }, - { - "type": 3, - "textContent": "\n ", - "id": 21 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 22 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "id": "spa-navigation" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** * *** **********", + "id": 16 + } + ], + "id": 15 + }, + { + "type": 3, + "textContent": "\n ", + "id": 17 + }, + { + "type": 3, + "textContent": "\n ", + "id": 18 + }, + { + "type": 2, + "tagName": "a", + "attributes": { + "href": "/index.html" + }, + "childNodes": [ + { + "type": 3, + "textContent": "** **** ** ***** ****", + "id": 20 + } + ], + "id": 19 + }, + { + "type": 3, + "textContent": "\n ", + "id": 21 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 22 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-5-snap-incremental b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-5-snap-incremental index 3035cb50910e..13c75c43bf61 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-5-snap-incremental +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-5-snap-incremental @@ -1,39 +1,44 @@ [ { - "source": 1, - "positions": [ - { - "x": 41, - "y": 90, - "id": 12, - "timeOffset": [timeOffset] - } - ] + "type": 3, + "data": { + "source": 2, + "type": 1, + "id": 12, + "x": 41, + "y": 90 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 1, - "id": 12, - "x": 41, - "y": 90 + "type": 3, + "data": { + "source": 2, + "type": 5, + "id": 12 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 5, - "id": 12 + "type": 3, + "data": { + "source": 2, + "type": 0, + "id": 12, + "x": 41, + "y": 90 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 0, - "id": 12, - "x": 41, - "y": 90 - }, - { - "source": 2, - "type": 2, - "id": 12, - "x": 41, - "y": 90 + "type": 3, + "data": { + "source": 2, + "type": 2, + "id": 12, + "x": 41, + "y": 90 + }, + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-5-snap-incremental-chromium b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-5-snap-incremental-chromium index 3035cb50910e..13c75c43bf61 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-5-snap-incremental-chromium +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-5-snap-incremental-chromium @@ -1,39 +1,44 @@ [ { - "source": 1, - "positions": [ - { - "x": 41, - "y": 90, - "id": 12, - "timeOffset": [timeOffset] - } - ] + "type": 3, + "data": { + "source": 2, + "type": 1, + "id": 12, + "x": 41, + "y": 90 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 1, - "id": 12, - "x": 41, - "y": 90 + "type": 3, + "data": { + "source": 2, + "type": 5, + "id": 12 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 5, - "id": 12 + "type": 3, + "data": { + "source": 2, + "type": 0, + "id": 12, + "x": 41, + "y": 90 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 0, - "id": 12, - "x": 41, - "y": 90 - }, - { - "source": 2, - "type": 2, - "id": 12, - "x": 41, - "y": 90 + "type": 3, + "data": { + "source": 2, + "type": 2, + "id": 12, + "x": 41, + "y": 90 + }, + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-6-snap-incremental b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-6-snap-incremental index ddaf5314ca3d..c7be8ab3861a 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-6-snap-incremental +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-6-snap-incremental @@ -1,44 +1,53 @@ [ { - "source": 1, - "positions": [ - { - "x": 157, - "y": 90, - "id": 15, - "timeOffset": [timeOffset] - } - ] + "type": 3, + "data": { + "source": 2, + "type": 1, + "id": 15, + "x": 157, + "y": 90 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 1, - "id": 15, - "x": 157, - "y": 90 + "type": 3, + "data": { + "source": 2, + "type": 6, + "id": 12 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 6, - "id": 12 + "type": 3, + "data": { + "source": 2, + "type": 5, + "id": 15 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 5, - "id": 15 + "type": 3, + "data": { + "source": 2, + "type": 0, + "id": 15, + "x": 157, + "y": 90 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 0, - "id": 15, - "x": 157, - "y": 90 - }, - { - "source": 2, - "type": 2, - "id": 15, - "x": 157, - "y": 90 + "type": 3, + "data": { + "source": 2, + "type": 2, + "id": 15, + "x": 157, + "y": 90 + }, + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-6-snap-incremental-chromium b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-6-snap-incremental-chromium index ddaf5314ca3d..c7be8ab3861a 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-6-snap-incremental-chromium +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-6-snap-incremental-chromium @@ -1,44 +1,53 @@ [ { - "source": 1, - "positions": [ - { - "x": 157, - "y": 90, - "id": 15, - "timeOffset": [timeOffset] - } - ] + "type": 3, + "data": { + "source": 2, + "type": 1, + "id": 15, + "x": 157, + "y": 90 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 1, - "id": 15, - "x": 157, - "y": 90 + "type": 3, + "data": { + "source": 2, + "type": 6, + "id": 12 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 6, - "id": 12 + "type": 3, + "data": { + "source": 2, + "type": 5, + "id": 15 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 5, - "id": 15 + "type": 3, + "data": { + "source": 2, + "type": 0, + "id": 15, + "x": 157, + "y": 90 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 0, - "id": 15, - "x": 157, - "y": 90 - }, - { - "source": 2, - "type": 2, - "id": 15, - "x": 157, - "y": 90 + "type": 3, + "data": { + "source": 2, + "type": 2, + "id": 15, + "x": 157, + "y": 90 + }, + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-7-snap-incremental b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-7-snap-incremental index ae20ba0fd987..5b461c8cb66c 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-7-snap-incremental +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-7-snap-incremental @@ -1,44 +1,53 @@ [ { - "source": 1, - "positions": [ - { - "x": 41, - "y": 90, - "id": 12, - "timeOffset": [timeOffset] - } - ] + "type": 3, + "data": { + "source": 2, + "type": 1, + "id": 12, + "x": 41, + "y": 90 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 1, - "id": 12, - "x": 41, - "y": 90 + "type": 3, + "data": { + "source": 2, + "type": 6, + "id": 15 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 6, - "id": 15 + "type": 3, + "data": { + "source": 2, + "type": 5, + "id": 12 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 5, - "id": 12 + "type": 3, + "data": { + "source": 2, + "type": 0, + "id": 12, + "x": 41, + "y": 90 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 0, - "id": 12, - "x": 41, - "y": 90 - }, - { - "source": 2, - "type": 2, - "id": 12, - "x": 41, - "y": 90 + "type": 3, + "data": { + "source": 2, + "type": 2, + "id": 12, + "x": 41, + "y": 90 + }, + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-7-snap-incremental-chromium b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-7-snap-incremental-chromium index ae20ba0fd987..5b461c8cb66c 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-7-snap-incremental-chromium +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-7-snap-incremental-chromium @@ -1,44 +1,53 @@ [ { - "source": 1, - "positions": [ - { - "x": 41, - "y": 90, - "id": 12, - "timeOffset": [timeOffset] - } - ] + "type": 3, + "data": { + "source": 2, + "type": 1, + "id": 12, + "x": 41, + "y": 90 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 1, - "id": 12, - "x": 41, - "y": 90 + "type": 3, + "data": { + "source": 2, + "type": 6, + "id": 15 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 6, - "id": 15 + "type": 3, + "data": { + "source": 2, + "type": 5, + "id": 12 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 5, - "id": 12 + "type": 3, + "data": { + "source": 2, + "type": 0, + "id": 12, + "x": 41, + "y": 90 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 0, - "id": 12, - "x": 41, - "y": 90 - }, - { - "source": 2, - "type": 2, - "id": 12, - "x": 41, - "y": 90 + "type": 3, + "data": { + "source": 2, + "type": 2, + "id": 12, + "x": 41, + "y": 90 + }, + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-8-snap-full b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-8-snap-full index cfd7928e8d9d..fdccbb1b9387 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-8-snap-full +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-8-snap-full @@ -1,109 +1,113 @@ [ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "id": "go-background" + { + "type": 2, + "tagName": "button", + "attributes": { + "id": "go-background" + }, + "childNodes": [ + { + "type": 3, + "textContent": "*** ***", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "*** ***", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "a", - "attributes": { - "href": "/page-0.html" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "** ** *** ****", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "a", + "attributes": { + "href": "/page-0.html" + }, + "childNodes": [ + { + "type": 3, + "textContent": "** ** *** ****", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-8-snap-full-chromium b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-8-snap-full-chromium index cfd7928e8d9d..fdccbb1b9387 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-8-snap-full-chromium +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-8-snap-full-chromium @@ -1,109 +1,113 @@ [ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "id": "go-background" + { + "type": 2, + "tagName": "button", + "attributes": { + "id": "go-background" + }, + "childNodes": [ + { + "type": 3, + "textContent": "*** ***", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "*** ***", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "a", - "attributes": { - "href": "/page-0.html" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "** ** *** ****", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "a", + "attributes": { + "href": "/page-0.html" + }, + "childNodes": [ + { + "type": 3, + "textContent": "** ** *** ****", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-9-snap-incremental b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-9-snap-incremental index 29620a33392b..f612eadc8f80 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-9-snap-incremental +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-9-snap-incremental @@ -1,39 +1,44 @@ [ { - "source": 1, - "positions": [ - { - "x": 41, - "y": 18, - "id": 9, - "timeOffset": [timeOffset] - } - ] + "type": 3, + "data": { + "source": 2, + "type": 1, + "id": 9, + "x": 41, + "y": 18 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 1, - "id": 9, - "x": 41, - "y": 18 + "type": 3, + "data": { + "source": 2, + "type": 5, + "id": 9 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 5, - "id": 9 + "type": 3, + "data": { + "source": 2, + "type": 0, + "id": 9, + "x": 41, + "y": 18 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 0, - "id": 9, - "x": 41, - "y": 18 - }, - { - "source": 2, - "type": 2, - "id": 9, - "x": 41, - "y": 18 + "type": 3, + "data": { + "source": 2, + "type": 2, + "id": 9, + "x": 41, + "y": 18 + }, + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-9-snap-incremental-chromium b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-9-snap-incremental-chromium index 29620a33392b..f612eadc8f80 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-9-snap-incremental-chromium +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts-snapshots/seg-9-snap-incremental-chromium @@ -1,39 +1,44 @@ [ { - "source": 1, - "positions": [ - { - "x": 41, - "y": 18, - "id": 9, - "timeOffset": [timeOffset] - } - ] + "type": 3, + "data": { + "source": 2, + "type": 1, + "id": 9, + "x": 41, + "y": 18 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 1, - "id": 9, - "x": 41, - "y": 18 + "type": 3, + "data": { + "source": 2, + "type": 5, + "id": 9 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 5, - "id": 9 + "type": 3, + "data": { + "source": 2, + "type": 0, + "id": 9, + "x": 41, + "y": 18 + }, + "timestamp": [timestamp] }, { - "source": 2, - "type": 0, - "id": 9, - "x": 41, - "y": 18 - }, - { - "source": 2, - "type": 2, - "id": 9, - "x": 41, - "y": 18 + "type": 3, + "data": { + "source": 2, + "type": 2, + "id": 9, + "x": 41, + "y": 18 + }, + "timestamp": [timestamp] } ] \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy-chromium.json b/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy-chromium.json index a120d5e44a5e..9ca91c2dc5da 100644 --- a/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy-chromium.json +++ b/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy-chromium.json @@ -1,319 +1,323 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + }, + { + "type": 2, + "tagName": "link", + "attributes": { + "rr_width": "[0-50]px", + "rr_height": "[0-50]px" + }, + "childNodes": [], + "id": 6 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 7 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 9 }, - "childNodes": [], - "id": 5 - }, - { - "type": 2, - "tagName": "link", - "attributes": { - "rr_width": "[0-50]px", - "rr_height": "[0-50]px" + { + "type": 2, + "tagName": "button", + "attributes": { + "aria-label": "***** **", + "onclick": "console.log('Test log')" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 11 + } + ], + "id": 10 }, - "childNodes": [], - "id": 6 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 7 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 9 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "aria-label": "***** **", - "onclick": "console.log('Test log')" + { + "type": 3, + "textContent": "\n ", + "id": 12 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 11 - } - ], - "id": 10 - }, - { - "type": 3, - "textContent": "\n ", - "id": 12 - }, - { - "type": 2, - "tagName": "div", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "**** ****** ** ****** ** *******", - "id": 14 - } - ], - "id": 13 - }, - { - "type": 3, - "textContent": "\n ", - "id": 15 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "data-sentry-unmask": "" + { + "type": 2, + "tagName": "div", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "**** ****** ** ****** ** *******", + "id": 14 + } + ], + "id": 13 }, - "childNodes": [ - { - "type": 3, - "textContent": "This should be unmasked due to data attribute", - "id": 17 - } - ], - "id": 16 - }, - { - "type": 3, - "textContent": "\n ", - "id": 18 - }, - { - "type": 2, - "tagName": "input", - "attributes": { - "placeholder": "*********** ****** ** ******" + { + "type": 3, + "textContent": "\n ", + "id": 15 }, - "childNodes": [], - "id": 19 - }, - { - "type": 3, - "textContent": "\n ", - "id": 20 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "title": "***** ****** ** ******" + { + "type": 2, + "tagName": "div", + "attributes": { + "data-sentry-unmask": "" + }, + "childNodes": [ + { + "type": 3, + "textContent": "This should be unmasked due to data attribute", + "id": 17 + } + ], + "id": 16 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** ****** ** ******", - "id": 22 - } - ], - "id": 21 - }, - { - "type": 3, - "textContent": "\n ", - "id": 23 - }, - { - "type": 2, - "tagName": "svg", - "attributes": { - "style": "width:200px;height:200px", - "viewBox": "0 0 80 80" + { + "type": 3, + "textContent": "\n ", + "id": 18 }, - "childNodes": [ - { - "type": 2, - "tagName": "path", - "attributes": { - "d": "" - }, - "childNodes": [], - "isSVG": true, - "id": 25 + { + "type": 2, + "tagName": "input", + "attributes": { + "placeholder": "*********** ****** ** ******" }, - { - "type": 2, - "tagName": "area", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 26 + "childNodes": [], + "id": 19 + }, + { + "type": 3, + "textContent": "\n ", + "id": 20 + }, + { + "type": 2, + "tagName": "div", + "attributes": { + "title": "***** ****** ** ******" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** ****** ** ******", + "id": 22 + } + ], + "id": 21 + }, + { + "type": 3, + "textContent": "\n ", + "id": 23 + }, + { + "type": 2, + "tagName": "svg", + "attributes": { + "style": "width:200px;height:200px", + "viewBox": "0 0 80 80" }, - { - "type": 2, - "tagName": "rect", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 27 - } - ], - "isSVG": true, - "id": 24 - }, - { - "type": 3, - "textContent": "\n ", - "id": 28 - }, - { - "type": 2, - "tagName": "svg", - "attributes": { - "style": "width:200px;height:200px", - "viewBox": "0 0 80 80", - "data-sentry-unblock": "" + "childNodes": [ + { + "type": 2, + "tagName": "path", + "attributes": { + "d": "" + }, + "childNodes": [], + "isSVG": true, + "id": 25 + }, + { + "type": 2, + "tagName": "area", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 26 + }, + { + "type": 2, + "tagName": "rect", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 27 + } + ], + "isSVG": true, + "id": 24 + }, + { + "type": 3, + "textContent": "\n ", + "id": 28 }, - "childNodes": [ - { - "type": 2, - "tagName": "path", - "attributes": { - "d": "" + { + "type": 2, + "tagName": "svg", + "attributes": { + "style": "width:200px;height:200px", + "viewBox": "0 0 80 80", + "data-sentry-unblock": "" + }, + "childNodes": [ + { + "type": 2, + "tagName": "path", + "attributes": { + "d": "" + }, + "childNodes": [], + "isSVG": true, + "id": 30 }, - "childNodes": [], - "isSVG": true, - "id": 30 + { + "type": 2, + "tagName": "area", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 31 + }, + { + "type": 2, + "tagName": "rect", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 32 + } + ], + "isSVG": true, + "id": 29 + }, + { + "type": 3, + "textContent": "\n ", + "id": 33 + }, + { + "type": 2, + "tagName": "img", + "attributes": { + "style": "width:100px;height:100px", + "src": "file:///none.png" }, - { - "type": 2, - "tagName": "area", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 31 + "childNodes": [], + "id": 34 + }, + { + "type": 3, + "textContent": "\n ", + "id": 35 + }, + { + "type": 2, + "tagName": "img", + "attributes": { + "data-sentry-unblock": "", + "style": "width:100px;height:100px", + "src": "file:///none.png" + }, + "childNodes": [], + "id": 36 + }, + { + "type": 3, + "textContent": "\n ", + "id": 37 + }, + { + "type": 2, + "tagName": "video", + "attributes": { + "rr_width": "[0-50]px", + "rr_height": "[0-50]px" }, - { - "type": 2, - "tagName": "rect", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 32 - } - ], - "isSVG": true, - "id": 29 - }, - { - "type": 3, - "textContent": "\n ", - "id": 33 - }, - { - "type": 2, - "tagName": "img", - "attributes": { - "style": "width:100px;height:100px", - "src": "file:///none.png" + "childNodes": [], + "id": 38 }, - "childNodes": [], - "id": 34 - }, - { - "type": 3, - "textContent": "\n ", - "id": 35 - }, - { - "type": 2, - "tagName": "img", - "attributes": { - "data-sentry-unblock": "", - "style": "width:100px;height:100px", - "src": "file:///none.png" + { + "type": 3, + "textContent": "\n ", + "id": 39 }, - "childNodes": [], - "id": 36 - }, - { - "type": 3, - "textContent": "\n ", - "id": 37 - }, - { - "type": 2, - "tagName": "video", - "attributes": { - "rr_width": "[0-50]px", - "rr_height": "[0-50]px" + { + "type": 2, + "tagName": "div", + "attributes": { + "class": "nested-hide", + "rr_width": "[1250-1300]px", + "rr_height": "[0-50]px" + }, + "childNodes": [], + "id": 40 }, - "childNodes": [], - "id": 38 - }, - { - "type": 3, - "textContent": "\n ", - "id": 39 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "class": "nested-hide", - "rr_width": "[1250-1300]px", - "rr_height": "[0-50]px" + { + "type": 3, + "textContent": "\n ", + "id": 41 }, - "childNodes": [], - "id": 40 - }, - { - "type": 3, - "textContent": "\n ", - "id": 41 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 42 - } - ], - "id": 8 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 3, + "textContent": "\n\n", + "id": 42 + } + ], + "id": 8 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy-firefox.json b/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy-firefox.json index a120d5e44a5e..9ca91c2dc5da 100644 --- a/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy-firefox.json +++ b/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy-firefox.json @@ -1,319 +1,323 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + }, + { + "type": 2, + "tagName": "link", + "attributes": { + "rr_width": "[0-50]px", + "rr_height": "[0-50]px" + }, + "childNodes": [], + "id": 6 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 7 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 9 }, - "childNodes": [], - "id": 5 - }, - { - "type": 2, - "tagName": "link", - "attributes": { - "rr_width": "[0-50]px", - "rr_height": "[0-50]px" + { + "type": 2, + "tagName": "button", + "attributes": { + "aria-label": "***** **", + "onclick": "console.log('Test log')" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 11 + } + ], + "id": 10 }, - "childNodes": [], - "id": 6 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 7 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 9 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "aria-label": "***** **", - "onclick": "console.log('Test log')" + { + "type": 3, + "textContent": "\n ", + "id": 12 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 11 - } - ], - "id": 10 - }, - { - "type": 3, - "textContent": "\n ", - "id": 12 - }, - { - "type": 2, - "tagName": "div", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "**** ****** ** ****** ** *******", - "id": 14 - } - ], - "id": 13 - }, - { - "type": 3, - "textContent": "\n ", - "id": 15 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "data-sentry-unmask": "" + { + "type": 2, + "tagName": "div", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "**** ****** ** ****** ** *******", + "id": 14 + } + ], + "id": 13 }, - "childNodes": [ - { - "type": 3, - "textContent": "This should be unmasked due to data attribute", - "id": 17 - } - ], - "id": 16 - }, - { - "type": 3, - "textContent": "\n ", - "id": 18 - }, - { - "type": 2, - "tagName": "input", - "attributes": { - "placeholder": "*********** ****** ** ******" + { + "type": 3, + "textContent": "\n ", + "id": 15 }, - "childNodes": [], - "id": 19 - }, - { - "type": 3, - "textContent": "\n ", - "id": 20 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "title": "***** ****** ** ******" + { + "type": 2, + "tagName": "div", + "attributes": { + "data-sentry-unmask": "" + }, + "childNodes": [ + { + "type": 3, + "textContent": "This should be unmasked due to data attribute", + "id": 17 + } + ], + "id": 16 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** ****** ** ******", - "id": 22 - } - ], - "id": 21 - }, - { - "type": 3, - "textContent": "\n ", - "id": 23 - }, - { - "type": 2, - "tagName": "svg", - "attributes": { - "style": "width:200px;height:200px", - "viewBox": "0 0 80 80" + { + "type": 3, + "textContent": "\n ", + "id": 18 }, - "childNodes": [ - { - "type": 2, - "tagName": "path", - "attributes": { - "d": "" - }, - "childNodes": [], - "isSVG": true, - "id": 25 + { + "type": 2, + "tagName": "input", + "attributes": { + "placeholder": "*********** ****** ** ******" }, - { - "type": 2, - "tagName": "area", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 26 + "childNodes": [], + "id": 19 + }, + { + "type": 3, + "textContent": "\n ", + "id": 20 + }, + { + "type": 2, + "tagName": "div", + "attributes": { + "title": "***** ****** ** ******" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** ****** ** ******", + "id": 22 + } + ], + "id": 21 + }, + { + "type": 3, + "textContent": "\n ", + "id": 23 + }, + { + "type": 2, + "tagName": "svg", + "attributes": { + "style": "width:200px;height:200px", + "viewBox": "0 0 80 80" }, - { - "type": 2, - "tagName": "rect", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 27 - } - ], - "isSVG": true, - "id": 24 - }, - { - "type": 3, - "textContent": "\n ", - "id": 28 - }, - { - "type": 2, - "tagName": "svg", - "attributes": { - "style": "width:200px;height:200px", - "viewBox": "0 0 80 80", - "data-sentry-unblock": "" + "childNodes": [ + { + "type": 2, + "tagName": "path", + "attributes": { + "d": "" + }, + "childNodes": [], + "isSVG": true, + "id": 25 + }, + { + "type": 2, + "tagName": "area", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 26 + }, + { + "type": 2, + "tagName": "rect", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 27 + } + ], + "isSVG": true, + "id": 24 + }, + { + "type": 3, + "textContent": "\n ", + "id": 28 }, - "childNodes": [ - { - "type": 2, - "tagName": "path", - "attributes": { - "d": "" + { + "type": 2, + "tagName": "svg", + "attributes": { + "style": "width:200px;height:200px", + "viewBox": "0 0 80 80", + "data-sentry-unblock": "" + }, + "childNodes": [ + { + "type": 2, + "tagName": "path", + "attributes": { + "d": "" + }, + "childNodes": [], + "isSVG": true, + "id": 30 }, - "childNodes": [], - "isSVG": true, - "id": 30 + { + "type": 2, + "tagName": "area", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 31 + }, + { + "type": 2, + "tagName": "rect", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 32 + } + ], + "isSVG": true, + "id": 29 + }, + { + "type": 3, + "textContent": "\n ", + "id": 33 + }, + { + "type": 2, + "tagName": "img", + "attributes": { + "style": "width:100px;height:100px", + "src": "file:///none.png" }, - { - "type": 2, - "tagName": "area", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 31 + "childNodes": [], + "id": 34 + }, + { + "type": 3, + "textContent": "\n ", + "id": 35 + }, + { + "type": 2, + "tagName": "img", + "attributes": { + "data-sentry-unblock": "", + "style": "width:100px;height:100px", + "src": "file:///none.png" + }, + "childNodes": [], + "id": 36 + }, + { + "type": 3, + "textContent": "\n ", + "id": 37 + }, + { + "type": 2, + "tagName": "video", + "attributes": { + "rr_width": "[0-50]px", + "rr_height": "[0-50]px" }, - { - "type": 2, - "tagName": "rect", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 32 - } - ], - "isSVG": true, - "id": 29 - }, - { - "type": 3, - "textContent": "\n ", - "id": 33 - }, - { - "type": 2, - "tagName": "img", - "attributes": { - "style": "width:100px;height:100px", - "src": "file:///none.png" + "childNodes": [], + "id": 38 }, - "childNodes": [], - "id": 34 - }, - { - "type": 3, - "textContent": "\n ", - "id": 35 - }, - { - "type": 2, - "tagName": "img", - "attributes": { - "data-sentry-unblock": "", - "style": "width:100px;height:100px", - "src": "file:///none.png" + { + "type": 3, + "textContent": "\n ", + "id": 39 }, - "childNodes": [], - "id": 36 - }, - { - "type": 3, - "textContent": "\n ", - "id": 37 - }, - { - "type": 2, - "tagName": "video", - "attributes": { - "rr_width": "[0-50]px", - "rr_height": "[0-50]px" + { + "type": 2, + "tagName": "div", + "attributes": { + "class": "nested-hide", + "rr_width": "[1250-1300]px", + "rr_height": "[0-50]px" + }, + "childNodes": [], + "id": 40 }, - "childNodes": [], - "id": 38 - }, - { - "type": 3, - "textContent": "\n ", - "id": 39 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "class": "nested-hide", - "rr_width": "[1250-1300]px", - "rr_height": "[0-50]px" + { + "type": 3, + "textContent": "\n ", + "id": 41 }, - "childNodes": [], - "id": 40 - }, - { - "type": 3, - "textContent": "\n ", - "id": 41 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 42 - } - ], - "id": 8 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 3, + "textContent": "\n\n", + "id": 42 + } + ], + "id": 8 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy-webkit.json b/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy-webkit.json index a120d5e44a5e..9ca91c2dc5da 100644 --- a/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy-webkit.json +++ b/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy-webkit.json @@ -1,319 +1,323 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + }, + { + "type": 2, + "tagName": "link", + "attributes": { + "rr_width": "[0-50]px", + "rr_height": "[0-50]px" + }, + "childNodes": [], + "id": 6 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 7 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 9 }, - "childNodes": [], - "id": 5 - }, - { - "type": 2, - "tagName": "link", - "attributes": { - "rr_width": "[0-50]px", - "rr_height": "[0-50]px" + { + "type": 2, + "tagName": "button", + "attributes": { + "aria-label": "***** **", + "onclick": "console.log('Test log')" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 11 + } + ], + "id": 10 }, - "childNodes": [], - "id": 6 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 7 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 9 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "aria-label": "***** **", - "onclick": "console.log('Test log')" + { + "type": 3, + "textContent": "\n ", + "id": 12 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 11 - } - ], - "id": 10 - }, - { - "type": 3, - "textContent": "\n ", - "id": 12 - }, - { - "type": 2, - "tagName": "div", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "**** ****** ** ****** ** *******", - "id": 14 - } - ], - "id": 13 - }, - { - "type": 3, - "textContent": "\n ", - "id": 15 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "data-sentry-unmask": "" + { + "type": 2, + "tagName": "div", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "**** ****** ** ****** ** *******", + "id": 14 + } + ], + "id": 13 }, - "childNodes": [ - { - "type": 3, - "textContent": "This should be unmasked due to data attribute", - "id": 17 - } - ], - "id": 16 - }, - { - "type": 3, - "textContent": "\n ", - "id": 18 - }, - { - "type": 2, - "tagName": "input", - "attributes": { - "placeholder": "*********** ****** ** ******" + { + "type": 3, + "textContent": "\n ", + "id": 15 }, - "childNodes": [], - "id": 19 - }, - { - "type": 3, - "textContent": "\n ", - "id": 20 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "title": "***** ****** ** ******" + { + "type": 2, + "tagName": "div", + "attributes": { + "data-sentry-unmask": "" + }, + "childNodes": [ + { + "type": 3, + "textContent": "This should be unmasked due to data attribute", + "id": 17 + } + ], + "id": 16 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** ****** ** ******", - "id": 22 - } - ], - "id": 21 - }, - { - "type": 3, - "textContent": "\n ", - "id": 23 - }, - { - "type": 2, - "tagName": "svg", - "attributes": { - "style": "width:200px;height:200px", - "viewBox": "0 0 80 80" + { + "type": 3, + "textContent": "\n ", + "id": 18 }, - "childNodes": [ - { - "type": 2, - "tagName": "path", - "attributes": { - "d": "" - }, - "childNodes": [], - "isSVG": true, - "id": 25 + { + "type": 2, + "tagName": "input", + "attributes": { + "placeholder": "*********** ****** ** ******" }, - { - "type": 2, - "tagName": "area", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 26 + "childNodes": [], + "id": 19 + }, + { + "type": 3, + "textContent": "\n ", + "id": 20 + }, + { + "type": 2, + "tagName": "div", + "attributes": { + "title": "***** ****** ** ******" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** ****** ** ******", + "id": 22 + } + ], + "id": 21 + }, + { + "type": 3, + "textContent": "\n ", + "id": 23 + }, + { + "type": 2, + "tagName": "svg", + "attributes": { + "style": "width:200px;height:200px", + "viewBox": "0 0 80 80" }, - { - "type": 2, - "tagName": "rect", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 27 - } - ], - "isSVG": true, - "id": 24 - }, - { - "type": 3, - "textContent": "\n ", - "id": 28 - }, - { - "type": 2, - "tagName": "svg", - "attributes": { - "style": "width:200px;height:200px", - "viewBox": "0 0 80 80", - "data-sentry-unblock": "" + "childNodes": [ + { + "type": 2, + "tagName": "path", + "attributes": { + "d": "" + }, + "childNodes": [], + "isSVG": true, + "id": 25 + }, + { + "type": 2, + "tagName": "area", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 26 + }, + { + "type": 2, + "tagName": "rect", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 27 + } + ], + "isSVG": true, + "id": 24 + }, + { + "type": 3, + "textContent": "\n ", + "id": 28 }, - "childNodes": [ - { - "type": 2, - "tagName": "path", - "attributes": { - "d": "" + { + "type": 2, + "tagName": "svg", + "attributes": { + "style": "width:200px;height:200px", + "viewBox": "0 0 80 80", + "data-sentry-unblock": "" + }, + "childNodes": [ + { + "type": 2, + "tagName": "path", + "attributes": { + "d": "" + }, + "childNodes": [], + "isSVG": true, + "id": 30 }, - "childNodes": [], - "isSVG": true, - "id": 30 + { + "type": 2, + "tagName": "area", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 31 + }, + { + "type": 2, + "tagName": "rect", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 32 + } + ], + "isSVG": true, + "id": 29 + }, + { + "type": 3, + "textContent": "\n ", + "id": 33 + }, + { + "type": 2, + "tagName": "img", + "attributes": { + "style": "width:100px;height:100px", + "src": "file:///none.png" }, - { - "type": 2, - "tagName": "area", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 31 + "childNodes": [], + "id": 34 + }, + { + "type": 3, + "textContent": "\n ", + "id": 35 + }, + { + "type": 2, + "tagName": "img", + "attributes": { + "data-sentry-unblock": "", + "style": "width:100px;height:100px", + "src": "file:///none.png" + }, + "childNodes": [], + "id": 36 + }, + { + "type": 3, + "textContent": "\n ", + "id": 37 + }, + { + "type": 2, + "tagName": "video", + "attributes": { + "rr_width": "[0-50]px", + "rr_height": "[0-50]px" }, - { - "type": 2, - "tagName": "rect", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 32 - } - ], - "isSVG": true, - "id": 29 - }, - { - "type": 3, - "textContent": "\n ", - "id": 33 - }, - { - "type": 2, - "tagName": "img", - "attributes": { - "style": "width:100px;height:100px", - "src": "file:///none.png" + "childNodes": [], + "id": 38 }, - "childNodes": [], - "id": 34 - }, - { - "type": 3, - "textContent": "\n ", - "id": 35 - }, - { - "type": 2, - "tagName": "img", - "attributes": { - "data-sentry-unblock": "", - "style": "width:100px;height:100px", - "src": "file:///none.png" + { + "type": 3, + "textContent": "\n ", + "id": 39 }, - "childNodes": [], - "id": 36 - }, - { - "type": 3, - "textContent": "\n ", - "id": 37 - }, - { - "type": 2, - "tagName": "video", - "attributes": { - "rr_width": "[0-50]px", - "rr_height": "[0-50]px" + { + "type": 2, + "tagName": "div", + "attributes": { + "class": "nested-hide", + "rr_width": "[1250-1300]px", + "rr_height": "[0-50]px" + }, + "childNodes": [], + "id": 40 }, - "childNodes": [], - "id": 38 - }, - { - "type": 3, - "textContent": "\n ", - "id": 39 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "class": "nested-hide", - "rr_width": "[1250-1300]px", - "rr_height": "[0-50]px" + { + "type": 3, + "textContent": "\n ", + "id": 41 }, - "childNodes": [], - "id": 40 - }, - { - "type": 3, - "textContent": "\n ", - "id": 41 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 42 - } - ], - "id": 8 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 3, + "textContent": "\n\n", + "id": 42 + } + ], + "id": 8 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy.json b/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy.json index a120d5e44a5e..9ca91c2dc5da 100644 --- a/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy.json +++ b/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy.json @@ -1,319 +1,323 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + }, + { + "type": 2, + "tagName": "link", + "attributes": { + "rr_width": "[0-50]px", + "rr_height": "[0-50]px" + }, + "childNodes": [], + "id": 6 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 7 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 9 }, - "childNodes": [], - "id": 5 - }, - { - "type": 2, - "tagName": "link", - "attributes": { - "rr_width": "[0-50]px", - "rr_height": "[0-50]px" + { + "type": 2, + "tagName": "button", + "attributes": { + "aria-label": "***** **", + "onclick": "console.log('Test log')" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 11 + } + ], + "id": 10 }, - "childNodes": [], - "id": 6 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 7 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 9 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "aria-label": "***** **", - "onclick": "console.log('Test log')" + { + "type": 3, + "textContent": "\n ", + "id": 12 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 11 - } - ], - "id": 10 - }, - { - "type": 3, - "textContent": "\n ", - "id": 12 - }, - { - "type": 2, - "tagName": "div", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "**** ****** ** ****** ** *******", - "id": 14 - } - ], - "id": 13 - }, - { - "type": 3, - "textContent": "\n ", - "id": 15 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "data-sentry-unmask": "" + { + "type": 2, + "tagName": "div", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "**** ****** ** ****** ** *******", + "id": 14 + } + ], + "id": 13 }, - "childNodes": [ - { - "type": 3, - "textContent": "This should be unmasked due to data attribute", - "id": 17 - } - ], - "id": 16 - }, - { - "type": 3, - "textContent": "\n ", - "id": 18 - }, - { - "type": 2, - "tagName": "input", - "attributes": { - "placeholder": "*********** ****** ** ******" + { + "type": 3, + "textContent": "\n ", + "id": 15 }, - "childNodes": [], - "id": 19 - }, - { - "type": 3, - "textContent": "\n ", - "id": 20 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "title": "***** ****** ** ******" + { + "type": 2, + "tagName": "div", + "attributes": { + "data-sentry-unmask": "" + }, + "childNodes": [ + { + "type": 3, + "textContent": "This should be unmasked due to data attribute", + "id": 17 + } + ], + "id": 16 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** ****** ** ******", - "id": 22 - } - ], - "id": 21 - }, - { - "type": 3, - "textContent": "\n ", - "id": 23 - }, - { - "type": 2, - "tagName": "svg", - "attributes": { - "style": "width:200px;height:200px", - "viewBox": "0 0 80 80" + { + "type": 3, + "textContent": "\n ", + "id": 18 }, - "childNodes": [ - { - "type": 2, - "tagName": "path", - "attributes": { - "d": "" - }, - "childNodes": [], - "isSVG": true, - "id": 25 + { + "type": 2, + "tagName": "input", + "attributes": { + "placeholder": "*********** ****** ** ******" }, - { - "type": 2, - "tagName": "area", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 26 + "childNodes": [], + "id": 19 + }, + { + "type": 3, + "textContent": "\n ", + "id": 20 + }, + { + "type": 2, + "tagName": "div", + "attributes": { + "title": "***** ****** ** ******" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** ****** ** ******", + "id": 22 + } + ], + "id": 21 + }, + { + "type": 3, + "textContent": "\n ", + "id": 23 + }, + { + "type": 2, + "tagName": "svg", + "attributes": { + "style": "width:200px;height:200px", + "viewBox": "0 0 80 80" }, - { - "type": 2, - "tagName": "rect", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 27 - } - ], - "isSVG": true, - "id": 24 - }, - { - "type": 3, - "textContent": "\n ", - "id": 28 - }, - { - "type": 2, - "tagName": "svg", - "attributes": { - "style": "width:200px;height:200px", - "viewBox": "0 0 80 80", - "data-sentry-unblock": "" + "childNodes": [ + { + "type": 2, + "tagName": "path", + "attributes": { + "d": "" + }, + "childNodes": [], + "isSVG": true, + "id": 25 + }, + { + "type": 2, + "tagName": "area", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 26 + }, + { + "type": 2, + "tagName": "rect", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 27 + } + ], + "isSVG": true, + "id": 24 + }, + { + "type": 3, + "textContent": "\n ", + "id": 28 }, - "childNodes": [ - { - "type": 2, - "tagName": "path", - "attributes": { - "d": "" + { + "type": 2, + "tagName": "svg", + "attributes": { + "style": "width:200px;height:200px", + "viewBox": "0 0 80 80", + "data-sentry-unblock": "" + }, + "childNodes": [ + { + "type": 2, + "tagName": "path", + "attributes": { + "d": "" + }, + "childNodes": [], + "isSVG": true, + "id": 30 }, - "childNodes": [], - "isSVG": true, - "id": 30 + { + "type": 2, + "tagName": "area", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 31 + }, + { + "type": 2, + "tagName": "rect", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 32 + } + ], + "isSVG": true, + "id": 29 + }, + { + "type": 3, + "textContent": "\n ", + "id": 33 + }, + { + "type": 2, + "tagName": "img", + "attributes": { + "style": "width:100px;height:100px", + "src": "file:///none.png" }, - { - "type": 2, - "tagName": "area", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 31 + "childNodes": [], + "id": 34 + }, + { + "type": 3, + "textContent": "\n ", + "id": 35 + }, + { + "type": 2, + "tagName": "img", + "attributes": { + "data-sentry-unblock": "", + "style": "width:100px;height:100px", + "src": "file:///none.png" + }, + "childNodes": [], + "id": 36 + }, + { + "type": 3, + "textContent": "\n ", + "id": 37 + }, + { + "type": 2, + "tagName": "video", + "attributes": { + "rr_width": "[0-50]px", + "rr_height": "[0-50]px" }, - { - "type": 2, - "tagName": "rect", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 32 - } - ], - "isSVG": true, - "id": 29 - }, - { - "type": 3, - "textContent": "\n ", - "id": 33 - }, - { - "type": 2, - "tagName": "img", - "attributes": { - "style": "width:100px;height:100px", - "src": "file:///none.png" + "childNodes": [], + "id": 38 }, - "childNodes": [], - "id": 34 - }, - { - "type": 3, - "textContent": "\n ", - "id": 35 - }, - { - "type": 2, - "tagName": "img", - "attributes": { - "data-sentry-unblock": "", - "style": "width:100px;height:100px", - "src": "file:///none.png" + { + "type": 3, + "textContent": "\n ", + "id": 39 }, - "childNodes": [], - "id": 36 - }, - { - "type": 3, - "textContent": "\n ", - "id": 37 - }, - { - "type": 2, - "tagName": "video", - "attributes": { - "rr_width": "[0-50]px", - "rr_height": "[0-50]px" + { + "type": 2, + "tagName": "div", + "attributes": { + "class": "nested-hide", + "rr_width": "[1250-1300]px", + "rr_height": "[0-50]px" + }, + "childNodes": [], + "id": 40 }, - "childNodes": [], - "id": 38 - }, - { - "type": 3, - "textContent": "\n ", - "id": 39 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "class": "nested-hide", - "rr_width": "[1250-1300]px", - "rr_height": "[0-50]px" + { + "type": 3, + "textContent": "\n ", + "id": 41 }, - "childNodes": [], - "id": 40 - }, - { - "type": 3, - "textContent": "\n ", - "id": 41 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 42 - } - ], - "id": 8 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 3, + "textContent": "\n\n", + "id": 42 + } + ], + "id": 8 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-chromium.json b/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-chromium.json index 11bf6d7a7fa7..f1b55c0884ef 100644 --- a/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-chromium.json +++ b/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-chromium.json @@ -1,276 +1,280 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + }, + { + "type": 2, + "tagName": "link", + "attributes": { + "rr_width": "[0-50]px", + "rr_height": "[0-50]px" + }, + "childNodes": [], + "id": 6 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 7 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 9 }, - "childNodes": [], - "id": 5 - }, - { - "type": 2, - "tagName": "link", - "attributes": { - "rr_width": "[0-50]px", - "rr_height": "[0-50]px" + { + "type": 2, + "tagName": "button", + "attributes": { + "aria-label": "***** **", + "onclick": "console.log('Test log')" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 11 + } + ], + "id": 10 }, - "childNodes": [], - "id": 6 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 7 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 9 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "aria-label": "***** **", - "onclick": "console.log('Test log')" + { + "type": 3, + "textContent": "\n ", + "id": 12 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 11 - } - ], - "id": 10 - }, - { - "type": 3, - "textContent": "\n ", - "id": 12 - }, - { - "type": 2, - "tagName": "div", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "**** ****** ** ****** ** *******", - "id": 14 - } - ], - "id": 13 - }, - { - "type": 3, - "textContent": "\n ", - "id": 15 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "data-sentry-unmask": "" + { + "type": 2, + "tagName": "div", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "**** ****** ** ****** ** *******", + "id": 14 + } + ], + "id": 13 }, - "childNodes": [ - { - "type": 3, - "textContent": "This should be unmasked due to data attribute", - "id": 17 - } - ], - "id": 16 - }, - { - "type": 3, - "textContent": "\n ", - "id": 18 - }, - { - "type": 2, - "tagName": "input", - "attributes": { - "placeholder": "*********** ****** ** ******" + { + "type": 3, + "textContent": "\n ", + "id": 15 }, - "childNodes": [], - "id": 19 - }, - { - "type": 3, - "textContent": "\n ", - "id": 20 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "title": "***** ****** ** ******" + { + "type": 2, + "tagName": "div", + "attributes": { + "data-sentry-unmask": "" + }, + "childNodes": [ + { + "type": 3, + "textContent": "This should be unmasked due to data attribute", + "id": 17 + } + ], + "id": 16 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** ****** ** ******", - "id": 22 - } - ], - "id": 21 - }, - { - "type": 3, - "textContent": "\n ", - "id": 23 - }, - { - "type": 2, - "tagName": "svg", - "attributes": { - "rr_width": "[200-250]px", - "rr_height": "[200-250]px" + { + "type": 3, + "textContent": "\n ", + "id": 18 }, - "childNodes": [], - "isSVG": true, - "id": 24 - }, - { - "type": 3, - "textContent": "\n ", - "id": 25 - }, - { - "type": 2, - "tagName": "svg", - "attributes": { - "style": "width:200px;height:200px", - "viewBox": "0 0 80 80", - "data-sentry-unblock": "" + { + "type": 2, + "tagName": "input", + "attributes": { + "placeholder": "*********** ****** ** ******" + }, + "childNodes": [], + "id": 19 }, - "childNodes": [ - { - "type": 2, - "tagName": "path", - "attributes": { - "d": "" + { + "type": 3, + "textContent": "\n ", + "id": 20 + }, + { + "type": 2, + "tagName": "div", + "attributes": { + "title": "***** ****** ** ******" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** ****** ** ******", + "id": 22 + } + ], + "id": 21 + }, + { + "type": 3, + "textContent": "\n ", + "id": 23 + }, + { + "type": 2, + "tagName": "svg", + "attributes": { + "rr_width": "[200-250]px", + "rr_height": "[200-250]px" + }, + "childNodes": [], + "isSVG": true, + "id": 24 + }, + { + "type": 3, + "textContent": "\n ", + "id": 25 + }, + { + "type": 2, + "tagName": "svg", + "attributes": { + "style": "width:200px;height:200px", + "viewBox": "0 0 80 80", + "data-sentry-unblock": "" + }, + "childNodes": [ + { + "type": 2, + "tagName": "path", + "attributes": { + "d": "" + }, + "childNodes": [], + "isSVG": true, + "id": 27 }, - "childNodes": [], - "isSVG": true, - "id": 27 + { + "type": 2, + "tagName": "area", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 28 + }, + { + "type": 2, + "tagName": "rect", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 29 + } + ], + "isSVG": true, + "id": 26 + }, + { + "type": 3, + "textContent": "\n ", + "id": 30 + }, + { + "type": 2, + "tagName": "img", + "attributes": { + "rr_width": "[100-150]px", + "rr_height": "[100-150]px" }, - { - "type": 2, - "tagName": "area", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 28 + "childNodes": [], + "id": 31 + }, + { + "type": 3, + "textContent": "\n ", + "id": 32 + }, + { + "type": 2, + "tagName": "img", + "attributes": { + "data-sentry-unblock": "", + "style": "width:100px;height:100px", + "src": "file:///none.png" }, - { - "type": 2, - "tagName": "rect", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 29 - } - ], - "isSVG": true, - "id": 26 - }, - { - "type": 3, - "textContent": "\n ", - "id": 30 - }, - { - "type": 2, - "tagName": "img", - "attributes": { - "rr_width": "[100-150]px", - "rr_height": "[100-150]px" + "childNodes": [], + "id": 33 }, - "childNodes": [], - "id": 31 - }, - { - "type": 3, - "textContent": "\n ", - "id": 32 - }, - { - "type": 2, - "tagName": "img", - "attributes": { - "data-sentry-unblock": "", - "style": "width:100px;height:100px", - "src": "file:///none.png" + { + "type": 3, + "textContent": "\n ", + "id": 34 + }, + { + "type": 2, + "tagName": "video", + "attributes": { + "rr_width": "[0-50]px", + "rr_height": "[0-50]px" + }, + "childNodes": [], + "id": 35 }, - "childNodes": [], - "id": 33 - }, - { - "type": 3, - "textContent": "\n ", - "id": 34 - }, - { - "type": 2, - "tagName": "video", - "attributes": { - "rr_width": "[0-50]px", - "rr_height": "[0-50]px" + { + "type": 3, + "textContent": "\n ", + "id": 36 }, - "childNodes": [], - "id": 35 - }, - { - "type": 3, - "textContent": "\n ", - "id": 36 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 37 - } - ], - "id": 8 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 3, + "textContent": "\n\n", + "id": 37 + } + ], + "id": 8 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-firefox.json b/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-firefox.json index 11bf6d7a7fa7..f1b55c0884ef 100644 --- a/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-firefox.json +++ b/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-firefox.json @@ -1,276 +1,280 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + }, + { + "type": 2, + "tagName": "link", + "attributes": { + "rr_width": "[0-50]px", + "rr_height": "[0-50]px" + }, + "childNodes": [], + "id": 6 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 7 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 9 }, - "childNodes": [], - "id": 5 - }, - { - "type": 2, - "tagName": "link", - "attributes": { - "rr_width": "[0-50]px", - "rr_height": "[0-50]px" + { + "type": 2, + "tagName": "button", + "attributes": { + "aria-label": "***** **", + "onclick": "console.log('Test log')" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 11 + } + ], + "id": 10 }, - "childNodes": [], - "id": 6 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 7 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 9 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "aria-label": "***** **", - "onclick": "console.log('Test log')" + { + "type": 3, + "textContent": "\n ", + "id": 12 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 11 - } - ], - "id": 10 - }, - { - "type": 3, - "textContent": "\n ", - "id": 12 - }, - { - "type": 2, - "tagName": "div", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "**** ****** ** ****** ** *******", - "id": 14 - } - ], - "id": 13 - }, - { - "type": 3, - "textContent": "\n ", - "id": 15 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "data-sentry-unmask": "" + { + "type": 2, + "tagName": "div", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "**** ****** ** ****** ** *******", + "id": 14 + } + ], + "id": 13 }, - "childNodes": [ - { - "type": 3, - "textContent": "This should be unmasked due to data attribute", - "id": 17 - } - ], - "id": 16 - }, - { - "type": 3, - "textContent": "\n ", - "id": 18 - }, - { - "type": 2, - "tagName": "input", - "attributes": { - "placeholder": "*********** ****** ** ******" + { + "type": 3, + "textContent": "\n ", + "id": 15 }, - "childNodes": [], - "id": 19 - }, - { - "type": 3, - "textContent": "\n ", - "id": 20 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "title": "***** ****** ** ******" + { + "type": 2, + "tagName": "div", + "attributes": { + "data-sentry-unmask": "" + }, + "childNodes": [ + { + "type": 3, + "textContent": "This should be unmasked due to data attribute", + "id": 17 + } + ], + "id": 16 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** ****** ** ******", - "id": 22 - } - ], - "id": 21 - }, - { - "type": 3, - "textContent": "\n ", - "id": 23 - }, - { - "type": 2, - "tagName": "svg", - "attributes": { - "rr_width": "[200-250]px", - "rr_height": "[200-250]px" + { + "type": 3, + "textContent": "\n ", + "id": 18 }, - "childNodes": [], - "isSVG": true, - "id": 24 - }, - { - "type": 3, - "textContent": "\n ", - "id": 25 - }, - { - "type": 2, - "tagName": "svg", - "attributes": { - "style": "width:200px;height:200px", - "viewBox": "0 0 80 80", - "data-sentry-unblock": "" + { + "type": 2, + "tagName": "input", + "attributes": { + "placeholder": "*********** ****** ** ******" + }, + "childNodes": [], + "id": 19 }, - "childNodes": [ - { - "type": 2, - "tagName": "path", - "attributes": { - "d": "" + { + "type": 3, + "textContent": "\n ", + "id": 20 + }, + { + "type": 2, + "tagName": "div", + "attributes": { + "title": "***** ****** ** ******" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** ****** ** ******", + "id": 22 + } + ], + "id": 21 + }, + { + "type": 3, + "textContent": "\n ", + "id": 23 + }, + { + "type": 2, + "tagName": "svg", + "attributes": { + "rr_width": "[200-250]px", + "rr_height": "[200-250]px" + }, + "childNodes": [], + "isSVG": true, + "id": 24 + }, + { + "type": 3, + "textContent": "\n ", + "id": 25 + }, + { + "type": 2, + "tagName": "svg", + "attributes": { + "style": "width:200px;height:200px", + "viewBox": "0 0 80 80", + "data-sentry-unblock": "" + }, + "childNodes": [ + { + "type": 2, + "tagName": "path", + "attributes": { + "d": "" + }, + "childNodes": [], + "isSVG": true, + "id": 27 }, - "childNodes": [], - "isSVG": true, - "id": 27 + { + "type": 2, + "tagName": "area", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 28 + }, + { + "type": 2, + "tagName": "rect", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 29 + } + ], + "isSVG": true, + "id": 26 + }, + { + "type": 3, + "textContent": "\n ", + "id": 30 + }, + { + "type": 2, + "tagName": "img", + "attributes": { + "rr_width": "[100-150]px", + "rr_height": "[100-150]px" }, - { - "type": 2, - "tagName": "area", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 28 + "childNodes": [], + "id": 31 + }, + { + "type": 3, + "textContent": "\n ", + "id": 32 + }, + { + "type": 2, + "tagName": "img", + "attributes": { + "data-sentry-unblock": "", + "style": "width:100px;height:100px", + "src": "file:///none.png" }, - { - "type": 2, - "tagName": "rect", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 29 - } - ], - "isSVG": true, - "id": 26 - }, - { - "type": 3, - "textContent": "\n ", - "id": 30 - }, - { - "type": 2, - "tagName": "img", - "attributes": { - "rr_width": "[100-150]px", - "rr_height": "[100-150]px" + "childNodes": [], + "id": 33 }, - "childNodes": [], - "id": 31 - }, - { - "type": 3, - "textContent": "\n ", - "id": 32 - }, - { - "type": 2, - "tagName": "img", - "attributes": { - "data-sentry-unblock": "", - "style": "width:100px;height:100px", - "src": "file:///none.png" + { + "type": 3, + "textContent": "\n ", + "id": 34 + }, + { + "type": 2, + "tagName": "video", + "attributes": { + "rr_width": "[0-50]px", + "rr_height": "[0-50]px" + }, + "childNodes": [], + "id": 35 }, - "childNodes": [], - "id": 33 - }, - { - "type": 3, - "textContent": "\n ", - "id": 34 - }, - { - "type": 2, - "tagName": "video", - "attributes": { - "rr_width": "[0-50]px", - "rr_height": "[0-50]px" + { + "type": 3, + "textContent": "\n ", + "id": 36 }, - "childNodes": [], - "id": 35 - }, - { - "type": 3, - "textContent": "\n ", - "id": 36 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 37 - } - ], - "id": 8 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 3, + "textContent": "\n\n", + "id": 37 + } + ], + "id": 8 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-webkit.json b/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-webkit.json index 11bf6d7a7fa7..f1b55c0884ef 100644 --- a/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-webkit.json +++ b/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-webkit.json @@ -1,276 +1,280 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + }, + { + "type": 2, + "tagName": "link", + "attributes": { + "rr_width": "[0-50]px", + "rr_height": "[0-50]px" + }, + "childNodes": [], + "id": 6 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 7 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 9 }, - "childNodes": [], - "id": 5 - }, - { - "type": 2, - "tagName": "link", - "attributes": { - "rr_width": "[0-50]px", - "rr_height": "[0-50]px" + { + "type": 2, + "tagName": "button", + "attributes": { + "aria-label": "***** **", + "onclick": "console.log('Test log')" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 11 + } + ], + "id": 10 }, - "childNodes": [], - "id": 6 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 7 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 9 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "aria-label": "***** **", - "onclick": "console.log('Test log')" + { + "type": 3, + "textContent": "\n ", + "id": 12 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 11 - } - ], - "id": 10 - }, - { - "type": 3, - "textContent": "\n ", - "id": 12 - }, - { - "type": 2, - "tagName": "div", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "**** ****** ** ****** ** *******", - "id": 14 - } - ], - "id": 13 - }, - { - "type": 3, - "textContent": "\n ", - "id": 15 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "data-sentry-unmask": "" + { + "type": 2, + "tagName": "div", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "**** ****** ** ****** ** *******", + "id": 14 + } + ], + "id": 13 }, - "childNodes": [ - { - "type": 3, - "textContent": "This should be unmasked due to data attribute", - "id": 17 - } - ], - "id": 16 - }, - { - "type": 3, - "textContent": "\n ", - "id": 18 - }, - { - "type": 2, - "tagName": "input", - "attributes": { - "placeholder": "*********** ****** ** ******" + { + "type": 3, + "textContent": "\n ", + "id": 15 }, - "childNodes": [], - "id": 19 - }, - { - "type": 3, - "textContent": "\n ", - "id": 20 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "title": "***** ****** ** ******" + { + "type": 2, + "tagName": "div", + "attributes": { + "data-sentry-unmask": "" + }, + "childNodes": [ + { + "type": 3, + "textContent": "This should be unmasked due to data attribute", + "id": 17 + } + ], + "id": 16 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** ****** ** ******", - "id": 22 - } - ], - "id": 21 - }, - { - "type": 3, - "textContent": "\n ", - "id": 23 - }, - { - "type": 2, - "tagName": "svg", - "attributes": { - "rr_width": "[200-250]px", - "rr_height": "[200-250]px" + { + "type": 3, + "textContent": "\n ", + "id": 18 }, - "childNodes": [], - "isSVG": true, - "id": 24 - }, - { - "type": 3, - "textContent": "\n ", - "id": 25 - }, - { - "type": 2, - "tagName": "svg", - "attributes": { - "style": "width:200px;height:200px", - "viewBox": "0 0 80 80", - "data-sentry-unblock": "" + { + "type": 2, + "tagName": "input", + "attributes": { + "placeholder": "*********** ****** ** ******" + }, + "childNodes": [], + "id": 19 }, - "childNodes": [ - { - "type": 2, - "tagName": "path", - "attributes": { - "d": "" + { + "type": 3, + "textContent": "\n ", + "id": 20 + }, + { + "type": 2, + "tagName": "div", + "attributes": { + "title": "***** ****** ** ******" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** ****** ** ******", + "id": 22 + } + ], + "id": 21 + }, + { + "type": 3, + "textContent": "\n ", + "id": 23 + }, + { + "type": 2, + "tagName": "svg", + "attributes": { + "rr_width": "[200-250]px", + "rr_height": "[200-250]px" + }, + "childNodes": [], + "isSVG": true, + "id": 24 + }, + { + "type": 3, + "textContent": "\n ", + "id": 25 + }, + { + "type": 2, + "tagName": "svg", + "attributes": { + "style": "width:200px;height:200px", + "viewBox": "0 0 80 80", + "data-sentry-unblock": "" + }, + "childNodes": [ + { + "type": 2, + "tagName": "path", + "attributes": { + "d": "" + }, + "childNodes": [], + "isSVG": true, + "id": 27 }, - "childNodes": [], - "isSVG": true, - "id": 27 + { + "type": 2, + "tagName": "area", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 28 + }, + { + "type": 2, + "tagName": "rect", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 29 + } + ], + "isSVG": true, + "id": 26 + }, + { + "type": 3, + "textContent": "\n ", + "id": 30 + }, + { + "type": 2, + "tagName": "img", + "attributes": { + "rr_width": "[100-150]px", + "rr_height": "[100-150]px" }, - { - "type": 2, - "tagName": "area", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 28 + "childNodes": [], + "id": 31 + }, + { + "type": 3, + "textContent": "\n ", + "id": 32 + }, + { + "type": 2, + "tagName": "img", + "attributes": { + "data-sentry-unblock": "", + "style": "width:100px;height:100px", + "src": "file:///none.png" }, - { - "type": 2, - "tagName": "rect", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 29 - } - ], - "isSVG": true, - "id": 26 - }, - { - "type": 3, - "textContent": "\n ", - "id": 30 - }, - { - "type": 2, - "tagName": "img", - "attributes": { - "rr_width": "[100-150]px", - "rr_height": "[100-150]px" + "childNodes": [], + "id": 33 }, - "childNodes": [], - "id": 31 - }, - { - "type": 3, - "textContent": "\n ", - "id": 32 - }, - { - "type": 2, - "tagName": "img", - "attributes": { - "data-sentry-unblock": "", - "style": "width:100px;height:100px", - "src": "file:///none.png" + { + "type": 3, + "textContent": "\n ", + "id": 34 + }, + { + "type": 2, + "tagName": "video", + "attributes": { + "rr_width": "[0-50]px", + "rr_height": "[0-50]px" + }, + "childNodes": [], + "id": 35 }, - "childNodes": [], - "id": 33 - }, - { - "type": 3, - "textContent": "\n ", - "id": 34 - }, - { - "type": 2, - "tagName": "video", - "attributes": { - "rr_width": "[0-50]px", - "rr_height": "[0-50]px" + { + "type": 3, + "textContent": "\n ", + "id": 36 }, - "childNodes": [], - "id": 35 - }, - { - "type": 3, - "textContent": "\n ", - "id": 36 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 37 - } - ], - "id": 8 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 3, + "textContent": "\n\n", + "id": 37 + } + ], + "id": 8 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy.json b/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy.json index 11bf6d7a7fa7..f1b55c0884ef 100644 --- a/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy.json +++ b/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy.json @@ -1,276 +1,280 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + }, + { + "type": 2, + "tagName": "link", + "attributes": { + "rr_width": "[0-50]px", + "rr_height": "[0-50]px" + }, + "childNodes": [], + "id": 6 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 7 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 9 }, - "childNodes": [], - "id": 5 - }, - { - "type": 2, - "tagName": "link", - "attributes": { - "rr_width": "[0-50]px", - "rr_height": "[0-50]px" + { + "type": 2, + "tagName": "button", + "attributes": { + "aria-label": "***** **", + "onclick": "console.log('Test log')" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 11 + } + ], + "id": 10 }, - "childNodes": [], - "id": 6 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 7 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 9 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "aria-label": "***** **", - "onclick": "console.log('Test log')" + { + "type": 3, + "textContent": "\n ", + "id": 12 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 11 - } - ], - "id": 10 - }, - { - "type": 3, - "textContent": "\n ", - "id": 12 - }, - { - "type": 2, - "tagName": "div", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "**** ****** ** ****** ** *******", - "id": 14 - } - ], - "id": 13 - }, - { - "type": 3, - "textContent": "\n ", - "id": 15 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "data-sentry-unmask": "" + { + "type": 2, + "tagName": "div", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "**** ****** ** ****** ** *******", + "id": 14 + } + ], + "id": 13 }, - "childNodes": [ - { - "type": 3, - "textContent": "This should be unmasked due to data attribute", - "id": 17 - } - ], - "id": 16 - }, - { - "type": 3, - "textContent": "\n ", - "id": 18 - }, - { - "type": 2, - "tagName": "input", - "attributes": { - "placeholder": "*********** ****** ** ******" + { + "type": 3, + "textContent": "\n ", + "id": 15 }, - "childNodes": [], - "id": 19 - }, - { - "type": 3, - "textContent": "\n ", - "id": 20 - }, - { - "type": 2, - "tagName": "div", - "attributes": { - "title": "***** ****** ** ******" + { + "type": 2, + "tagName": "div", + "attributes": { + "data-sentry-unmask": "" + }, + "childNodes": [ + { + "type": 3, + "textContent": "This should be unmasked due to data attribute", + "id": 17 + } + ], + "id": 16 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** ****** ** ******", - "id": 22 - } - ], - "id": 21 - }, - { - "type": 3, - "textContent": "\n ", - "id": 23 - }, - { - "type": 2, - "tagName": "svg", - "attributes": { - "rr_width": "[200-250]px", - "rr_height": "[200-250]px" + { + "type": 3, + "textContent": "\n ", + "id": 18 }, - "childNodes": [], - "isSVG": true, - "id": 24 - }, - { - "type": 3, - "textContent": "\n ", - "id": 25 - }, - { - "type": 2, - "tagName": "svg", - "attributes": { - "style": "width:200px;height:200px", - "viewBox": "0 0 80 80", - "data-sentry-unblock": "" + { + "type": 2, + "tagName": "input", + "attributes": { + "placeholder": "*********** ****** ** ******" + }, + "childNodes": [], + "id": 19 }, - "childNodes": [ - { - "type": 2, - "tagName": "path", - "attributes": { - "d": "" + { + "type": 3, + "textContent": "\n ", + "id": 20 + }, + { + "type": 2, + "tagName": "div", + "attributes": { + "title": "***** ****** ** ******" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** ****** ** ******", + "id": 22 + } + ], + "id": 21 + }, + { + "type": 3, + "textContent": "\n ", + "id": 23 + }, + { + "type": 2, + "tagName": "svg", + "attributes": { + "rr_width": "[200-250]px", + "rr_height": "[200-250]px" + }, + "childNodes": [], + "isSVG": true, + "id": 24 + }, + { + "type": 3, + "textContent": "\n ", + "id": 25 + }, + { + "type": 2, + "tagName": "svg", + "attributes": { + "style": "width:200px;height:200px", + "viewBox": "0 0 80 80", + "data-sentry-unblock": "" + }, + "childNodes": [ + { + "type": 2, + "tagName": "path", + "attributes": { + "d": "" + }, + "childNodes": [], + "isSVG": true, + "id": 27 }, - "childNodes": [], - "isSVG": true, - "id": 27 + { + "type": 2, + "tagName": "area", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 28 + }, + { + "type": 2, + "tagName": "rect", + "attributes": {}, + "childNodes": [], + "isSVG": true, + "id": 29 + } + ], + "isSVG": true, + "id": 26 + }, + { + "type": 3, + "textContent": "\n ", + "id": 30 + }, + { + "type": 2, + "tagName": "img", + "attributes": { + "rr_width": "[100-150]px", + "rr_height": "[100-150]px" }, - { - "type": 2, - "tagName": "area", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 28 + "childNodes": [], + "id": 31 + }, + { + "type": 3, + "textContent": "\n ", + "id": 32 + }, + { + "type": 2, + "tagName": "img", + "attributes": { + "data-sentry-unblock": "", + "style": "width:100px;height:100px", + "src": "file:///none.png" }, - { - "type": 2, - "tagName": "rect", - "attributes": {}, - "childNodes": [], - "isSVG": true, - "id": 29 - } - ], - "isSVG": true, - "id": 26 - }, - { - "type": 3, - "textContent": "\n ", - "id": 30 - }, - { - "type": 2, - "tagName": "img", - "attributes": { - "rr_width": "[100-150]px", - "rr_height": "[100-150]px" + "childNodes": [], + "id": 33 }, - "childNodes": [], - "id": 31 - }, - { - "type": 3, - "textContent": "\n ", - "id": 32 - }, - { - "type": 2, - "tagName": "img", - "attributes": { - "data-sentry-unblock": "", - "style": "width:100px;height:100px", - "src": "file:///none.png" + { + "type": 3, + "textContent": "\n ", + "id": 34 + }, + { + "type": 2, + "tagName": "video", + "attributes": { + "rr_width": "[0-50]px", + "rr_height": "[0-50]px" + }, + "childNodes": [], + "id": 35 }, - "childNodes": [], - "id": 33 - }, - { - "type": 3, - "textContent": "\n ", - "id": 34 - }, - { - "type": 2, - "tagName": "video", - "attributes": { - "rr_width": "[0-50]px", - "rr_height": "[0-50]px" + { + "type": 3, + "textContent": "\n ", + "id": 36 }, - "childNodes": [], - "id": 35 - }, - { - "type": 3, - "textContent": "\n ", - "id": 36 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 37 - } - ], - "id": 8 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 3, + "textContent": "\n\n", + "id": 37 + } + ], + "id": 8 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionExpiry/test.ts b/packages/integration-tests/suites/replay/sessionExpiry/test.ts index 38927478dea6..c574ac570ec6 100644 --- a/packages/integration-tests/suites/replay/sessionExpiry/test.ts +++ b/packages/integration-tests/suites/replay/sessionExpiry/test.ts @@ -4,7 +4,6 @@ import { sentryTest } from '../../../utils/fixtures'; import { getExpectedReplayEvent } from '../../../utils/replayEventTemplates'; import { getFullRecordingSnapshots, - getIncrementalRecordingSnapshots, getReplayEvent, getReplaySnapshot, normalize, @@ -53,29 +52,6 @@ sentryTest('handles an expired session RUN', async ({ getLocalTestPath, page }) const replayEvent1 = getReplayEvent(req1); expect(replayEvent1).toEqual(getExpectedReplayEvent({ replay_start_timestamp: undefined, segment_id: 1, urls: [] })); - const fullSnapshots1 = getFullRecordingSnapshots(req1); - expect(fullSnapshots1.length).toEqual(0); - - const incrementalSnapshots1 = getIncrementalRecordingSnapshots(req1); - // The number of incremental snapshots depends on the browser - expect(incrementalSnapshots1.length).toBeGreaterThanOrEqual(4); - - expect(incrementalSnapshots1).toEqual( - expect.arrayContaining([ - { - source: 1, - positions: [ - { - id: 9, - timeOffset: expect.any(Number), - x: expect.any(Number), - y: expect.any(Number), - }, - ], - }, - ]), - ); - const replay = await getReplaySnapshot(page); const oldSessionId = replay.session?.id; diff --git a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-chromium.json b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-chromium.json index a4ad4ac4d60a..d510b410a343 100644 --- a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-chromium.json +++ b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-chromium.json @@ -1,109 +1,113 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 1')", - "id": "button1" + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 2')", - "id": "button2" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-firefox.json b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-firefox.json index a4ad4ac4d60a..d510b410a343 100644 --- a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-firefox.json +++ b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-firefox.json @@ -1,109 +1,113 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 1')", - "id": "button1" + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 2')", - "id": "button2" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-webkit.json b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-webkit.json index a4ad4ac4d60a..d510b410a343 100644 --- a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-webkit.json +++ b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0-webkit.json @@ -1,109 +1,113 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 1')", - "id": "button1" + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 2')", - "id": "button2" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0.json b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0.json index a4ad4ac4d60a..d510b410a343 100644 --- a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0.json +++ b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-0.json @@ -1,109 +1,113 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 1')", - "id": "button1" + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 2')", - "id": "button2" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-chromium.json b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-chromium.json index a4ad4ac4d60a..d510b410a343 100644 --- a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-chromium.json +++ b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-chromium.json @@ -1,109 +1,113 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 1')", - "id": "button1" + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 2')", - "id": "button2" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-firefox.json b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-firefox.json index a4ad4ac4d60a..d510b410a343 100644 --- a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-firefox.json +++ b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-firefox.json @@ -1,109 +1,113 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 1')", - "id": "button1" + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 2')", - "id": "button2" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-webkit.json b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-webkit.json index a4ad4ac4d60a..d510b410a343 100644 --- a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-webkit.json +++ b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2-webkit.json @@ -1,109 +1,113 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 1')", - "id": "button1" + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 2')", - "id": "button2" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2.json b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2.json index a4ad4ac4d60a..d510b410a343 100644 --- a/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2.json +++ b/packages/integration-tests/suites/replay/sessionExpiry/test.ts-snapshots/snapshot-2.json @@ -1,109 +1,113 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 1')", - "id": "button1" + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 2')", - "id": "button2" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-chromium.json b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-chromium.json index a4ad4ac4d60a..d510b410a343 100644 --- a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-chromium.json +++ b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-chromium.json @@ -1,109 +1,113 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 1')", - "id": "button1" + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 2')", - "id": "button2" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-firefox.json b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-firefox.json index a4ad4ac4d60a..d510b410a343 100644 --- a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-firefox.json +++ b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-firefox.json @@ -1,109 +1,113 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 1')", - "id": "button1" + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 2')", - "id": "button2" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-webkit.json b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-webkit.json index a4ad4ac4d60a..d510b410a343 100644 --- a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-webkit.json +++ b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0-webkit.json @@ -1,109 +1,113 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 1')", - "id": "button1" + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 2')", - "id": "button2" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0.json b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0.json index a4ad4ac4d60a..d510b410a343 100644 --- a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0.json +++ b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-0.json @@ -1,109 +1,113 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 1')", - "id": "button1" + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 2')", - "id": "button2" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-chromium.json b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-chromium.json index a4ad4ac4d60a..d510b410a343 100644 --- a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-chromium.json +++ b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-chromium.json @@ -1,109 +1,113 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 1')", - "id": "button1" + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 2')", - "id": "button2" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-firefox.json b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-firefox.json index a4ad4ac4d60a..d510b410a343 100644 --- a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-firefox.json +++ b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-firefox.json @@ -1,109 +1,113 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 1')", - "id": "button1" + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 2')", - "id": "button2" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-webkit.json b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-webkit.json index a4ad4ac4d60a..d510b410a343 100644 --- a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-webkit.json +++ b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1-webkit.json @@ -1,109 +1,113 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 1')", - "id": "button1" + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 2')", - "id": "button2" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1.json b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1.json index a4ad4ac4d60a..d510b410a343 100644 --- a/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1.json +++ b/packages/integration-tests/suites/replay/sessionInactive/test.ts-snapshots/snapshot-1.json @@ -1,109 +1,113 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 1')", - "id": "button1" + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "onclick": "console.log('Test log 2')", - "id": "button2" + { + "type": 3, + "textContent": "\n ", + "id": 11 }, - "childNodes": [ - { - "type": 3, - "textContent": "***** **", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n ", - "id": 14 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 15 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/unicode/compressed/test.ts-snapshots/unicode-compressed-chromium.json b/packages/integration-tests/suites/replay/unicode/compressed/test.ts-snapshots/unicode-compressed-chromium.json index 1ffd71d178d8..12e2147fa515 100644 --- a/packages/integration-tests/suites/replay/unicode/compressed/test.ts-snapshots/unicode-compressed-chromium.json +++ b/packages/integration-tests/suites/replay/unicode/compressed/test.ts-snapshots/unicode-compressed-chromium.json @@ -1,123 +1,127 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "h1", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "Hi 👋👋👋", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "p", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n Adding some unicode characters to the page to make sure they are properly handled. At sentry, we like 🚢🚢🚢. We\n also like 🍕, 🍺 and 🐕. (Some people might actually prefer 🐈‍⬛ but the test author is a dog person, so 🤷‍♂️).\n ", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n\n ", - "id": 14 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "id": "go-background" + { + "type": 2, + "tagName": "h1", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "Hi 👋👋👋", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "✅ Acknowledge", - "id": 16 - } - ], - "id": 15 - }, - { - "type": 3, - "textContent": "\n ", - "id": 17 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 18 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "p", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n Adding some unicode characters to the page to make sure they are properly handled. At sentry, we like 🚢🚢🚢. We\n also like 🍕, 🍺 and 🐕. (Some people might actually prefer 🐈‍⬛ but the test author is a dog person, so 🤷‍♂️).\n ", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n\n ", + "id": 14 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "id": "go-background" + }, + "childNodes": [ + { + "type": 3, + "textContent": "✅ Acknowledge", + "id": 16 + } + ], + "id": 15 + }, + { + "type": 3, + "textContent": "\n ", + "id": 17 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 18 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/unicode/compressed/test.ts-snapshots/unicode-compressed-firefox.json b/packages/integration-tests/suites/replay/unicode/compressed/test.ts-snapshots/unicode-compressed-firefox.json index 1ffd71d178d8..12e2147fa515 100644 --- a/packages/integration-tests/suites/replay/unicode/compressed/test.ts-snapshots/unicode-compressed-firefox.json +++ b/packages/integration-tests/suites/replay/unicode/compressed/test.ts-snapshots/unicode-compressed-firefox.json @@ -1,123 +1,127 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "h1", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "Hi 👋👋👋", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "p", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n Adding some unicode characters to the page to make sure they are properly handled. At sentry, we like 🚢🚢🚢. We\n also like 🍕, 🍺 and 🐕. (Some people might actually prefer 🐈‍⬛ but the test author is a dog person, so 🤷‍♂️).\n ", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n\n ", - "id": 14 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "id": "go-background" + { + "type": 2, + "tagName": "h1", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "Hi 👋👋👋", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "✅ Acknowledge", - "id": 16 - } - ], - "id": 15 - }, - { - "type": 3, - "textContent": "\n ", - "id": 17 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 18 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "p", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n Adding some unicode characters to the page to make sure they are properly handled. At sentry, we like 🚢🚢🚢. We\n also like 🍕, 🍺 and 🐕. (Some people might actually prefer 🐈‍⬛ but the test author is a dog person, so 🤷‍♂️).\n ", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n\n ", + "id": 14 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "id": "go-background" + }, + "childNodes": [ + { + "type": 3, + "textContent": "✅ Acknowledge", + "id": 16 + } + ], + "id": 15 + }, + { + "type": 3, + "textContent": "\n ", + "id": 17 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 18 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/unicode/compressed/test.ts-snapshots/unicode-compressed-webkit.json b/packages/integration-tests/suites/replay/unicode/compressed/test.ts-snapshots/unicode-compressed-webkit.json index 1ffd71d178d8..12e2147fa515 100644 --- a/packages/integration-tests/suites/replay/unicode/compressed/test.ts-snapshots/unicode-compressed-webkit.json +++ b/packages/integration-tests/suites/replay/unicode/compressed/test.ts-snapshots/unicode-compressed-webkit.json @@ -1,123 +1,127 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "h1", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "Hi 👋👋👋", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "p", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n Adding some unicode characters to the page to make sure they are properly handled. At sentry, we like 🚢🚢🚢. We\n also like 🍕, 🍺 and 🐕. (Some people might actually prefer 🐈‍⬛ but the test author is a dog person, so 🤷‍♂️).\n ", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n\n ", - "id": 14 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "id": "go-background" + { + "type": 2, + "tagName": "h1", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "Hi 👋👋👋", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "✅ Acknowledge", - "id": 16 - } - ], - "id": 15 - }, - { - "type": 3, - "textContent": "\n ", - "id": 17 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 18 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "p", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n Adding some unicode characters to the page to make sure they are properly handled. At sentry, we like 🚢🚢🚢. We\n also like 🍕, 🍺 and 🐕. (Some people might actually prefer 🐈‍⬛ but the test author is a dog person, so 🤷‍♂️).\n ", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n\n ", + "id": 14 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "id": "go-background" + }, + "childNodes": [ + { + "type": 3, + "textContent": "✅ Acknowledge", + "id": 16 + } + ], + "id": 15 + }, + { + "type": 3, + "textContent": "\n ", + "id": 17 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 18 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/unicode/compressed/test.ts-snapshots/unicode-compressed.json b/packages/integration-tests/suites/replay/unicode/compressed/test.ts-snapshots/unicode-compressed.json index 1ffd71d178d8..12e2147fa515 100644 --- a/packages/integration-tests/suites/replay/unicode/compressed/test.ts-snapshots/unicode-compressed.json +++ b/packages/integration-tests/suites/replay/unicode/compressed/test.ts-snapshots/unicode-compressed.json @@ -1,123 +1,127 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "h1", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "Hi 👋👋👋", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "p", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n Adding some unicode characters to the page to make sure they are properly handled. At sentry, we like 🚢🚢🚢. We\n also like 🍕, 🍺 and 🐕. (Some people might actually prefer 🐈‍⬛ but the test author is a dog person, so 🤷‍♂️).\n ", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n\n ", - "id": 14 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "id": "go-background" + { + "type": 2, + "tagName": "h1", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "Hi 👋👋👋", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "✅ Acknowledge", - "id": 16 - } - ], - "id": 15 - }, - { - "type": 3, - "textContent": "\n ", - "id": 17 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 18 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "p", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n Adding some unicode characters to the page to make sure they are properly handled. At sentry, we like 🚢🚢🚢. We\n also like 🍕, 🍺 and 🐕. (Some people might actually prefer 🐈‍⬛ but the test author is a dog person, so 🤷‍♂️).\n ", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n\n ", + "id": 14 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "id": "go-background" + }, + "childNodes": [ + { + "type": 3, + "textContent": "✅ Acknowledge", + "id": 16 + } + ], + "id": 15 + }, + { + "type": 3, + "textContent": "\n ", + "id": 17 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 18 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/unicode/uncompressed/test.ts-snapshots/unicode-uncompressed-chromium.json b/packages/integration-tests/suites/replay/unicode/uncompressed/test.ts-snapshots/unicode-uncompressed-chromium.json index 1ffd71d178d8..12e2147fa515 100644 --- a/packages/integration-tests/suites/replay/unicode/uncompressed/test.ts-snapshots/unicode-uncompressed-chromium.json +++ b/packages/integration-tests/suites/replay/unicode/uncompressed/test.ts-snapshots/unicode-uncompressed-chromium.json @@ -1,123 +1,127 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "h1", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "Hi 👋👋👋", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "p", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n Adding some unicode characters to the page to make sure they are properly handled. At sentry, we like 🚢🚢🚢. We\n also like 🍕, 🍺 and 🐕. (Some people might actually prefer 🐈‍⬛ but the test author is a dog person, so 🤷‍♂️).\n ", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n\n ", - "id": 14 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "id": "go-background" + { + "type": 2, + "tagName": "h1", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "Hi 👋👋👋", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "✅ Acknowledge", - "id": 16 - } - ], - "id": 15 - }, - { - "type": 3, - "textContent": "\n ", - "id": 17 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 18 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "p", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n Adding some unicode characters to the page to make sure they are properly handled. At sentry, we like 🚢🚢🚢. We\n also like 🍕, 🍺 and 🐕. (Some people might actually prefer 🐈‍⬛ but the test author is a dog person, so 🤷‍♂️).\n ", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n\n ", + "id": 14 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "id": "go-background" + }, + "childNodes": [ + { + "type": 3, + "textContent": "✅ Acknowledge", + "id": 16 + } + ], + "id": 15 + }, + { + "type": 3, + "textContent": "\n ", + "id": 17 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 18 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/unicode/uncompressed/test.ts-snapshots/unicode-uncompressed-firefox.json b/packages/integration-tests/suites/replay/unicode/uncompressed/test.ts-snapshots/unicode-uncompressed-firefox.json index 1ffd71d178d8..12e2147fa515 100644 --- a/packages/integration-tests/suites/replay/unicode/uncompressed/test.ts-snapshots/unicode-uncompressed-firefox.json +++ b/packages/integration-tests/suites/replay/unicode/uncompressed/test.ts-snapshots/unicode-uncompressed-firefox.json @@ -1,123 +1,127 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "h1", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "Hi 👋👋👋", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "p", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n Adding some unicode characters to the page to make sure they are properly handled. At sentry, we like 🚢🚢🚢. We\n also like 🍕, 🍺 and 🐕. (Some people might actually prefer 🐈‍⬛ but the test author is a dog person, so 🤷‍♂️).\n ", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n\n ", - "id": 14 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "id": "go-background" + { + "type": 2, + "tagName": "h1", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "Hi 👋👋👋", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "✅ Acknowledge", - "id": 16 - } - ], - "id": 15 - }, - { - "type": 3, - "textContent": "\n ", - "id": 17 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 18 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "p", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n Adding some unicode characters to the page to make sure they are properly handled. At sentry, we like 🚢🚢🚢. We\n also like 🍕, 🍺 and 🐕. (Some people might actually prefer 🐈‍⬛ but the test author is a dog person, so 🤷‍♂️).\n ", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n\n ", + "id": 14 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "id": "go-background" + }, + "childNodes": [ + { + "type": 3, + "textContent": "✅ Acknowledge", + "id": 16 + } + ], + "id": 15 + }, + { + "type": 3, + "textContent": "\n ", + "id": 17 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 18 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/unicode/uncompressed/test.ts-snapshots/unicode-uncompressed-webkit.json b/packages/integration-tests/suites/replay/unicode/uncompressed/test.ts-snapshots/unicode-uncompressed-webkit.json index 1ffd71d178d8..12e2147fa515 100644 --- a/packages/integration-tests/suites/replay/unicode/uncompressed/test.ts-snapshots/unicode-uncompressed-webkit.json +++ b/packages/integration-tests/suites/replay/unicode/uncompressed/test.ts-snapshots/unicode-uncompressed-webkit.json @@ -1,123 +1,127 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "h1", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "Hi 👋👋👋", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "p", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n Adding some unicode characters to the page to make sure they are properly handled. At sentry, we like 🚢🚢🚢. We\n also like 🍕, 🍺 and 🐕. (Some people might actually prefer 🐈‍⬛ but the test author is a dog person, so 🤷‍♂️).\n ", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n\n ", - "id": 14 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "id": "go-background" + { + "type": 2, + "tagName": "h1", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "Hi 👋👋👋", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "✅ Acknowledge", - "id": 16 - } - ], - "id": 15 - }, - { - "type": 3, - "textContent": "\n ", - "id": 17 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 18 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "p", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n Adding some unicode characters to the page to make sure they are properly handled. At sentry, we like 🚢🚢🚢. We\n also like 🍕, 🍺 and 🐕. (Some people might actually prefer 🐈‍⬛ but the test author is a dog person, so 🤷‍♂️).\n ", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n\n ", + "id": 14 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "id": "go-background" + }, + "childNodes": [ + { + "type": 3, + "textContent": "✅ Acknowledge", + "id": 16 + } + ], + "id": 15 + }, + { + "type": 3, + "textContent": "\n ", + "id": 17 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 18 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/unicode/uncompressed/test.ts-snapshots/unicode-uncompressed.json b/packages/integration-tests/suites/replay/unicode/uncompressed/test.ts-snapshots/unicode-uncompressed.json index 1ffd71d178d8..12e2147fa515 100644 --- a/packages/integration-tests/suites/replay/unicode/uncompressed/test.ts-snapshots/unicode-uncompressed.json +++ b/packages/integration-tests/suites/replay/unicode/uncompressed/test.ts-snapshots/unicode-uncompressed.json @@ -1,123 +1,127 @@ { - "node": { - "type": 0, - "childNodes": [ - { - "type": 1, - "name": "html", - "publicId": "", - "systemId": "", - "id": 2 - }, - { - "type": 2, - "tagName": "html", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "head", - "attributes": {}, - "childNodes": [ - { - "type": 2, - "tagName": "meta", - "attributes": { - "charset": "utf-8" + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 }, - "childNodes": [], - "id": 5 - } - ], - "id": 4 - }, - { - "type": 3, - "textContent": "\n ", - "id": 6 - }, - { - "type": 2, - "tagName": "body", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n ", - "id": 8 - }, - { - "type": 2, - "tagName": "h1", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "Hi 👋👋👋", - "id": 10 - } - ], - "id": 9 - }, - { - "type": 3, - "textContent": "\n ", - "id": 11 - }, - { - "type": 2, - "tagName": "p", - "attributes": {}, - "childNodes": [ - { - "type": 3, - "textContent": "\n Adding some unicode characters to the page to make sure they are properly handled. At sentry, we like 🚢🚢🚢. We\n also like 🍕, 🍺 and 🐕. (Some people might actually prefer 🐈‍⬛ but the test author is a dog person, so 🤷‍♂️).\n ", - "id": 13 - } - ], - "id": 12 - }, - { - "type": 3, - "textContent": "\n\n ", - "id": 14 - }, - { - "type": 2, - "tagName": "button", - "attributes": { - "id": "go-background" + { + "type": 2, + "tagName": "h1", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "Hi 👋👋👋", + "id": 10 + } + ], + "id": 9 }, - "childNodes": [ - { - "type": 3, - "textContent": "✅ Acknowledge", - "id": 16 - } - ], - "id": 15 - }, - { - "type": 3, - "textContent": "\n ", - "id": 17 - }, - { - "type": 3, - "textContent": "\n\n", - "id": 18 - } - ], - "id": 7 - } - ], - "id": 3 - } - ], - "id": 1 + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "p", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n Adding some unicode characters to the page to make sure they are properly handled. At sentry, we like 🚢🚢🚢. We\n also like 🍕, 🍺 and 🐕. (Some people might actually prefer 🐈‍⬛ but the test author is a dog person, so 🤷‍♂️).\n ", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n\n ", + "id": 14 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "id": "go-background" + }, + "childNodes": [ + { + "type": 3, + "textContent": "✅ Acknowledge", + "id": 16 + } + ], + "id": 15 + }, + { + "type": 3, + "textContent": "\n ", + "id": 17 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 18 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } }, - "initialOffset": { - "left": 0, - "top": 0 - } + "timestamp": [timestamp] } \ No newline at end of file diff --git a/packages/integration-tests/utils/replayHelpers.ts b/packages/integration-tests/utils/replayHelpers.ts index b68e74708916..a4dd02c068a4 100644 --- a/packages/integration-tests/utils/replayHelpers.ts +++ b/packages/integration-tests/utils/replayHelpers.ts @@ -1,4 +1,5 @@ import type { RecordingEvent, ReplayContainer } from '@sentry/replay/build/npm/types/types'; +import type { eventWithTime } from '@sentry/replay/build/npm/types/types/rrweb'; import type { Breadcrumb, Event, ReplayEvent } from '@sentry/types'; import pako from 'pako'; import type { Page, Request, Response } from 'playwright'; @@ -14,15 +15,8 @@ export type PerformanceSpan = { data: Record; }; -export type RecordingSnapshot = { - node: SnapshotNode; - initialOffset: number; -}; - -type SnapshotNode = { - type: number; - id: number; - childNodes: SnapshotNode[]; +type RecordingSnapshot = eventWithTime & { + timestamp: 0; }; /** @@ -134,19 +128,29 @@ function getReplayPerformanceSpans(recordingEvents: RecordingEvent[]): Performan export function getFullRecordingSnapshots(resOrReq: Request | Response): RecordingSnapshot[] { const replayRequest = getRequest(resOrReq); - const events = getDecompressedRecordingEvents(replayRequest) as RecordingEvent[]; - return events.filter(event => event.type === 2).map(event => event.data as RecordingSnapshot); + const events = getDecompressedRecordingEvents(replayRequest); + return events.filter(event => event.type === 2); } export function getIncrementalRecordingSnapshots(resOrReq: Request | Response): RecordingSnapshot[] { const replayRequest = getRequest(resOrReq); - const events = getDecompressedRecordingEvents(replayRequest) as RecordingEvent[]; - return events.filter(event => event.type === 3).map(event => event.data as RecordingSnapshot); + const events = getDecompressedRecordingEvents(replayRequest); + return events.filter(event => event.type === 3); } -function getDecompressedRecordingEvents(resOrReq: Request | Response): RecordingEvent[] { +function getDecompressedRecordingEvents(resOrReq: Request | Response): RecordingSnapshot[] { const replayRequest = getRequest(resOrReq); - return replayEnvelopeRequestParser(replayRequest, 5) as RecordingEvent[]; + return ( + (replayEnvelopeRequestParser(replayRequest, 5) as eventWithTime[]) + .sort((a, b) => a.timestamp - b.timestamp) + // source 1 is MouseMove, which is a bit flaky and we don't care about + .filter( + event => typeof event.data === 'object' && event.data && (event.data as Record).source !== 1, + ) + .map(event => { + return { ...event, timestamp: 0 }; + }) + ); } export function getReplayRecordingContent(resOrReq: Request | Response): RecordingContent { @@ -231,7 +235,8 @@ export function normalize( const rawString = JSON.stringify(obj, null, 2); let normalizedString = rawString .replace(/"file:\/\/.+(\/.*\.html)"/gm, '"$1"') - .replace(/"timeOffset":\s*-?\d+/gm, '"timeOffset": [timeOffset]'); + .replace(/"timeOffset":\s*-?\d+/gm, '"timeOffset": [timeOffset]') + .replace(/"timestamp":\s*0/gm, '"timestamp": [timestamp]'); if (normalizeNumberAttributes?.length) { // We look for: "attr": "123px", "123", "123%", "123em", "123rem" From 148dd43b8b67ea13fc6a39e4aa7f693900f1b09e Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Tue, 7 Mar 2023 15:26:48 +0100 Subject: [PATCH 26/44] chore(sveltekit): Add boilerplate SvelteKit SDK package (#7365) Add the usual files for a new package, a few dependencies as well as craft/publish config entries to keep the package from being published accidentally for now. --- .craft.yml | 1 + package.json | 1 + .../e2e-tests/verdaccio-config/config.yaml | 6 + packages/sveltekit/.eslintrc.js | 7 + packages/sveltekit/LICENSE | 14 + packages/sveltekit/README.md | 32 ++ packages/sveltekit/jest.config.js | 3 + packages/sveltekit/package.json | 58 ++++ packages/sveltekit/rollup.npm.config.js | 14 + packages/sveltekit/src/client/index.ts | 4 + packages/sveltekit/src/index.client.ts | 7 + packages/sveltekit/src/index.server.ts | 9 + packages/sveltekit/src/index.types.ts | 25 ++ packages/sveltekit/src/server/index.ts | 4 + packages/sveltekit/test/index.test.ts | 12 + packages/sveltekit/tsconfig.json | 9 + packages/sveltekit/tsconfig.test.json | 10 + packages/sveltekit/tsconfig.types.json | 10 + scripts/node-unit-tests.ts | 12 +- yarn.lock | 303 +++++++++++++++++- 20 files changed, 535 insertions(+), 6 deletions(-) create mode 100644 packages/sveltekit/.eslintrc.js create mode 100644 packages/sveltekit/LICENSE create mode 100644 packages/sveltekit/README.md create mode 100644 packages/sveltekit/jest.config.js create mode 100644 packages/sveltekit/package.json create mode 100644 packages/sveltekit/rollup.npm.config.js create mode 100644 packages/sveltekit/src/client/index.ts create mode 100644 packages/sveltekit/src/index.client.ts create mode 100644 packages/sveltekit/src/index.server.ts create mode 100644 packages/sveltekit/src/index.types.ts create mode 100644 packages/sveltekit/src/server/index.ts create mode 100644 packages/sveltekit/test/index.test.ts create mode 100644 packages/sveltekit/tsconfig.json create mode 100644 packages/sveltekit/tsconfig.test.json create mode 100644 packages/sveltekit/tsconfig.types.json diff --git a/.craft.yml b/.craft.yml index bf775c7a276a..c21726412f60 100644 --- a/.craft.yml +++ b/.craft.yml @@ -22,6 +22,7 @@ targets: - name: github includeNames: /^sentry-.*$/ - name: npm + excludeNames: /^sentry-sveltekit-.*$/ - name: registry sdks: 'npm:@sentry/browser': diff --git a/package.json b/package.json index f44c07492703..d106efb1743d 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "packages/replay-worker", "packages/serverless", "packages/svelte", + "packages/sveltekit", "packages/tracing", "packages/types", "packages/typescript", diff --git a/packages/e2e-tests/verdaccio-config/config.yaml b/packages/e2e-tests/verdaccio-config/config.yaml index efcf65968273..a5b4f7919cc8 100644 --- a/packages/e2e-tests/verdaccio-config/config.yaml +++ b/packages/e2e-tests/verdaccio-config/config.yaml @@ -128,6 +128,12 @@ packages: unpublish: $all # proxy: npmjs # Don't proxy for E2E tests! + '@sentry/sveltekit': + access: $all + publish: $all + unpublish: $all + # proxy: npmjs # Don't proxy for E2E tests! + '@sentry/tracing': access: $all publish: $all diff --git a/packages/sveltekit/.eslintrc.js b/packages/sveltekit/.eslintrc.js new file mode 100644 index 000000000000..2d614f46733b --- /dev/null +++ b/packages/sveltekit/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + env: { + browser: true, + node: true, + }, + extends: ['../../.eslintrc.js'], +}; diff --git a/packages/sveltekit/LICENSE b/packages/sveltekit/LICENSE new file mode 100644 index 000000000000..d11896ba1181 --- /dev/null +++ b/packages/sveltekit/LICENSE @@ -0,0 +1,14 @@ +Copyright (c) 2023 Sentry (https://sentry.io) and individual contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/sveltekit/README.md b/packages/sveltekit/README.md new file mode 100644 index 000000000000..bb0206a72ac4 --- /dev/null +++ b/packages/sveltekit/README.md @@ -0,0 +1,32 @@ +

+ + Sentry + +

+ +# Official Sentry SDK for SvelteKit + +[![npm version](https://img.shields.io/npm/v/@sentry/sveltekit.svg)](https://www.npmjs.com/package/@sentry/sveltekit) +[![npm dm](https://img.shields.io/npm/dm/@sentry/sveltekit.svg)](https://www.npmjs.com/package/@sentry/sveltekit) +[![npm dt](https://img.shields.io/npm/dt/@sentry/sveltekit.svg)](https://www.npmjs.com/package/@sentry/sveltekit) + + + +## SDK Status + +This SDK is currently in **Alpha state** and we're still experimenting with APIs and functionality. We therefore make no guarantees in terms of semver or breaking changes. If you want to try this SDK and come across a problem, please open a [GitHub Issue](https://github.com/getsentry/sentry-javascript/issues/new/choose). + +## Compatibility + +Currently, the minimum supported version of SvelteKit is `1.0.0`. + +## General + +This package is a wrapper around `@sentry/node` for the server and `@sentry/svelte` for the client, with added functionality related to SvelteKit. + +TODO: Add usage instructions diff --git a/packages/sveltekit/jest.config.js b/packages/sveltekit/jest.config.js new file mode 100644 index 000000000000..222e6a817c7b --- /dev/null +++ b/packages/sveltekit/jest.config.js @@ -0,0 +1,3 @@ +const baseConfig = require('../../jest/jest.config.js'); + +module.exports = baseConfig; diff --git a/packages/sveltekit/package.json b/packages/sveltekit/package.json new file mode 100644 index 000000000000..15ace0d3482a --- /dev/null +++ b/packages/sveltekit/package.json @@ -0,0 +1,58 @@ +{ + "name": "@sentry/sveltekit", + "version": "7.41.0", + "description": "Official Sentry SDK for SvelteKit", + "repository": "git://github.com/getsentry/sentry-javascript.git", + "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/sveltekit", + "author": "Sentry", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "main": "build/cjs/index.server.js", + "module": "build/esm/index.server.js", + "browser": "build/esm/index.client.js", + "types": "build/types/index.types.d.ts", + "publishConfig": { + "access": "public" + }, + "peerDependencies": { + "@sveltejs/kit": "1.x" + }, + "dependencies": { + "@sentry/core": "7.41.0", + "@sentry/node": "7.41.0", + "@sentry/svelte": "7.41.0", + "@sentry/types": "7.41.0", + "@sentry/utils": "7.41.0" + }, + "devDependencies": { + "@sveltejs/kit": "^1.10.0", + "vite": "^4.0.0" + }, + "scripts": { + "build": "run-p build:transpile build:types", + "build:dev": "yarn build", + "build:transpile": "rollup -c rollup.npm.config.js", + "build:types": "tsc -p tsconfig.types.json", + "build:watch": "run-p build:transpile:watch build:types:watch", + "build:dev:watch": "yarn build:watch", + "build:transpile:watch": "rollup -c rollup.npm.config.js --watch", + "build:types:watch": "tsc -p tsconfig.types.json --watch", + "build:tarball": "ts-node ../../scripts/prepack.ts && npm pack ./build", + "circularDepCheck": "madge --circular src/index.client.ts && madge --circular src/index.server.ts && madge --circular src/index.types.ts", + "clean": "rimraf build coverage sentry-sveltekit-*.tgz", + "fix": "run-s fix:eslint fix:prettier", + "fix:eslint": "eslint . --format stylish --fix", + "fix:prettier": "prettier --write \"{src,test,scripts}/**/**.ts\"", + "lint": "run-s lint:prettier lint:eslint", + "lint:eslint": "eslint . --format stylish", + "lint:prettier": "prettier --check \"{src,test,scripts}/**/**.ts\"", + "test": "yarn test:unit", + "test:unit": "jest", + "test:watch": "jest --watch" + }, + "volta": { + "extends": "../../package.json" + } +} diff --git a/packages/sveltekit/rollup.npm.config.js b/packages/sveltekit/rollup.npm.config.js new file mode 100644 index 000000000000..f1f8240d5a7a --- /dev/null +++ b/packages/sveltekit/rollup.npm.config.js @@ -0,0 +1,14 @@ +import { makeBaseNPMConfig, makeNPMConfigVariants } from '../../rollup/index.js'; + +export default + makeNPMConfigVariants( + makeBaseNPMConfig({ + entrypoints: [ + 'src/index.server.ts', + 'src/index.client.ts', + 'src/client/index.ts', + 'src/server/index.ts', + ], + }), + ) +; diff --git a/packages/sveltekit/src/client/index.ts b/packages/sveltekit/src/client/index.ts new file mode 100644 index 000000000000..cdd2d7ba8a6e --- /dev/null +++ b/packages/sveltekit/src/client/index.ts @@ -0,0 +1,4 @@ +export * from '@sentry/svelte'; + +// Just here so that eslint is happy until we export more stuff here +export const PLACEHOLDER_CLIENT = 'PLACEHOLDER'; diff --git a/packages/sveltekit/src/index.client.ts b/packages/sveltekit/src/index.client.ts new file mode 100644 index 000000000000..98d53afc24d2 --- /dev/null +++ b/packages/sveltekit/src/index.client.ts @@ -0,0 +1,7 @@ +export * from './client'; + +/** + * This const serves no purpose besides being an identifier for this file that the SDK multiplexer loader can use to + * determine that this is in fact a file that wants to be multiplexed. + */ +export const _SENTRY_SDK_MULTIPLEXER = true; diff --git a/packages/sveltekit/src/index.server.ts b/packages/sveltekit/src/index.server.ts new file mode 100644 index 000000000000..9bdd72ae4f02 --- /dev/null +++ b/packages/sveltekit/src/index.server.ts @@ -0,0 +1,9 @@ +export * from './server'; + +// This file is the main entrypoint on the server and/or when the package is `require`d + +/** + * This const serves no purpose besides being an identifier for this file that the SDK multiplexer loader can use to + * determine that this is in fact a file that wants to be multiplexed. + */ +export const _SENTRY_SDK_MULTIPLEXER = true; diff --git a/packages/sveltekit/src/index.types.ts b/packages/sveltekit/src/index.types.ts new file mode 100644 index 000000000000..f2eccf6ffb92 --- /dev/null +++ b/packages/sveltekit/src/index.types.ts @@ -0,0 +1,25 @@ +/* eslint-disable import/export */ + +// We export everything from both the client part of the SDK and from the server part. +// Some of the exports collide, which is not allowed, unless we redifine the colliding +// exports in this file - which we do below. +export * from './client'; +export * from './server'; + +import type { Integration, Options, StackParser } from '@sentry/types'; + +import type * as clientSdk from './client'; +import type * as serverSdk from './server'; + +/** Initializes Sentry SvelteKit SDK */ +export declare function init(options: Options | clientSdk.BrowserOptions | serverSdk.NodeOptions): void; + +// We export a merged Integrations object so that users can (at least typing-wise) use all integrations everywhere. +export declare const Integrations: typeof clientSdk.Integrations & typeof serverSdk.Integrations; + +export declare const defaultIntegrations: Integration[]; +export declare const defaultStackParser: StackParser; + +export declare function close(timeout?: number | undefined): PromiseLike; +export declare function flush(timeout?: number | undefined): PromiseLike; +export declare function lastEventId(): string | undefined; diff --git a/packages/sveltekit/src/server/index.ts b/packages/sveltekit/src/server/index.ts new file mode 100644 index 000000000000..04654fecd19a --- /dev/null +++ b/packages/sveltekit/src/server/index.ts @@ -0,0 +1,4 @@ +export * from '@sentry/node'; + +// Just here so that eslint is happy until we export more stuff here +export const PLACEHOLDER_SERVER = 'PLACEHOLDER'; diff --git a/packages/sveltekit/test/index.test.ts b/packages/sveltekit/test/index.test.ts new file mode 100644 index 000000000000..6bc0e7072028 --- /dev/null +++ b/packages/sveltekit/test/index.test.ts @@ -0,0 +1,12 @@ +import * as SentryClient from '../src/client'; +import * as SentryServer from '../src/server'; + +describe('SvelteKit SDK', () => { + // This is a place holder test at best to satisfy the test runner + it('exports client and server SDKs', () => { + expect(SentryClient).toBeDefined(); + expect(SentryServer).toBeDefined(); + expect(SentryClient.init).toBeDefined(); + expect(SentryServer.init).toBeDefined(); + }); +}); diff --git a/packages/sveltekit/tsconfig.json b/packages/sveltekit/tsconfig.json new file mode 100644 index 000000000000..bf45a09f2d71 --- /dev/null +++ b/packages/sveltekit/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + + "include": ["src/**/*"], + + "compilerOptions": { + // package-specific options + } +} diff --git a/packages/sveltekit/tsconfig.test.json b/packages/sveltekit/tsconfig.test.json new file mode 100644 index 000000000000..39a2d7203902 --- /dev/null +++ b/packages/sveltekit/tsconfig.test.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + + "include": ["test/**/*"], + + "compilerOptions": { + // should include all types from `./tsconfig.json` plus types for all test frameworks used + "types": ["node", "jest"] + } +} diff --git a/packages/sveltekit/tsconfig.types.json b/packages/sveltekit/tsconfig.types.json new file mode 100644 index 000000000000..65455f66bd75 --- /dev/null +++ b/packages/sveltekit/tsconfig.types.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "build/types" + } +} diff --git a/scripts/node-unit-tests.ts b/scripts/node-unit-tests.ts index 4e6efaec9d0e..ebe252a95240 100644 --- a/scripts/node-unit-tests.ts +++ b/scripts/node-unit-tests.ts @@ -16,7 +16,7 @@ const DEFAULT_SKIP_TESTS_PACKAGES = [ ]; // These packages don't support Node 8 for syntax or dependency reasons. -const NODE_8_SKIP_TESTS_PACKAGES = ['@sentry/gatsby', '@sentry/serverless', '@sentry/nextjs', '@sentry/remix']; +const NODE_8_SKIP_TESTS_PACKAGES = ['@sentry/gatsby', '@sentry/serverless', '@sentry/nextjs', '@sentry/remix', '@sentry/sveltekit']; // We have to downgrade some of our dependencies in order to run tests in Node 8 and 10. const NODE_8_LEGACY_DEPENDENCIES = [ @@ -28,12 +28,15 @@ const NODE_8_LEGACY_DEPENDENCIES = [ 'lerna@3.13.4', ]; -const NODE_10_SKIP_TESTS_PACKAGES = ['@sentry/remix']; +const NODE_10_SKIP_TESTS_PACKAGES = ['@sentry/remix', '@sentry/sveltekit']; const NODE_10_LEGACY_DEPENDENCIES = ['jsdom@16.x', 'lerna@3.13.4']; -const NODE_12_SKIP_TESTS_PACKAGES = ['@sentry/remix']; +const NODE_12_SKIP_TESTS_PACKAGES = ['@sentry/remix', '@sentry/sveltekit']; const NODE_12_LEGACY_DEPENDENCIES = ['lerna@3.13.4']; +const NODE_14_SKIP_TESTS_PACKAGES = ['@sentry/sveltekit']; + + type JSONValue = string | number | boolean | null | JSONArray | JSONObject; type JSONObject = { @@ -131,6 +134,9 @@ function runTests(): void { installLegacyDeps(NODE_12_LEGACY_DEPENDENCIES); es6ifyTestTSConfig('utils'); break; + case '14': + NODE_14_SKIP_TESTS_PACKAGES.forEach(dep => ignores.add(dep)); + break; } runWithIgnores(Array.from(ignores)); diff --git a/yarn.lock b/yarn.lock index 6de62b92a4ea..77998803e637 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2345,6 +2345,116 @@ broccoli-funnel "^3.0.5" ember-cli-babel "^7.23.1" +"@esbuild/android-arm64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz#cf91e86df127aa3d141744edafcba0abdc577d23" + integrity sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg== + +"@esbuild/android-arm@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.16.17.tgz#025b6246d3f68b7bbaa97069144fb5fb70f2fff2" + integrity sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw== + +"@esbuild/android-x64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.16.17.tgz#c820e0fef982f99a85c4b8bfdd582835f04cd96e" + integrity sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ== + +"@esbuild/darwin-arm64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz#edef4487af6b21afabba7be5132c26d22379b220" + integrity sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w== + +"@esbuild/darwin-x64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz#42829168730071c41ef0d028d8319eea0e2904b4" + integrity sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg== + +"@esbuild/freebsd-arm64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz#1f4af488bfc7e9ced04207034d398e793b570a27" + integrity sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw== + +"@esbuild/freebsd-x64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz#636306f19e9bc981e06aa1d777302dad8fddaf72" + integrity sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug== + +"@esbuild/linux-arm64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz#a003f7ff237c501e095d4f3a09e58fc7b25a4aca" + integrity sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g== + +"@esbuild/linux-arm@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz#b591e6a59d9c4fe0eeadd4874b157ab78cf5f196" + integrity sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ== + +"@esbuild/linux-ia32@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz#24333a11027ef46a18f57019450a5188918e2a54" + integrity sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg== + +"@esbuild/linux-loong64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz#d5ad459d41ed42bbd4d005256b31882ec52227d8" + integrity sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ== + +"@esbuild/linux-mips64el@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz#4e5967a665c38360b0a8205594377d4dcf9c3726" + integrity sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw== + +"@esbuild/linux-ppc64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz#206443a02eb568f9fdf0b438fbd47d26e735afc8" + integrity sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g== + +"@esbuild/linux-riscv64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz#c351e433d009bf256e798ad048152c8d76da2fc9" + integrity sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw== + +"@esbuild/linux-s390x@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz#661f271e5d59615b84b6801d1c2123ad13d9bd87" + integrity sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w== + +"@esbuild/linux-x64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz#e4ba18e8b149a89c982351443a377c723762b85f" + integrity sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw== + +"@esbuild/netbsd-x64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz#7d4f4041e30c5c07dd24ffa295c73f06038ec775" + integrity sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA== + +"@esbuild/openbsd-x64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz#970fa7f8470681f3e6b1db0cc421a4af8060ec35" + integrity sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg== + +"@esbuild/sunos-x64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz#abc60e7c4abf8b89fb7a4fe69a1484132238022c" + integrity sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw== + +"@esbuild/win32-arm64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz#7b0ff9e8c3265537a7a7b1fd9a24e7bd39fcd87a" + integrity sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw== + +"@esbuild/win32-ia32@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz#e90fe5267d71a7b7567afdc403dfd198c292eb09" + integrity sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig== + +"@esbuild/win32-x64@0.16.17": + version "0.16.17" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz#c5a1a4bfe1b57f0c3e61b29883525c6da3e5c091" + integrity sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q== + "@eslint/eslintrc@^0.4.3": version "0.4.3" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" @@ -3589,6 +3699,11 @@ optionalDependencies: fsevents "2.3.2" +"@polka/url@^1.0.0-next.20": + version "1.0.0-next.21" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" + integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== + "@polka/url@^1.0.0-next.9": version "1.0.0-next.12" resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.12.tgz#431ec342a7195622f86688bbda82e3166ce8cb28" @@ -4090,6 +4205,37 @@ dependencies: highlight.js "^9.15.6" +"@sveltejs/kit@^1.10.0": + version "1.10.0" + resolved "https://registry.yarnpkg.com/@sveltejs/kit/-/kit-1.10.0.tgz#17d3565e5903f6d2c0730197fd875c2cf921ad01" + integrity sha512-0P35zHrByfbF3Ym3RdQL+RvzgsCDSyO3imSwuZ67XAD5HoCQFF3a8Mhh0V3sObz3rc5aJd4Qn82UpAihJqZ6gQ== + dependencies: + "@sveltejs/vite-plugin-svelte" "^2.0.0" + "@types/cookie" "^0.5.1" + cookie "^0.5.0" + devalue "^4.3.0" + esm-env "^1.0.0" + kleur "^4.1.5" + magic-string "^0.30.0" + mime "^3.0.0" + sade "^1.8.1" + set-cookie-parser "^2.5.1" + sirv "^2.0.2" + tiny-glob "^0.2.9" + undici "5.20.0" + +"@sveltejs/vite-plugin-svelte@^2.0.0": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-2.0.3.tgz#3d276eab341638dd58691a3de610774e155a7578" + integrity sha512-o+cguBFdwIGtRbNkYOyqTM7KvRUffxh5bfK4oJsWKG2obu+v/cbpT03tJrGl58C7tRXo/aEC0/axN5FVHBj0nA== + dependencies: + debug "^4.3.4" + deepmerge "^4.3.0" + kleur "^4.1.5" + magic-string "^0.29.0" + svelte-hmr "^0.15.1" + vitefu "^0.2.4" + "@szmarczak/http-timer@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" @@ -4280,6 +4426,11 @@ resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== +"@types/cookie@^0.5.1": + version "0.5.1" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.5.1.tgz#b29aa1f91a59f35e29ff8f7cb24faf1a3a750554" + integrity sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g== + "@types/cors@2.8.12", "@types/cors@^2.8.12": version "2.8.12" resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080" @@ -8265,6 +8416,13 @@ builtins@^5.0.0: dependencies: semver "^7.0.0" +busboy@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== + dependencies: + streamsearch "^1.1.0" + byte-size@7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/byte-size/-/byte-size-7.0.0.tgz#36528cd1ca87d39bd9abd51f5715dc93b6ceb032" @@ -9394,7 +9552,7 @@ cookie-signature@^1.1.0: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.2.0.tgz#4deed303f5f095e7a02c979e3fcb19157f5eaeea" integrity sha512-R0BOPfLGTitaKhgKROKZQN6iyq2iDQcH1DOF8nJoaWapguX5bC2w+Q/I9NmmM5lfcvEarnLZr+cCvmEYYSXvYA== -cookie@0.5.0: +cookie@0.5.0, cookie@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== @@ -10271,6 +10429,11 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== +deepmerge@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.0.tgz#65491893ec47756d44719ae520e0e2609233b59b" + integrity sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og== + default-gateway@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" @@ -10522,6 +10685,11 @@ detective-typescript@^7.0.0: node-source-walk "^4.2.0" typescript "^3.9.7" +devalue@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/devalue/-/devalue-4.3.0.tgz#d86db8fee63a70317c2355be0d3d1b4d8f89a44e" + integrity sha512-n94yQo4LI3w7erwf84mhRUkUJfhLoCZiLyoOZ/QFsDbcWNZePrLwbQpvZBUG2TNxwV3VjCKPxkiiQA6pe3TrTA== + dezalgo@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" @@ -11889,6 +12057,34 @@ esbuild@0.13.8: esbuild-windows-64 "0.13.8" esbuild-windows-arm64 "0.13.8" +esbuild@^0.16.14: + version "0.16.17" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.16.17.tgz#fc2c3914c57ee750635fee71b89f615f25065259" + integrity sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg== + optionalDependencies: + "@esbuild/android-arm" "0.16.17" + "@esbuild/android-arm64" "0.16.17" + "@esbuild/android-x64" "0.16.17" + "@esbuild/darwin-arm64" "0.16.17" + "@esbuild/darwin-x64" "0.16.17" + "@esbuild/freebsd-arm64" "0.16.17" + "@esbuild/freebsd-x64" "0.16.17" + "@esbuild/linux-arm" "0.16.17" + "@esbuild/linux-arm64" "0.16.17" + "@esbuild/linux-ia32" "0.16.17" + "@esbuild/linux-loong64" "0.16.17" + "@esbuild/linux-mips64el" "0.16.17" + "@esbuild/linux-ppc64" "0.16.17" + "@esbuild/linux-riscv64" "0.16.17" + "@esbuild/linux-s390x" "0.16.17" + "@esbuild/linux-x64" "0.16.17" + "@esbuild/netbsd-x64" "0.16.17" + "@esbuild/openbsd-x64" "0.16.17" + "@esbuild/sunos-x64" "0.16.17" + "@esbuild/win32-arm64" "0.16.17" + "@esbuild/win32-ia32" "0.16.17" + "@esbuild/win32-x64" "0.16.17" + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -12171,6 +12367,11 @@ eslint@7.32.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" +esm-env@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esm-env/-/esm-env-1.0.0.tgz#b124b40b180711690a4cb9b00d16573391950413" + integrity sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA== + esm@^3.2.4: version "3.2.25" resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" @@ -16618,6 +16819,11 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== +kleur@^4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" + integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== + klona@^2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" @@ -17468,6 +17674,20 @@ magic-string@^0.27.0: dependencies: "@jridgewell/sourcemap-codec" "^1.4.13" +magic-string@^0.29.0: + version "0.29.0" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.29.0.tgz#f034f79f8c43dba4ae1730ffb5e8c4e084b16cf3" + integrity sha512-WcfidHrDjMY+eLjlU+8OvwREqHwpgCeKVBUpQ3OhYYuvfaYCUgcbuBzappNzZvg/v8onU3oQj+BYpkOJe9Iw4Q== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.13" + +magic-string@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.0.tgz#fd58a4748c5c4547338a424e90fa5dd17f4de529" + integrity sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.13" + make-dir@3.1.0, make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0, make-dir@~3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -17855,6 +18075,11 @@ mime@^2.3.1, mime@^2.4.4, mime@^2.5.2: resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== +mime@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" + integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== + mime@~2.5.2: version "2.5.2" resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" @@ -18264,6 +18489,11 @@ move-concurrently@^1.0.1: rimraf "^2.5.4" run-queue "^1.0.3" +mri@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" + integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== + mrmime@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.0.tgz#14d387f0585a5233d291baba339b063752a2398b" @@ -21457,7 +21687,7 @@ postcss@^8.1.10, postcss@^8.1.7, postcss@^8.2.15: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8.2.4, postcss@^8.3.5, postcss@^8.3.7: +postcss@^8.2.4, postcss@^8.3.5, postcss@^8.3.7, postcss@^8.4.21: version "8.4.21" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4" integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg== @@ -23054,6 +23284,13 @@ rollup@^2.45.1: optionalDependencies: fsevents "~2.3.2" +rollup@^3.10.0: + version "3.18.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.18.0.tgz#2354ba63ba66d6a09c652c3ea0dbcd9dad72bbde" + integrity sha512-J8C6VfEBjkvYPESMQYxKHxNOh4A5a3FlP+0BETGo34HEcE4eTlgCrO2+eWzlu2a/sHs2QUkZco+wscH7jhhgWg== + optionalDependencies: + fsevents "~2.3.2" + rsvp@^3.0.14, rsvp@^3.0.17, rsvp@^3.0.18, rsvp@^3.0.21, rsvp@^3.0.6, rsvp@^3.1.0: version "3.6.2" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" @@ -23123,6 +23360,13 @@ rxjs@^7.5.5: dependencies: tslib "^2.1.0" +sade@^1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701" + integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A== + dependencies: + mri "^1.1.0" + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -23448,6 +23692,11 @@ set-cookie-parser@^2.4.8: resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz#d0da0ed388bc8f24e706a391f9c9e252a13c58b2" integrity sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg== +set-cookie-parser@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.5.1.tgz#ddd3e9a566b0e8e0862aca974a6ac0e01349430b" + integrity sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ== + set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" @@ -23617,6 +23866,15 @@ sirv@^1.0.7: mime "^2.3.1" totalist "^1.0.0" +sirv@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-2.0.2.tgz#128b9a628d77568139cff85703ad5497c46a4760" + integrity sha512-4Qog6aE29nIjAOKe/wowFTxOdmbEZKb+3tsLljaBRzJwtqto0BChD2zzH0LhgCSXiI+V7X+Y45v14wBZQ1TK3w== + dependencies: + "@polka/url" "^1.0.0-next.20" + mrmime "^1.0.0" + totalist "^3.0.0" + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -24326,6 +24584,11 @@ streamroller@^3.0.2: debug "^4.1.1" fs-extra "^10.0.0" +streamsearch@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== + strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" @@ -24739,6 +25002,11 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +svelte-hmr@^0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/svelte-hmr/-/svelte-hmr-0.15.1.tgz#d11d878a0bbb12ec1cba030f580cd2049f4ec86b" + integrity sha512-BiKB4RZ8YSwRKCNVdNxK/GfY+r4Kjgp9jCLEy0DuqAKfmQtpL38cQK3afdpjw4sqSs4PLi3jIPJIFp259NkZtA== + svelte-jester@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/svelte-jester/-/svelte-jester-2.3.2.tgz#9eb818da30807bbcc940b6130d15b2c34408d64f" @@ -25205,7 +25473,7 @@ timsort@^0.3.0: resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= -tiny-glob@0.2.9: +tiny-glob@0.2.9, tiny-glob@^0.2.9: version "0.2.9" resolved "https://registry.yarnpkg.com/tiny-glob/-/tiny-glob-0.2.9.tgz#2212d441ac17928033b110f8b3640683129d31e2" integrity sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg== @@ -25335,6 +25603,11 @@ totalist@^1.0.0: resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== +totalist@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/totalist/-/totalist-3.0.0.tgz#4ef9c58c5f095255cdc3ff2a0a55091c57a3a1bd" + integrity sha512-eM+pCBxXO/njtF7vdFsHuqb+ElbxqtI4r5EAvk6grfAFyJ6IvWlSkfZ5T9ozC6xWw3Fj1fGoSmrl0gUs46JVIw== + touch@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" @@ -25782,6 +26055,13 @@ underscore@>=1.8.3: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e" integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw== +undici@5.20.0: + version "5.20.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.20.0.tgz#6327462f5ce1d3646bcdac99da7317f455bcc263" + integrity sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g== + dependencies: + busboy "^1.6.0" + unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" @@ -26238,6 +26518,23 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +vite@^4.0.0: + version "4.1.4" + resolved "https://registry.yarnpkg.com/vite/-/vite-4.1.4.tgz#170d93bcff97e0ebc09764c053eebe130bfe6ca0" + integrity sha512-3knk/HsbSTKEin43zHu7jTwYWv81f8kgAL99G5NWBcA1LKvtvcVAC4JjBH1arBunO9kQka+1oGbrMKOjk4ZrBg== + dependencies: + esbuild "^0.16.14" + postcss "^8.4.21" + resolve "^1.22.1" + rollup "^3.10.0" + optionalDependencies: + fsevents "~2.3.2" + +vitefu@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/vitefu/-/vitefu-0.2.4.tgz#212dc1a9d0254afe65e579351bed4e25d81e0b35" + integrity sha512-fanAXjSaf9xXtOOeno8wZXIhgia+CZury481LsDaV++lSvcU2R9Ch2bPh3PYFyoHW+w9LqAeYRISVQjUIew14g== + vm-browserify@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.0.tgz#bd76d6a23323e2ca8ffa12028dc04559c75f9019" From 14b6fcae6a26b38a278fda87b223e8835bf452d4 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Tue, 7 Mar 2023 16:03:41 +0100 Subject: [PATCH 27/44] ref(replay): Handle checkouts more explicitly (#7321) --- .../suites/replay/multiple-pages/test.ts | 69 ++++++----- packages/replay/src/replay.ts | 112 ++++-------------- packages/replay/src/types.ts | 2 + packages/replay/src/util/addEvent.ts | 3 +- .../replay/src/util/handleRecordingEmit.ts | 86 ++++++++++++++ .../test/integration/autoSaveSession.test.ts | 4 +- .../unit/util/handleRecordingEmit.test.ts | 86 ++++++++++++++ .../replay/test/utils/setupReplayContainer.ts | 2 +- 8 files changed, 239 insertions(+), 125 deletions(-) create mode 100644 packages/replay/src/util/handleRecordingEmit.ts create mode 100644 packages/replay/test/unit/util/handleRecordingEmit.test.ts diff --git a/packages/integration-tests/suites/replay/multiple-pages/test.ts b/packages/integration-tests/suites/replay/multiple-pages/test.ts index 914c7dd856ca..9fc3c3f0481a 100644 --- a/packages/integration-tests/suites/replay/multiple-pages/test.ts +++ b/packages/integration-tests/suites/replay/multiple-pages/test.ts @@ -45,12 +45,21 @@ sentryTest( const reqPromise0 = waitForReplayRequest(page, 0); const reqPromise1 = waitForReplayRequest(page, 1); + const reqPromise2 = waitForReplayRequest(page, 2); + const reqPromise3 = waitForReplayRequest(page, 3); + const reqPromise4 = waitForReplayRequest(page, 4); + const reqPromise5 = waitForReplayRequest(page, 5); + const reqPromise6 = waitForReplayRequest(page, 6); + const reqPromise7 = waitForReplayRequest(page, 7); + const reqPromise8 = waitForReplayRequest(page, 8); + const reqPromise9 = waitForReplayRequest(page, 9); const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); - const replayEvent0 = getReplayEvent(await reqPromise0); - const recording0 = getReplayRecordingContent(await reqPromise0); + const req0 = await reqPromise0; + const replayEvent0 = getReplayEvent(req0); + const recording0 = getReplayRecordingContent(req0); expect(replayEvent0).toEqual(getExpectedReplayEvent({ segment_id: 0 })); expect(normalize(recording0.fullSnapshots)).toMatchSnapshot('seg-0-snap-full'); @@ -58,8 +67,9 @@ sentryTest( await page.click('#go-background'); - const replayEvent1 = getReplayEvent(await reqPromise1); - const recording1 = getReplayRecordingContent(await reqPromise1); + const req1 = await reqPromise1; + const replayEvent1 = getReplayEvent(req1); + const recording1 = getReplayRecordingContent(req1); expect(replayEvent1).toEqual( getExpectedReplayEvent({ segment_id: 1, urls: [], replay_start_timestamp: undefined }), @@ -91,11 +101,9 @@ sentryTest( await page.reload(); - const reqPromise2 = waitForReplayRequest(page, 2); - const reqPromise3 = waitForReplayRequest(page, 3); - - const replayEvent2 = getReplayEvent(await reqPromise2); - const recording2 = getReplayRecordingContent(await reqPromise2); + const req2 = await reqPromise2; + const replayEvent2 = getReplayEvent(req2); + const recording2 = getReplayRecordingContent(req2); expect(replayEvent2).toEqual(getExpectedReplayEvent({ segment_id: 2, replay_start_timestamp: undefined })); expect(normalize(recording2.fullSnapshots)).toMatchSnapshot('seg-2-snap-full'); @@ -103,8 +111,9 @@ sentryTest( await page.click('#go-background'); - const replayEvent3 = getReplayEvent(await reqPromise3); - const recording3 = getReplayRecordingContent(await reqPromise3); + const req3 = await reqPromise3; + const replayEvent3 = getReplayEvent(req3); + const recording3 = getReplayRecordingContent(req3); expect(replayEvent3).toEqual( getExpectedReplayEvent({ segment_id: 3, urls: [], replay_start_timestamp: undefined }), @@ -134,11 +143,9 @@ sentryTest( await page.click('a'); - const reqPromise4 = waitForReplayRequest(page, 4); - const reqPromise5 = waitForReplayRequest(page, 5); - - const replayEvent4 = getReplayEvent(await reqPromise4); - const recording4 = getReplayRecordingContent(await reqPromise4); + const req4 = await reqPromise4; + const replayEvent4 = getReplayEvent(req4); + const recording4 = getReplayRecordingContent(req4); expect(replayEvent4).toEqual( getExpectedReplayEvent({ @@ -161,8 +168,9 @@ sentryTest( await page.click('#go-background'); - const replayEvent5 = getReplayEvent(await reqPromise5); - const recording5 = getReplayRecordingContent(await reqPromise5); + const req5 = await reqPromise5; + const replayEvent5 = getReplayEvent(req5); + const recording5 = getReplayRecordingContent(req5); expect(replayEvent5).toEqual( getExpectedReplayEvent({ @@ -207,9 +215,9 @@ sentryTest( await page.click('#spa-navigation'); - const reqPromise6 = waitForReplayRequest(page, 6); - const replayEvent6 = getReplayEvent(await reqPromise6); - const recording6 = getReplayRecordingContent(await reqPromise6); + const req6 = await reqPromise6; + const replayEvent6 = getReplayEvent(req6); + const recording6 = getReplayRecordingContent(req6); expect(replayEvent6).toEqual( getExpectedReplayEvent({ @@ -231,9 +239,9 @@ sentryTest( await page.click('#go-background'); - const reqPromise7 = waitForReplayRequest(page, 7); - const replayEvent7 = getReplayEvent(await reqPromise7); - const recording7 = getReplayRecordingContent(await reqPromise7); + const req7 = await reqPromise7; + const replayEvent7 = getReplayEvent(req7); + const recording7 = getReplayRecordingContent(req7); expect(replayEvent7).toEqual( getExpectedReplayEvent({ @@ -279,11 +287,9 @@ sentryTest( await page.click('a'); - const reqPromise8 = waitForReplayRequest(page, 8); - const reqPromise9 = waitForReplayRequest(page, 9); - - const replayEvent8 = getReplayEvent(await reqPromise8); - const recording8 = getReplayRecordingContent(await reqPromise8); + const req8 = await reqPromise8; + const replayEvent8 = getReplayEvent(req8); + const recording8 = getReplayRecordingContent(req8); expect(replayEvent8).toEqual( getExpectedReplayEvent({ @@ -296,8 +302,9 @@ sentryTest( await page.click('#go-background'); - const replayEvent9 = getReplayEvent(await reqPromise9); - const recording9 = getReplayRecordingContent(await reqPromise9); + const req9 = await reqPromise9; + const replayEvent9 = getReplayEvent(req9); + const recording9 = getReplayRecordingContent(req9); expect(replayEvent9).toEqual( getExpectedReplayEvent({ diff --git a/packages/replay/src/replay.ts b/packages/replay/src/replay.ts index f96252f01d43..939dd0b8375c 100644 --- a/packages/replay/src/replay.ts +++ b/packages/replay/src/replay.ts @@ -16,7 +16,6 @@ import type { EventBuffer, InternalEventContext, PopEventContext, - RecordingEvent, RecordingOptions, ReplayContainer as ReplayContainerInterface, ReplayPluginOptions, @@ -30,6 +29,7 @@ import { createBreadcrumb } from './util/createBreadcrumb'; import { createPerformanceEntries } from './util/createPerformanceEntries'; import { createPerformanceSpans } from './util/createPerformanceSpans'; import { debounce } from './util/debounce'; +import { getHandleRecordingEmit } from './util/handleRecordingEmit'; import { isExpired } from './util/isExpired'; import { isSessionExpired } from './util/isSessionExpired'; import { overwriteRecordDroppedEvent, restoreRecordDroppedEvent } from './util/monkeyPatchRecordDroppedEvent'; @@ -155,7 +155,7 @@ export class ReplayContainer implements ReplayContainerInterface { * _performanceObserver, Recording, Sentry SDK, etc) */ public start(): void { - this._setInitialState(); + this.setInitialState(); if (!this._loadAndCheckSession()) { return; @@ -207,7 +207,7 @@ export class ReplayContainer implements ReplayContainerInterface { // Without this, it would record forever, until an error happens, which we don't want // instead, we'll always keep the last 60 seconds of replay before an error happened ...(this.recordingMode === 'error' && { checkoutEveryNms: ERROR_CHECKOUT_TIME }), - emit: this._handleRecordingEmit, + emit: getHandleRecordingEmit(this), onMutation: (mutations: unknown[]) => { if (this._options._experiments.captureMutationSize) { const count = mutations.length; @@ -420,6 +420,25 @@ export class ReplayContainer implements ReplayContainerInterface { return false; } + /** + * Capture some initial state that can change throughout the lifespan of the + * replay. This is required because otherwise they would be captured at the + * first flush. + */ + public setInitialState(): void { + const urlPath = `${WINDOW.location.pathname}${WINDOW.location.hash}${WINDOW.location.search}`; + const url = `${WINDOW.location.origin}${urlPath}`; + + this.performanceEvents = []; + + // Reset _context as well + this._clearContext(); + + this._context.initialUrl = url; + this._context.initialTimestamp = new Date().getTime(); + this._context.urls.push(url); + } + /** A wrapper to conditionally capture exceptions. */ private _handleException(error: unknown): void { __DEBUG_BUILD__ && logger.error('[Replay]', error); @@ -445,7 +464,7 @@ export class ReplayContainer implements ReplayContainerInterface { // If session was newly created (i.e. was not loaded from storage), then // enable flag to create the root replay if (type === 'new') { - this._setInitialState(); + this.setInitialState(); } const currentSessionId = this.getSessionId(); @@ -463,25 +482,6 @@ export class ReplayContainer implements ReplayContainerInterface { return true; } - /** - * Capture some initial state that can change throughout the lifespan of the - * replay. This is required because otherwise they would be captured at the - * first flush. - */ - private _setInitialState(): void { - const urlPath = `${WINDOW.location.pathname}${WINDOW.location.hash}${WINDOW.location.search}`; - const url = `${WINDOW.location.origin}${urlPath}`; - - this.performanceEvents = []; - - // Reset _context as well - this._clearContext(); - - this._context.initialUrl = url; - this._context.initialTimestamp = new Date().getTime(); - this._context.urls.push(url); - } - /** * Adds listeners to record events for the replay */ @@ -533,72 +533,6 @@ export class ReplayContainer implements ReplayContainerInterface { } } - /** - * Handler for recording events. - * - * Adds to event buffer, and has varying flushing behaviors if the event was a checkout. - */ - private _handleRecordingEmit: (event: RecordingEvent, isCheckout?: boolean) => void = ( - event: RecordingEvent, - isCheckout?: boolean, - ) => { - // If this is false, it means session is expired, create and a new session and wait for checkout - if (!this.checkAndHandleExpiredSession()) { - __DEBUG_BUILD__ && logger.warn('[Replay] Received replay event after session expired.'); - - return; - } - - this.addUpdate(() => { - // The session is always started immediately on pageload/init, but for - // error-only replays, it should reflect the most recent checkout - // when an error occurs. Clear any state that happens before this current - // checkout. This needs to happen before `addEvent()` which updates state - // dependent on this reset. - if (this.recordingMode === 'error' && event.type === 2) { - this._setInitialState(); - } - - // We need to clear existing events on a checkout, otherwise they are - // incremental event updates and should be appended - void addEvent(this, event, isCheckout); - - // Different behavior for full snapshots (type=2), ignore other event types - // See https://github.com/rrweb-io/rrweb/blob/d8f9290ca496712aa1e7d472549480c4e7876594/packages/rrweb/src/types.ts#L16 - if (event.type !== 2) { - return false; - } - - // If there is a previousSessionId after a full snapshot occurs, then - // the replay session was started due to session expiration. The new session - // is started before triggering a new checkout and contains the id - // of the previous session. Do not immediately flush in this case - // to avoid capturing only the checkout and instead the replay will - // be captured if they perform any follow-up actions. - if (this.session && this.session.previousSessionId) { - return true; - } - - // See note above re: session start needs to reflect the most recent - // checkout. - if (this.recordingMode === 'error' && this.session && this._context.earliestEvent) { - this.session.started = this._context.earliestEvent; - this._maybeSaveSession(); - } - - // Flush immediately so that we do not miss the first segment, otherwise - // it can prevent loading on the UI. This will cause an increase in short - // replays (e.g. opening and closing a tab quickly), but these can be - // filtered on the UI. - if (this.recordingMode === 'session') { - // We want to ensure the worker is ready, as otherwise we'd always send the first event uncompressed - void this.flushImmediate(); - } - - return true; - }); - }; - /** * Handle when visibility of the page content changes. Opening a new tab will * cause the state to change to hidden because of content of current page will diff --git a/packages/replay/src/types.ts b/packages/replay/src/types.ts index 15c03e228b83..1ea691f3ec4e 100644 --- a/packages/replay/src/types.ts +++ b/packages/replay/src/types.ts @@ -277,6 +277,7 @@ export interface EventBuffer { /** * Add an event to the event buffer. + * `isCheckout` is true if this is either the very first event, or an event triggered by `checkoutEveryNms`. * * Returns a promise that resolves if the event was successfully added, else rejects. */ @@ -314,6 +315,7 @@ export interface ReplayContainer { getOptions(): ReplayPluginOptions; getSessionId(): string | undefined; checkAndHandleExpiredSession(): boolean | void; + setInitialState(): void; } export interface ReplayPerformanceEntry { diff --git a/packages/replay/src/util/addEvent.ts b/packages/replay/src/util/addEvent.ts index 8b2918656518..357ecaca0e61 100644 --- a/packages/replay/src/util/addEvent.ts +++ b/packages/replay/src/util/addEvent.ts @@ -4,7 +4,8 @@ import { logger } from '@sentry/utils'; import type { AddEventResult, RecordingEvent, ReplayContainer } from '../types'; /** - * Add an event to the event buffer + * Add an event to the event buffer. + * `isCheckout` is true if this is either the very first event, or an event triggered by `checkoutEveryNms`. */ export async function addEvent( replay: ReplayContainer, diff --git a/packages/replay/src/util/handleRecordingEmit.ts b/packages/replay/src/util/handleRecordingEmit.ts new file mode 100644 index 000000000000..e9a4a16b5018 --- /dev/null +++ b/packages/replay/src/util/handleRecordingEmit.ts @@ -0,0 +1,86 @@ +import { logger } from '@sentry/utils'; + +import { saveSession } from '../session/saveSession'; +import type { RecordingEvent, ReplayContainer } from '../types'; +import { addEvent } from './addEvent'; + +type RecordingEmitCallback = (event: RecordingEvent, isCheckout?: boolean) => void; + +/** + * Handler for recording events. + * + * Adds to event buffer, and has varying flushing behaviors if the event was a checkout. + */ +export function getHandleRecordingEmit(replay: ReplayContainer): RecordingEmitCallback { + let hadFirstEvent = false; + + return (event: RecordingEvent, _isCheckout?: boolean) => { + // If this is false, it means session is expired, create and a new session and wait for checkout + if (!replay.checkAndHandleExpiredSession()) { + __DEBUG_BUILD__ && logger.warn('[Replay] Received replay event after session expired.'); + + return; + } + + // `_isCheckout` is only set when the checkout is due to `checkoutEveryNms` + // We also want to treat the first event as a checkout, so we handle this specifically here + const isCheckout = _isCheckout || !hadFirstEvent; + hadFirstEvent = true; + + // The handler returns `true` if we do not want to trigger debounced flush, `false` if we want to debounce flush. + replay.addUpdate(() => { + // The session is always started immediately on pageload/init, but for + // error-only replays, it should reflect the most recent checkout + // when an error occurs. Clear any state that happens before this current + // checkout. This needs to happen before `addEvent()` which updates state + // dependent on this reset. + if (replay.recordingMode === 'error' && isCheckout) { + replay.setInitialState(); + } + + // We need to clear existing events on a checkout, otherwise they are + // incremental event updates and should be appended + void addEvent(replay, event, isCheckout); + + // Different behavior for full snapshots (type=2), ignore other event types + // See https://github.com/rrweb-io/rrweb/blob/d8f9290ca496712aa1e7d472549480c4e7876594/packages/rrweb/src/types.ts#L16 + if (!isCheckout) { + return false; + } + + // If there is a previousSessionId after a full snapshot occurs, then + // the replay session was started due to session expiration. The new session + // is started before triggering a new checkout and contains the id + // of the previous session. Do not immediately flush in this case + // to avoid capturing only the checkout and instead the replay will + // be captured if they perform any follow-up actions. + if (replay.session && replay.session.previousSessionId) { + return true; + } + + // See note above re: session start needs to reflect the most recent + // checkout. + if (replay.recordingMode === 'error' && replay.session) { + const { earliestEvent } = replay.getContext(); + if (earliestEvent) { + replay.session.started = earliestEvent; + + if (replay.getOptions().stickySession) { + saveSession(replay.session); + } + } + } + + // Flush immediately so that we do not miss the first segment, otherwise + // it can prevent loading on the UI. This will cause an increase in short + // replays (e.g. opening and closing a tab quickly), but these can be + // filtered on the UI. + if (replay.recordingMode === 'session') { + // We want to ensure the worker is ready, as otherwise we'd always send the first event uncompressed + void replay.flushImmediate(); + } + + return true; + }); + }; +} diff --git a/packages/replay/test/integration/autoSaveSession.test.ts b/packages/replay/test/integration/autoSaveSession.test.ts index a640f810d2e7..6fc0539c771d 100644 --- a/packages/replay/test/integration/autoSaveSession.test.ts +++ b/packages/replay/test/integration/autoSaveSession.test.ts @@ -16,11 +16,9 @@ describe('Integration | autoSaveSession', () => { ['with stickySession=true', true, 1], ['with stickySession=false', false, 0], ])('%s', async (_: string, stickySession: boolean, addSummand: number) => { - let saveSessionSpy; + const saveSessionSpy = jest.fn(); jest.mock('../../src/session/saveSession', () => { - saveSessionSpy = jest.fn(); - return { saveSession: saveSessionSpy, }; diff --git a/packages/replay/test/unit/util/handleRecordingEmit.test.ts b/packages/replay/test/unit/util/handleRecordingEmit.test.ts new file mode 100644 index 000000000000..4762b875ce5b --- /dev/null +++ b/packages/replay/test/unit/util/handleRecordingEmit.test.ts @@ -0,0 +1,86 @@ +import { EventType } from '@sentry-internal/rrweb'; + +import { BASE_TIMESTAMP } from '../..'; +import * as SentryAddEvent from '../../../src/util/addEvent'; +import { getHandleRecordingEmit } from '../../../src/util/handleRecordingEmit'; +import { setupReplayContainer } from '../../utils/setupReplayContainer'; +import { useFakeTimers } from '../../utils/use-fake-timers'; + +useFakeTimers(); + +describe('Unit | util | handleRecordingEmit', () => { + let addEventMock: jest.SpyInstance; + + beforeEach(function () { + jest.setSystemTime(BASE_TIMESTAMP); + addEventMock = jest.spyOn(SentryAddEvent, 'addEvent').mockImplementation(async () => { + // Do nothing + }); + }); + + afterEach(function () { + addEventMock.mockReset(); + }); + + it('interprets first event as checkout event', async function () { + const replay = setupReplayContainer({ + options: { + errorSampleRate: 0, + sessionSampleRate: 1, + }, + }); + + const handler = getHandleRecordingEmit(replay); + + const event = { + type: EventType.FullSnapshot, + data: { + tag: 'test custom', + }, + timestamp: BASE_TIMESTAMP + 10, + }; + + handler(event); + await new Promise(process.nextTick); + + expect(addEventMock).toBeCalledTimes(1); + expect(addEventMock).toHaveBeenLastCalledWith(replay, event, true); + + handler(event); + await new Promise(process.nextTick); + + expect(addEventMock).toBeCalledTimes(2); + expect(addEventMock).toHaveBeenLastCalledWith(replay, event, false); + }); + + it('interprets any event with isCheckout as checkout', async function () { + const replay = setupReplayContainer({ + options: { + errorSampleRate: 0, + sessionSampleRate: 1, + }, + }); + + const handler = getHandleRecordingEmit(replay); + + const event = { + type: EventType.IncrementalSnapshot, + data: { + tag: 'test custom', + }, + timestamp: BASE_TIMESTAMP + 10, + }; + + handler(event, true); + await new Promise(process.nextTick); + + expect(addEventMock).toBeCalledTimes(1); + expect(addEventMock).toHaveBeenLastCalledWith(replay, event, true); + + handler(event, true); + await new Promise(process.nextTick); + + expect(addEventMock).toBeCalledTimes(2); + expect(addEventMock).toHaveBeenLastCalledWith(replay, event, true); + }); +}); diff --git a/packages/replay/test/utils/setupReplayContainer.ts b/packages/replay/test/utils/setupReplayContainer.ts index 9a9455a3728a..e6a427e19638 100644 --- a/packages/replay/test/utils/setupReplayContainer.ts +++ b/packages/replay/test/utils/setupReplayContainer.ts @@ -26,7 +26,7 @@ export function setupReplayContainer({ }); clearSession(replay); - replay['_setInitialState'](); + replay.setInitialState(); replay['_loadAndCheckSession'](); replay['_isEnabled'] = true; replay.eventBuffer = createEventBuffer({ From 5e4e71999a4c7b5ab351786acd272d81bff5f692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kry=C5=A1tof=20Wold=C5=99ich?= <31292499+krystofwoldrich@users.noreply.github.com> Date: Tue, 7 Mar 2023 16:30:59 +0100 Subject: [PATCH 28/44] feat(tracing): Expose cancelIdleTimeout and add option to make it permanent (#7236) --- packages/core/src/tracing/idletransaction.ts | 46 ++++++++++++++----- packages/tracing/test/idletransaction.test.ts | 39 ++++++++++++++++ 2 files changed, 74 insertions(+), 11 deletions(-) diff --git a/packages/core/src/tracing/idletransaction.ts b/packages/core/src/tracing/idletransaction.ts index aeef547ebaf5..49c7b64ea4a0 100644 --- a/packages/core/src/tracing/idletransaction.ts +++ b/packages/core/src/tracing/idletransaction.ts @@ -69,6 +69,9 @@ export class IdleTransaction extends Transaction { // We should not use heartbeat if we finished a transaction private _finished: boolean = false; + // Idle timeout was canceled and we should finish the transaction with the last span end. + private _idleTimeoutCanceledPermanently: boolean = false; + private readonly _beforeFinishCallbacks: BeforeFinishCallback[] = []; /** @@ -104,7 +107,7 @@ export class IdleTransaction extends Transaction { _idleHub.configureScope(scope => scope.setSpan(this)); } - this._startIdleTimeout(); + this._restartIdleTimeout(); setTimeout(() => { if (!this._finished) { this.setStatus('deadline_exceeded'); @@ -203,20 +206,37 @@ export class IdleTransaction extends Transaction { } /** - * Cancels the existing idletimeout, if there is one + * Cancels the existing idle timeout, if there is one. + * @param restartOnChildSpanChange Default is `true`. + * If set to false the transaction will end + * with the last child span. */ - private _cancelIdleTimeout(): void { + public cancelIdleTimeout( + endTimestamp?: Parameters[0], + { + restartOnChildSpanChange, + }: { + restartOnChildSpanChange?: boolean; + } = { + restartOnChildSpanChange: true, + }, + ): void { if (this._idleTimeoutID) { clearTimeout(this._idleTimeoutID); this._idleTimeoutID = undefined; + this._idleTimeoutCanceledPermanently = restartOnChildSpanChange === false; + + if (Object.keys(this.activities).length === 0 && this._idleTimeoutCanceledPermanently) { + this.finish(endTimestamp); + } } } /** - * Creates an idletimeout + * Restarts idle timeout, if there is no running idle timeout it will start one. */ - private _startIdleTimeout(endTimestamp?: Parameters[0]): void { - this._cancelIdleTimeout(); + private _restartIdleTimeout(endTimestamp?: Parameters[0]): void { + this.cancelIdleTimeout(); this._idleTimeoutID = setTimeout(() => { if (!this._finished && Object.keys(this.activities).length === 0) { this.finish(endTimestamp); @@ -229,7 +249,7 @@ export class IdleTransaction extends Transaction { * @param spanId The span id that represents the activity */ private _pushActivity(spanId: string): void { - this._cancelIdleTimeout(); + this.cancelIdleTimeout(); __DEBUG_BUILD__ && logger.log(`[Tracing] pushActivity: ${spanId}`); this.activities[spanId] = true; __DEBUG_BUILD__ && logger.log('[Tracing] new activities count', Object.keys(this.activities).length); @@ -248,10 +268,14 @@ export class IdleTransaction extends Transaction { } if (Object.keys(this.activities).length === 0) { - // We need to add the timeout here to have the real endtimestamp of the transaction - // Remember timestampWithMs is in seconds, timeout is in ms - const endTimestamp = timestampWithMs() + this._idleTimeout / 1000; - this._startIdleTimeout(endTimestamp); + const endTimestamp = timestampWithMs(); + if (this._idleTimeoutCanceledPermanently) { + this.finish(endTimestamp); + } else { + // We need to add the timeout here to have the real endtimestamp of the transaction + // Remember timestampWithMs is in seconds, timeout is in ms + this._restartIdleTimeout(endTimestamp + this._idleTimeout / 1000); + } } } diff --git a/packages/tracing/test/idletransaction.test.ts b/packages/tracing/test/idletransaction.test.ts index 5ac210c19a08..563c2220959c 100644 --- a/packages/tracing/test/idletransaction.test.ts +++ b/packages/tracing/test/idletransaction.test.ts @@ -247,6 +247,45 @@ describe('IdleTransaction', () => { }); }); + describe('cancelIdleTimeout', () => { + it('permanent idle timeout cancel finishes transaction if there are no activities', () => { + const idleTimeout = 10; + const transaction = new IdleTransaction({ name: 'foo', startTimestamp: 1234 }, hub, idleTimeout); + transaction.initSpanRecorder(10); + + const span = transaction.startChild({}); + span.finish(); + + jest.advanceTimersByTime(2); + + transaction.cancelIdleTimeout(undefined, { restartOnChildSpanChange: false }); + + expect(transaction.endTimestamp).toBeDefined(); + }); + + it('default idle cancel timeout is restarted by child span change', () => { + const idleTimeout = 10; + const transaction = new IdleTransaction({ name: 'foo', startTimestamp: 1234 }, hub, idleTimeout); + transaction.initSpanRecorder(10); + + const span = transaction.startChild({}); + span.finish(); + + jest.advanceTimersByTime(2); + + transaction.cancelIdleTimeout(); + + const span2 = transaction.startChild({}); + span2.finish(); + + jest.advanceTimersByTime(8); + expect(transaction.endTimestamp).toBeUndefined(); + + jest.advanceTimersByTime(2); + expect(transaction.endTimestamp).toBeDefined(); + }); + }); + describe('heartbeat', () => { it('does not mark transaction as `DeadlineExceeded` if idle timeout has not been reached', () => { // 20s to exceed 3 heartbeats From 7ab581bde042b811811915191455c50252dc9bb3 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Tue, 7 Mar 2023 18:45:47 -0500 Subject: [PATCH 29/44] feat(replay): Consider user input in form field as "user activity" (#7355) This adds user input (event from core SDK) as a trigger for user activity (to reset idle timeout). Note that this is only from input changes in a form field, it will not consider using tab key to move focus. --- .../src/coreHandlers/addBreadcrumbEvent.ts | 2 +- .../test/integration/sendReplayEvent.test.ts | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/packages/replay/src/coreHandlers/addBreadcrumbEvent.ts b/packages/replay/src/coreHandlers/addBreadcrumbEvent.ts index 8022e8a549d2..70fe932910a6 100644 --- a/packages/replay/src/coreHandlers/addBreadcrumbEvent.ts +++ b/packages/replay/src/coreHandlers/addBreadcrumbEvent.ts @@ -12,7 +12,7 @@ export function addBreadcrumbEvent(replay: ReplayContainer, breadcrumb: Breadcru return; } - if (breadcrumb.category === 'ui.click') { + if (['ui.click', 'ui.input'].includes(breadcrumb.category as string)) { replay.triggerUserActivity(); } else { replay.checkAndHandleExpiredSession(); diff --git a/packages/replay/test/integration/sendReplayEvent.test.ts b/packages/replay/test/integration/sendReplayEvent.test.ts index 4f17644a241e..356cfb33630c 100644 --- a/packages/replay/test/integration/sendReplayEvent.test.ts +++ b/packages/replay/test/integration/sendReplayEvent.test.ts @@ -129,6 +129,26 @@ describe('Integration | sendReplayEvent', () => { expect(replay.session?.lastActivity).toBe(BASE_TIMESTAMP + ELAPSED); }); + it('update last activity when user uses keyboard input', async () => { + expect(replay.session?.lastActivity).toBe(BASE_TIMESTAMP); + + domHandler({ + name: 'input', + }); + + expect(replay.session?.lastActivity).toBe(BASE_TIMESTAMP); + + // Pretend 5 seconds have passed + const ELAPSED = 5000; + jest.advanceTimersByTime(ELAPSED); + + domHandler({ + name: 'input', + }); + + expect(replay.session?.lastActivity).toBe(BASE_TIMESTAMP + ELAPSED); + }); + it('uploads a replay event if 5 seconds have elapsed since the last replay event occurred', async () => { const TEST_EVENT = { data: {}, timestamp: BASE_TIMESTAMP, type: 3 }; mockRecord._emitter(TEST_EVENT); From e8fe66864b0124b443132038329bdb38c50bd316 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 8 Mar 2023 09:19:54 +0100 Subject: [PATCH 30/44] test(replay): Add test for session max age handling (#7362) --- .../suites/replay/errorResponse/test.ts | 1 - .../suites/replay/sessionInactive/test.ts | 6 - .../suites/replay/sessionMaxAge/init.js | 22 ++++ .../suites/replay/sessionMaxAge/template.html | 10 ++ .../suites/replay/sessionMaxAge/test.ts | 89 ++++++++++++++ .../snapshot-0-chromium.json | 113 ++++++++++++++++++ .../test.ts-snapshots/snapshot-0-firefox.json | 113 ++++++++++++++++++ .../test.ts-snapshots/snapshot-0-webkit.json | 113 ++++++++++++++++++ .../test.ts-snapshots/snapshot-0.json | 113 ++++++++++++++++++ .../snapshot-2-chromium.json | 113 ++++++++++++++++++ .../test.ts-snapshots/snapshot-2-firefox.json | 113 ++++++++++++++++++ .../test.ts-snapshots/snapshot-2-webkit.json | 113 ++++++++++++++++++ .../test.ts-snapshots/snapshot-2.json | 113 ++++++++++++++++++ .../integration-tests/utils/replayHelpers.ts | 26 +++- rollup/plugins/bundlePlugins.js | 2 - 15 files changed, 1047 insertions(+), 13 deletions(-) create mode 100644 packages/integration-tests/suites/replay/sessionMaxAge/init.js create mode 100644 packages/integration-tests/suites/replay/sessionMaxAge/template.html create mode 100644 packages/integration-tests/suites/replay/sessionMaxAge/test.ts create mode 100644 packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-chromium.json create mode 100644 packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-firefox.json create mode 100644 packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-webkit.json create mode 100644 packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0.json create mode 100644 packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-chromium.json create mode 100644 packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-firefox.json create mode 100644 packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-webkit.json create mode 100644 packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2.json diff --git a/packages/integration-tests/suites/replay/errorResponse/test.ts b/packages/integration-tests/suites/replay/errorResponse/test.ts index d81d16196b8e..2c40666096ee 100644 --- a/packages/integration-tests/suites/replay/errorResponse/test.ts +++ b/packages/integration-tests/suites/replay/errorResponse/test.ts @@ -39,6 +39,5 @@ sentryTest('should stop recording after receiving an error response', async ({ g const replay = await getReplaySnapshot(page); - // @ts-ignore private API expect(replay._isEnabled).toBe(false); }); diff --git a/packages/integration-tests/suites/replay/sessionInactive/test.ts b/packages/integration-tests/suites/replay/sessionInactive/test.ts index e4a1e6d8b243..ed53f155feea 100644 --- a/packages/integration-tests/suites/replay/sessionInactive/test.ts +++ b/packages/integration-tests/suites/replay/sessionInactive/test.ts @@ -52,9 +52,7 @@ sentryTest('handles an inactive session', async ({ getLocalTestPath, page }) => // nothing happened because no activity/inactivity was detected const replay = await getReplaySnapshot(page); - // @ts-ignore private api expect(replay._isEnabled).toEqual(true); - // @ts-ignore private api expect(replay._isPaused).toEqual(false); // Now we trigger a blur event, which should move the session to paused mode @@ -63,9 +61,7 @@ sentryTest('handles an inactive session', async ({ getLocalTestPath, page }) => }); const replay2 = await getReplaySnapshot(page); - // @ts-ignore private api expect(replay2._isEnabled).toEqual(true); - // @ts-ignore private api expect(replay2._isPaused).toEqual(true); // Trigger an action, should re-start the recording @@ -73,9 +69,7 @@ sentryTest('handles an inactive session', async ({ getLocalTestPath, page }) => const req1 = await reqPromise1; const replay3 = await getReplaySnapshot(page); - // @ts-ignore private api expect(replay3._isEnabled).toEqual(true); - // @ts-ignore private api expect(replay3._isPaused).toEqual(false); const replayEvent1 = getReplayEvent(req1); diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/init.js b/packages/integration-tests/suites/replay/sessionMaxAge/init.js new file mode 100644 index 000000000000..cf98205a5576 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/init.js @@ -0,0 +1,22 @@ +import * as Sentry from '@sentry/browser'; + +window.Sentry = Sentry; +window.Replay = new Sentry.Replay({ + flushMinDelay: 500, + flushMaxDelay: 500, +}); + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + sampleRate: 0, + replaysSessionSampleRate: 1.0, + replaysOnErrorSampleRate: 0.0, + debug: true, + + integrations: [window.Replay], +}); + +window.Replay._replay.timeouts = { + sessionIdle: 300000, // default: 5min + maxSessionLife: 4000, // this is usually 60min, but we want to test this with shorter times +}; diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/template.html b/packages/integration-tests/suites/replay/sessionMaxAge/template.html new file mode 100644 index 000000000000..7223a20f82ba --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/template.html @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/test.ts b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts new file mode 100644 index 000000000000..89ad76ea4d4a --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts @@ -0,0 +1,89 @@ +import { expect } from '@playwright/test'; + +import { sentryTest } from '../../../utils/fixtures'; +import { getExpectedReplayEvent } from '../../../utils/replayEventTemplates'; +import { + getFullRecordingSnapshots, + getReplayEvent, + getReplaySnapshot, + normalize, + shouldSkipReplayTest, + waitForReplayRequest, +} from '../../../utils/replayHelpers'; + +// Session should be max. 4s long +const SESSION_MAX_AGE = 4000; + +/* + The main difference between this and sessionExpiry test, is that here we wait for the overall time (4s) + in multiple steps (2s, 2s) instead of waiting for the whole time at once (4s). +*/ +sentryTest('handles session that exceeds max age', async ({ getLocalTestPath, page }) => { + if (shouldSkipReplayTest()) { + sentryTest.skip(); + } + + const reqPromise0 = waitForReplayRequest(page, 0); + const reqPromise1 = waitForReplayRequest(page, 1); + + await page.route('https://dsn.ingest.sentry.io/**/*', route => { + return route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ id: 'test-id' }), + }); + }); + + const url = await getLocalTestPath({ testDir: __dirname }); + + await page.goto(url); + + const replay0 = await getReplaySnapshot(page); + // We use the `initialTimestamp` of the replay to do any time based calculations + const startTimestamp = replay0._context.initialTimestamp; + + const req0 = await reqPromise0; + + const replayEvent0 = getReplayEvent(req0); + expect(replayEvent0).toEqual(getExpectedReplayEvent({})); + + const fullSnapshots0 = getFullRecordingSnapshots(req0); + expect(fullSnapshots0.length).toEqual(1); + const stringifiedSnapshot = normalize(fullSnapshots0[0]); + expect(stringifiedSnapshot).toMatchSnapshot('snapshot-0.json'); + + // Wait again for a new segment 0 (=new session) + const reqPromise2 = waitForReplayRequest(page, 0); + + // Wait for an incremental snapshot + // Wait half of the session max age (after initial flush), but account for potentially slow runners + const timePassed1 = Date.now() - startTimestamp; + await new Promise(resolve => setTimeout(resolve, Math.max(SESSION_MAX_AGE / 2 - timePassed1, 0))); + await page.click('#button1'); + + const req1 = await reqPromise1; + const replayEvent1 = getReplayEvent(req1); + + expect(replayEvent1).toEqual(getExpectedReplayEvent({ replay_start_timestamp: undefined, segment_id: 1, urls: [] })); + + const replay1 = await getReplaySnapshot(page); + const oldSessionId = replay1.session?.id; + + // Wait for session to expire + const timePassed2 = Date.now() - startTimestamp; + await new Promise(resolve => setTimeout(resolve, Math.max(SESSION_MAX_AGE - timePassed2, 0))); + await page.click('#button2'); + + const req2 = await reqPromise2; + const replay2 = await getReplaySnapshot(page); + + expect(replay2.session?.id).not.toEqual(oldSessionId); + + const replayEvent2 = getReplayEvent(req2); + expect(replayEvent2).toEqual(getExpectedReplayEvent({})); + + const fullSnapshots2 = getFullRecordingSnapshots(req2); + expect(fullSnapshots2.length).toEqual(1); + const stringifiedSnapshot2 = normalize(fullSnapshots2[0]); + expect(stringifiedSnapshot2).toMatchSnapshot('snapshot-2.json'); +}); diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-chromium.json b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-chromium.json new file mode 100644 index 000000000000..d510b410a343 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-chromium.json @@ -0,0 +1,113 @@ +{ + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } + }, + "timestamp": [timestamp] +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-firefox.json b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-firefox.json new file mode 100644 index 000000000000..d510b410a343 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-firefox.json @@ -0,0 +1,113 @@ +{ + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } + }, + "timestamp": [timestamp] +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-webkit.json b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-webkit.json new file mode 100644 index 000000000000..d510b410a343 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0-webkit.json @@ -0,0 +1,113 @@ +{ + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } + }, + "timestamp": [timestamp] +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0.json b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0.json new file mode 100644 index 000000000000..d510b410a343 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-0.json @@ -0,0 +1,113 @@ +{ + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } + }, + "timestamp": [timestamp] +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-chromium.json b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-chromium.json new file mode 100644 index 000000000000..d510b410a343 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-chromium.json @@ -0,0 +1,113 @@ +{ + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } + }, + "timestamp": [timestamp] +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-firefox.json b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-firefox.json new file mode 100644 index 000000000000..d510b410a343 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-firefox.json @@ -0,0 +1,113 @@ +{ + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } + }, + "timestamp": [timestamp] +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-webkit.json b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-webkit.json new file mode 100644 index 000000000000..d510b410a343 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2-webkit.json @@ -0,0 +1,113 @@ +{ + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } + }, + "timestamp": [timestamp] +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2.json b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2.json new file mode 100644 index 000000000000..d510b410a343 --- /dev/null +++ b/packages/integration-tests/suites/replay/sessionMaxAge/test.ts-snapshots/snapshot-2.json @@ -0,0 +1,113 @@ +{ + "type": 2, + "data": { + "node": { + "type": 0, + "childNodes": [ + { + "type": 1, + "name": "html", + "publicId": "", + "systemId": "", + "id": 2 + }, + { + "type": 2, + "tagName": "html", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "head", + "attributes": {}, + "childNodes": [ + { + "type": 2, + "tagName": "meta", + "attributes": { + "charset": "utf-8" + }, + "childNodes": [], + "id": 5 + } + ], + "id": 4 + }, + { + "type": 3, + "textContent": "\n ", + "id": 6 + }, + { + "type": 2, + "tagName": "body", + "attributes": {}, + "childNodes": [ + { + "type": 3, + "textContent": "\n ", + "id": 8 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 1')", + "id": "button1" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 10 + } + ], + "id": 9 + }, + { + "type": 3, + "textContent": "\n ", + "id": 11 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "onclick": "console.log('Test log 2')", + "id": "button2" + }, + "childNodes": [ + { + "type": 3, + "textContent": "***** **", + "id": 13 + } + ], + "id": 12 + }, + { + "type": 3, + "textContent": "\n ", + "id": 14 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 15 + } + ], + "id": 7 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } + }, + "timestamp": [timestamp] +} \ No newline at end of file diff --git a/packages/integration-tests/utils/replayHelpers.ts b/packages/integration-tests/utils/replayHelpers.ts index a4dd02c068a4..c5c3e1f50ae9 100644 --- a/packages/integration-tests/utils/replayHelpers.ts +++ b/packages/integration-tests/utils/replayHelpers.ts @@ -1,4 +1,9 @@ -import type { RecordingEvent, ReplayContainer } from '@sentry/replay/build/npm/types/types'; +import type { + InternalEventContext, + RecordingEvent, + ReplayContainer, + Session, +} from '@sentry/replay/build/npm/types/types'; import type { eventWithTime } from '@sentry/replay/build/npm/types/types/rrweb'; import type { Breadcrumb, Event, ReplayEvent } from '@sentry/types'; import pako from 'pako'; @@ -67,9 +72,22 @@ export function isReplayEvent(event: Event): event is ReplayEvent { * Note that due to how this works with playwright, this is a POJO copy of replay. * This means that we cannot access any methods on it, and also not mutate it in any way. */ -export async function getReplaySnapshot(page: Page): Promise { - const replayIntegration = await page.evaluate<{ _replay: ReplayContainer }>('window.Replay'); - return replayIntegration._replay; +export async function getReplaySnapshot( + page: Page, +): Promise<{ _isPaused: boolean; _isEnabled: boolean; _context: InternalEventContext; session: Session | undefined }> { + return await page.evaluate(() => { + const replayIntegration = (window as unknown as Window & { Replay: { _replay: ReplayContainer } }).Replay; + const replay = replayIntegration._replay; + + const replaySnapshot = { + _isPaused: replay.isPaused(), + _isEnabled: replay.isEnabled(), + _context: replay.getContext(), + session: replay.session, + }; + + return replaySnapshot; + }); } export const REPLAY_DEFAULT_FLUSH_MAX_DELAY = 5_000; diff --git a/rollup/plugins/bundlePlugins.js b/rollup/plugins/bundlePlugins.js index 752b3908f2e8..49dcaefbdf73 100644 --- a/rollup/plugins/bundlePlugins.js +++ b/rollup/plugins/bundlePlugins.js @@ -118,8 +118,6 @@ export function makeTerserPlugin() { '_support', // We want to keep some replay fields unmangled to enable integration tests to access them '_replay', - '_isEnabled', - '_isPaused', // We also can't mangle rrweb private fields when bundling rrweb in the replay CDN bundles '_cssText', // We want to keep the _integrations variable unmangled to send all installed integrations from replay From 095798981231af363488f5712f80b2707a34e718 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Wed, 8 Mar 2023 11:01:42 +0100 Subject: [PATCH 31/44] ref(tracing): Revert conditional exports usage (#7372) --- packages/tracing/package.json | 30 --------------------------- packages/tracing/rollup.npm.config.js | 1 - 2 files changed, 31 deletions(-) diff --git a/packages/tracing/package.json b/packages/tracing/package.json index 6187925a799e..24870fadcdd3 100644 --- a/packages/tracing/package.json +++ b/packages/tracing/package.json @@ -12,36 +12,6 @@ "main": "build/npm/cjs/index.js", "module": "build/npm/esm/index.js", "types": "build/npm/types/index.d.ts", - "exports": { - ".": { - "import": "./build/npm/esm/index.js", - "require": "./build/npm/cjs/index.js", - "types": "./build/npm/types/index.d.ts" - }, - "./node": { - "import": "./build/npm/esm/node/index.js", - "require": "./build/npm/cjs/node/index.js", - "types": "./build/npm/types/node/index.d.ts" - }, - "./browser": { - "import": "./build/npm/esm/browser/index.js", - "require": "./build/npm/cjs/browser/index.js", - "types": "./build/npm/types/browser/index.d.ts" - } - }, - "typesVersions": { - "*": { - "*": [ - "./build/npm/types/index.d.ts" - ], - "node": [ - "./build/npm/types/node/index.d.ts" - ], - "browser": [ - "./build/npm/types/browser/index.d.ts" - ] - } - }, "publishConfig": { "access": "public" }, diff --git a/packages/tracing/rollup.npm.config.js b/packages/tracing/rollup.npm.config.js index a7588e2a9538..4ffa8b9396d8 100644 --- a/packages/tracing/rollup.npm.config.js +++ b/packages/tracing/rollup.npm.config.js @@ -2,7 +2,6 @@ import { makeBaseNPMConfig, makeNPMConfigVariants } from '../../rollup/index.js' export default makeNPMConfigVariants( makeBaseNPMConfig({ - entrypoints: ['src/browser/index.ts', 'src/node/index.ts', 'src/index.ts'], // packages with bundles have a different build directory structure hasBundles: true, }), From a1dab3b73c5cfbe89815ef028f171f95834fa76f Mon Sep 17 00:00:00 2001 From: Jonas Date: Wed, 8 Mar 2023 05:02:21 -0500 Subject: [PATCH 32/44] ref(node): parallelize disk io when reading source files for context lines (#7374) --- .../node/src/integrations/contextlines.ts | 52 ++++++++++++++++--- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/packages/node/src/integrations/contextlines.ts b/packages/node/src/integrations/contextlines.ts index aa41ae68cdd8..f3cebc1d4037 100644 --- a/packages/node/src/integrations/contextlines.ts +++ b/packages/node/src/integrations/contextlines.ts @@ -62,10 +62,48 @@ export class ContextLines implements Integration { /** Processes an event and adds context lines */ public async addSourceContext(event: Event): Promise { + // keep a lookup map of which files we've already enqueued to read, + // so we don't enqueue the same file multiple times which would cause multiple i/o reads + const enqueuedReadSourceFileTasks: Record = {}; + const readSourceFileTasks: Promise[] = []; + + if (this._contextLines > 0 && event.exception?.values) { + for (const exception of event.exception.values) { + if (!exception.stacktrace?.frames) { + continue; + } + + // We want to iterate in reverse order as calling cache.get will bump the file in our LRU cache. + // This ends up prioritizes source context for frames at the top of the stack instead of the bottom. + for (let i = exception.stacktrace.frames.length - 1; i >= 0; i--) { + const frame = exception.stacktrace.frames[i]; + // Call cache.get to bump the file to the top of the cache and ensure we have not already + // enqueued a read operation for this filename + if ( + frame.filename && + !enqueuedReadSourceFileTasks[frame.filename] && + !FILE_CONTENT_CACHE.get(frame.filename) + ) { + readSourceFileTasks.push(_readSourceFile(frame.filename)); + enqueuedReadSourceFileTasks[frame.filename] = 1; + } + } + } + } + + // check if files to read > 0, if so, await all of them to be read before adding source contexts. + // Normally, Promise.all here could be short circuited if one of the promises rejects, but we + // are guarding from that by wrapping the i/o read operation in a try/catch. + if (readSourceFileTasks.length > 0) { + await Promise.all(readSourceFileTasks); + } + + // Perform the same loop as above, but this time we can assume all files are in the cache + // and attempt to add source context to frames. if (this._contextLines > 0 && event.exception?.values) { for (const exception of event.exception.values) { if (exception.stacktrace?.frames) { - await this.addSourceContextToFrames(exception.stacktrace.frames); + this.addSourceContextToFrames(exception.stacktrace.frames); } } } @@ -74,18 +112,16 @@ export class ContextLines implements Integration { } /** Adds context lines to frames */ - public async addSourceContextToFrames(frames: StackFrame[]): Promise { - const contextLines = this._contextLines; - + public addSourceContextToFrames(frames: StackFrame[]): void { for (const frame of frames) { // Only add context if we have a filename and it hasn't already been added if (frame.filename && frame.context_line === undefined) { - const sourceFile = await _readSourceFile(frame.filename); + const sourceFile = FILE_CONTENT_CACHE.get(frame.filename); if (sourceFile) { try { const lines = sourceFile.split('\n'); - addContextToFrame(lines, frame, contextLines); + addContextToFrame(lines, frame, this._contextLines); } catch (e) { // anomaly, being defensive in case // unlikely to ever happen in practice but can definitely happen in theory @@ -109,6 +145,10 @@ async function _readSourceFile(filename: string): Promise { } let content: string | null = null; + + // Guard from throwing if readFile fails, this enables us to use Promise.all and + // not have it short circuiting if one of the promises rejects + since context lines are added + // on a best effort basis, we want to throw here anyways. try { content = await readTextFileAsync(filename); } catch (_) { From ec70b54a26e90b36b285f17de1c0409ee1e416fa Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Wed, 8 Mar 2023 13:35:24 +0000 Subject: [PATCH 33/44] fix: Make redux integration be configurable via `normalizeDepth` --- packages/react/src/redux.ts | 20 +++++++++- packages/utils/src/normalize.ts | 15 ++++++-- packages/utils/test/normalize.test.ts | 54 +++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 5 deletions(-) diff --git a/packages/react/src/redux.ts b/packages/react/src/redux.ts index 5ef64a3d2522..eeecd7290d68 100644 --- a/packages/react/src/redux.ts +++ b/packages/react/src/redux.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { configureScope } from '@sentry/browser'; +import { configureScope, getCurrentHub } from '@sentry/browser'; import type { Scope } from '@sentry/types'; +import { addNonEnumerableProperty } from '@sentry/utils'; interface Action { type: T; @@ -105,7 +106,22 @@ function createReduxEnhancer(enhancerOptions?: Partial): /* Set latest state to scope */ const transformedState = options.stateTransformer(newState); if (typeof transformedState !== 'undefined' && transformedState !== null) { - scope.setContext('state', { state: { type: 'redux', value: transformedState } }); + const client = getCurrentHub().getClient(); + const options = client && client.getOptions(); + const normalizationDepth = options && options.normalizeDepth; + + // Set the normalization depth of the redux state to the configured `normalizeDepth` option or a sane number as a fallback + addNonEnumerableProperty( + transformedState, + '__sentry_override_normalization_depth__', + normalizationDepth || 3, + ); + + // Make sure the state is always reached during normalization + const newStateContext = { state: { type: 'redux', value: transformedState } }; + addNonEnumerableProperty(newStateContext, '__sentry_override_normalization_depth__', 3); + + scope.setContext('state', newStateContext); } else { scope.setContext('state', null); } diff --git a/packages/utils/src/normalize.ts b/packages/utils/src/normalize.ts index b10f78f39e98..20e72e158caa 100644 --- a/packages/utils/src/normalize.ts +++ b/packages/utils/src/normalize.ts @@ -100,8 +100,17 @@ function visit( return value as ObjOrArray; } + // Do not normalize objects that we know have already been normalized. As a general rule, the + // "__sentry_skip_normalization__" property should only be used sparingly and only should only be set on objects that + // have already been normalized. + let overriddenDepth = depth; + + if ((value as ObjOrArray)['__sentry_override_normalization_depth__']) { + overriddenDepth = (value as ObjOrArray)['__sentry_override_normalization_depth__'] as number; + } + // We're also done if we've reached the max depth - if (depth === 0) { + if (overriddenDepth === 0) { // At this point we know `serialized` is a string of the form `"[object XXXX]"`. Clean it up so it's just `"[XXXX]"`. return stringified.replace('object ', ''); } @@ -117,7 +126,7 @@ function visit( try { const jsonValue = valueWithToJSON.toJSON(); // We need to normalize the return value of `.toJSON()` in case it has circular references - return visit('', jsonValue, depth - 1, maxProperties, memo); + return visit('', jsonValue, overriddenDepth - 1, maxProperties, memo); } catch (err) { // pass (The built-in `toJSON` failed, but we can still try to do it ourselves) } @@ -146,7 +155,7 @@ function visit( // Recursively visit all the child nodes const visitValue = visitable[visitKey]; - normalized[visitKey] = visit(visitKey, visitValue, depth - 1, maxProperties, memo); + normalized[visitKey] = visit(visitKey, visitValue, overriddenDepth - 1, maxProperties, memo); numAdded++; } diff --git a/packages/utils/test/normalize.test.ts b/packages/utils/test/normalize.test.ts index 1319805e9488..94676c1449da 100644 --- a/packages/utils/test/normalize.test.ts +++ b/packages/utils/test/normalize.test.ts @@ -582,4 +582,58 @@ describe('normalize()', () => { expect(result?.foo?.bar?.boo?.bam?.pow).not.toBe('poof'); }); }); + + describe('overrides normalization depth with a non-enumerable property __sentry_override_normalization_depth__', () => { + test('by increasing depth if it is higher', () => { + const normalizationTarget = { + foo: 'bar', + baz: 42, + obj: { + obj: { + obj: { + bestSmashCharacter: 'Cpt. Falcon', + }, + }, + }, + }; + + addNonEnumerableProperty(normalizationTarget, '__sentry_override_normalization_depth__', 3); + + const result = normalize(normalizationTarget, 1); + + expect(result).toEqual({ + baz: 42, + foo: 'bar', + obj: { + obj: { + obj: '[Object]', + }, + }, + }); + }); + + test('by decreasing depth if it is lower', () => { + const normalizationTarget = { + foo: 'bar', + baz: 42, + obj: { + obj: { + obj: { + bestSmashCharacter: 'Cpt. Falcon', + }, + }, + }, + }; + + addNonEnumerableProperty(normalizationTarget, '__sentry_override_normalization_depth__', 1); + + const result = normalize(normalizationTarget, 3); + + expect(result).toEqual({ + baz: 42, + foo: 'bar', + obj: '[Object]', + }); + }); + }); }); From ec78a028090adad5a53e2b23c8f34f5c761d6f5d Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Wed, 8 Mar 2023 15:20:15 +0000 Subject: [PATCH 34/44] adress review --- packages/react/src/redux.ts | 12 +++++------- packages/utils/src/normalize.ts | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/react/src/redux.ts b/packages/react/src/redux.ts index eeecd7290d68..5bac99dbe511 100644 --- a/packages/react/src/redux.ts +++ b/packages/react/src/redux.ts @@ -108,19 +108,17 @@ function createReduxEnhancer(enhancerOptions?: Partial): if (typeof transformedState !== 'undefined' && transformedState !== null) { const client = getCurrentHub().getClient(); const options = client && client.getOptions(); - const normalizationDepth = options && options.normalizeDepth; + const normalizationDepth = (options && options.normalizeDepth) || 3; // default state normalization depth to 3 // Set the normalization depth of the redux state to the configured `normalizeDepth` option or a sane number as a fallback + const newStateContext = { state: { type: 'redux', value: transformedState } }; addNonEnumerableProperty( - transformedState, + newStateContext, '__sentry_override_normalization_depth__', - normalizationDepth || 3, + 3 + // 3 layers for `state.value.transformedState` + normalizationDepth, // rest for the actual state ); - // Make sure the state is always reached during normalization - const newStateContext = { state: { type: 'redux', value: transformedState } }; - addNonEnumerableProperty(newStateContext, '__sentry_override_normalization_depth__', 3); - scope.setContext('state', newStateContext); } else { scope.setContext('state', null); diff --git a/packages/utils/src/normalize.ts b/packages/utils/src/normalize.ts index 20e72e158caa..508442c2d14e 100644 --- a/packages/utils/src/normalize.ts +++ b/packages/utils/src/normalize.ts @@ -105,7 +105,7 @@ function visit( // have already been normalized. let overriddenDepth = depth; - if ((value as ObjOrArray)['__sentry_override_normalization_depth__']) { + if (typeof (value as ObjOrArray)['__sentry_override_normalization_depth__'] === 'number') { overriddenDepth = (value as ObjOrArray)['__sentry_override_normalization_depth__'] as number; } From 17f31c6011a3dd229c00db05b5e6bc6c96fcb1d6 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Wed, 8 Mar 2023 16:21:39 +0100 Subject: [PATCH 35/44] ref(node): Partially remove dynamic `require` calls (#7377) Remove a few dynamic `require` calls from our Node SDK in favor of making them top-level imports. * `Http` integration: `http` and `https` are now top-level imports. * Transport: `https-proxy-agent` is now a top-level import as v5 no longer produces side effects when importing. We need this change for the SvelteKit SDK, as SvelteKit doesn't accept `require` calls in server code by default. --- packages/node/src/declarations.d.ts | 1 - packages/node/src/integrations/http.ts | 24 +++++--------- .../node/src/integrations/localvariables.ts | 13 ++++++++ packages/node/src/transports/http.ts | 4 +-- packages/node/test/transports/http.test.ts | 29 ++++++++-------- packages/node/test/transports/https.test.ts | 33 ++++++++++--------- 6 files changed, 55 insertions(+), 49 deletions(-) diff --git a/packages/node/src/declarations.d.ts b/packages/node/src/declarations.d.ts index 7d9d77b82bfb..843b79454518 100644 --- a/packages/node/src/declarations.d.ts +++ b/packages/node/src/declarations.d.ts @@ -1,2 +1 @@ -declare module 'https-proxy-agent'; declare module 'async-limiter'; diff --git a/packages/node/src/integrations/http.ts b/packages/node/src/integrations/http.ts index ea7a9eae173d..017929fbe0eb 100644 --- a/packages/node/src/integrations/http.ts +++ b/packages/node/src/integrations/http.ts @@ -8,8 +8,8 @@ import { parseSemver, stringMatchesSomePattern, } from '@sentry/utils'; -import type * as http from 'http'; -import type * as https from 'https'; +import * as http from 'http'; +import * as https from 'https'; import { LRUMap } from 'lru_map'; import type { NodeClient } from '../client'; @@ -101,25 +101,17 @@ export class Http implements Integration { // and we will no longer have to do this optional merge, we can just pass `this._tracing` directly. const tracingOptions = this._tracing ? { ...clientOptions, ...this._tracing } : undefined; - // eslint-disable-next-line @typescript-eslint/no-var-requires - const httpModule = require('http'); - const wrappedHttpHandlerMaker = _createWrappedRequestMethodFactory(this._breadcrumbs, tracingOptions, httpModule); - fill(httpModule, 'get', wrappedHttpHandlerMaker); - fill(httpModule, 'request', wrappedHttpHandlerMaker); + const wrappedHttpHandlerMaker = _createWrappedRequestMethodFactory(this._breadcrumbs, tracingOptions, http); + fill(http, 'get', wrappedHttpHandlerMaker); + fill(http, 'request', wrappedHttpHandlerMaker); // NOTE: Prior to Node 9, `https` used internals of `http` module, thus we don't patch it. // If we do, we'd get double breadcrumbs and double spans for `https` calls. // It has been changed in Node 9, so for all versions equal and above, we patch `https` separately. if (NODE_VERSION.major && NODE_VERSION.major > 8) { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const httpsModule = require('https'); - const wrappedHttpsHandlerMaker = _createWrappedRequestMethodFactory( - this._breadcrumbs, - tracingOptions, - httpsModule, - ); - fill(httpsModule, 'get', wrappedHttpsHandlerMaker); - fill(httpsModule, 'request', wrappedHttpsHandlerMaker); + const wrappedHttpsHandlerMaker = _createWrappedRequestMethodFactory(this._breadcrumbs, tracingOptions, https); + fill(https, 'get', wrappedHttpsHandlerMaker); + fill(https, 'request', wrappedHttpsHandlerMaker); } } } diff --git a/packages/node/src/integrations/localvariables.ts b/packages/node/src/integrations/localvariables.ts index 2423cfa30c70..648a9e88d3be 100644 --- a/packages/node/src/integrations/localvariables.ts +++ b/packages/node/src/integrations/localvariables.ts @@ -28,6 +28,19 @@ class AsyncSession implements DebugSession { /** Throws is inspector API is not available */ public constructor() { + /* + TODO: We really should get rid of this require statement below for a couple of reasons: + 1. It makes the integration unusable in the SvelteKit SDK, as it's not possible to use `require` + in SvelteKit server code (at least not by default). + 2. Throwing in a constructor is bad practice + + More context for a future attempt to fix this: + We already tried replacing it with import but didn't get it to work because of async problems. + We still called import in the constructor but assigned to a promise which we "awaited" in + `configureAndConnect`. However, this broke the Node integration tests as no local variables + were reported any more. We probably missed a place where we need to await the promise, too. + */ + // Node can be build without inspector support so this can throw // eslint-disable-next-line @typescript-eslint/no-var-requires const { Session } = require('inspector'); diff --git a/packages/node/src/transports/http.ts b/packages/node/src/transports/http.ts index a16f78e79a6f..340bcf4800f0 100644 --- a/packages/node/src/transports/http.ts +++ b/packages/node/src/transports/http.ts @@ -8,6 +8,7 @@ import type { } from '@sentry/types'; import * as http from 'http'; import * as https from 'https'; +import { HttpsProxyAgent } from 'https-proxy-agent'; import { Readable } from 'stream'; import { URL } from 'url'; import { createGzip } from 'zlib'; @@ -74,8 +75,7 @@ export function makeNodeTransport(options: NodeTransportOptions): Transport { // TODO(v7): Evaluate if we can set keepAlive to true. This would involve testing for memory leaks in older node // versions(>= 8) as they had memory leaks when using it: #2555 const agent = proxy - ? // eslint-disable-next-line @typescript-eslint/no-var-requires - (new (require('https-proxy-agent'))(proxy) as http.Agent) + ? (new HttpsProxyAgent(proxy) as http.Agent) : new nativeHttpModule.Agent({ keepAlive, maxSockets: 30, timeout: 2000 }); const requestExecutor = createRequestExecutor(options, options.httpModule ?? nativeHttpModule, agent); diff --git a/packages/node/test/transports/http.test.ts b/packages/node/test/transports/http.test.ts index d03e917c4f42..58b2710f1ac5 100644 --- a/packages/node/test/transports/http.test.ts +++ b/packages/node/test/transports/http.test.ts @@ -17,11 +17,7 @@ jest.mock('@sentry/core', () => { }; }); -// eslint-disable-next-line @typescript-eslint/no-var-requires -const httpProxyAgent = require('https-proxy-agent'); -jest.mock('https-proxy-agent', () => { - return jest.fn().mockImplementation(() => new http.Agent({ keepAlive: false, maxSockets: 30, timeout: 2000 })); -}); +import * as httpProxyAgent from 'https-proxy-agent'; const SUCCESS = 200; const RATE_LIMIT = 429; @@ -211,6 +207,11 @@ describe('makeNewHttpTransport()', () => { }); describe('proxy', () => { + const proxyAgentSpy = jest + .spyOn(httpProxyAgent, 'HttpsProxyAgent') + // @ts-ignore + .mockImplementation(() => new http.Agent({ keepAlive: false, maxSockets: 30, timeout: 2000 })); + it('can be configured through option', () => { makeNodeTransport({ ...defaultOptions, @@ -218,8 +219,8 @@ describe('makeNewHttpTransport()', () => { proxy: 'http://example.com', }); - expect(httpProxyAgent).toHaveBeenCalledTimes(1); - expect(httpProxyAgent).toHaveBeenCalledWith('http://example.com'); + expect(proxyAgentSpy).toHaveBeenCalledTimes(1); + expect(proxyAgentSpy).toHaveBeenCalledWith('http://example.com'); }); it('can be configured through env variables option', () => { @@ -229,8 +230,8 @@ describe('makeNewHttpTransport()', () => { url: 'http://9e9fd4523d784609a5fc0ebb1080592f@sentry.io:8989/mysubpath/50622', }); - expect(httpProxyAgent).toHaveBeenCalledTimes(1); - expect(httpProxyAgent).toHaveBeenCalledWith('http://example.com'); + expect(proxyAgentSpy).toHaveBeenCalledTimes(1); + expect(proxyAgentSpy).toHaveBeenCalledWith('http://example.com'); delete process.env.http_proxy; }); @@ -242,8 +243,8 @@ describe('makeNewHttpTransport()', () => { proxy: 'http://bar.com', }); - expect(httpProxyAgent).toHaveBeenCalledTimes(1); - expect(httpProxyAgent).toHaveBeenCalledWith('http://bar.com'); + expect(proxyAgentSpy).toHaveBeenCalledTimes(1); + expect(proxyAgentSpy).toHaveBeenCalledWith('http://bar.com'); delete process.env.http_proxy; }); @@ -255,7 +256,7 @@ describe('makeNewHttpTransport()', () => { proxy: 'http://example.com', }); - expect(httpProxyAgent).not.toHaveBeenCalled(); + expect(proxyAgentSpy).not.toHaveBeenCalled(); delete process.env.no_proxy; }); @@ -269,7 +270,7 @@ describe('makeNewHttpTransport()', () => { url: 'http://9e9fd4523d784609a5fc0ebb1080592f@sentry.io:8989/mysubpath/50622', }); - expect(httpProxyAgent).not.toHaveBeenCalled(); + expect(proxyAgentSpy).not.toHaveBeenCalled(); delete process.env.no_proxy; delete process.env.http_proxy; @@ -284,7 +285,7 @@ describe('makeNewHttpTransport()', () => { url: 'http://9e9fd4523d784609a5fc0ebb1080592f@sentry.io:8989/mysubpath/50622', }); - expect(httpProxyAgent).not.toHaveBeenCalled(); + expect(proxyAgentSpy).not.toHaveBeenCalled(); delete process.env.no_proxy; delete process.env.http_proxy; diff --git a/packages/node/test/transports/https.test.ts b/packages/node/test/transports/https.test.ts index d43b8306bed0..e63898a3b11e 100644 --- a/packages/node/test/transports/https.test.ts +++ b/packages/node/test/transports/https.test.ts @@ -19,11 +19,7 @@ jest.mock('@sentry/core', () => { }; }); -// eslint-disable-next-line @typescript-eslint/no-var-requires -const httpProxyAgent = require('https-proxy-agent'); -jest.mock('https-proxy-agent', () => { - return jest.fn().mockImplementation(() => new http.Agent({ keepAlive: false, maxSockets: 30, timeout: 2000 })); -}); +import * as httpProxyAgent from 'https-proxy-agent'; const SUCCESS = 200; const RATE_LIMIT = 429; @@ -185,6 +181,11 @@ describe('makeNewHttpsTransport()', () => { }); describe('proxy', () => { + const proxyAgentSpy = jest + .spyOn(httpProxyAgent, 'HttpsProxyAgent') + // @ts-ignore + .mockImplementation(() => new http.Agent({ keepAlive: false, maxSockets: 30, timeout: 2000 })); + it('can be configured through option', () => { makeNodeTransport({ ...defaultOptions, @@ -193,8 +194,8 @@ describe('makeNewHttpsTransport()', () => { proxy: 'https://example.com', }); - expect(httpProxyAgent).toHaveBeenCalledTimes(1); - expect(httpProxyAgent).toHaveBeenCalledWith('https://example.com'); + expect(proxyAgentSpy).toHaveBeenCalledTimes(1); + expect(proxyAgentSpy).toHaveBeenCalledWith('https://example.com'); }); it('can be configured through env variables option (http)', () => { @@ -205,8 +206,8 @@ describe('makeNewHttpsTransport()', () => { url: 'https://9e9fd4523d784609a5fc0ebb1080592f@sentry.io:8989/mysubpath/50622', }); - expect(httpProxyAgent).toHaveBeenCalledTimes(1); - expect(httpProxyAgent).toHaveBeenCalledWith('https://example.com'); + expect(proxyAgentSpy).toHaveBeenCalledTimes(1); + expect(proxyAgentSpy).toHaveBeenCalledWith('https://example.com'); delete process.env.http_proxy; }); @@ -218,8 +219,8 @@ describe('makeNewHttpsTransport()', () => { url: 'https://9e9fd4523d784609a5fc0ebb1080592f@sentry.io:8989/mysubpath/50622', }); - expect(httpProxyAgent).toHaveBeenCalledTimes(1); - expect(httpProxyAgent).toHaveBeenCalledWith('https://example.com'); + expect(proxyAgentSpy).toHaveBeenCalledTimes(1); + expect(proxyAgentSpy).toHaveBeenCalledWith('https://example.com'); delete process.env.https_proxy; }); @@ -232,8 +233,8 @@ describe('makeNewHttpsTransport()', () => { proxy: 'https://bar.com', }); - expect(httpProxyAgent).toHaveBeenCalledTimes(1); - expect(httpProxyAgent).toHaveBeenCalledWith('https://bar.com'); + expect(proxyAgentSpy).toHaveBeenCalledTimes(1); + expect(proxyAgentSpy).toHaveBeenCalledWith('https://bar.com'); delete process.env.https_proxy; }); @@ -246,7 +247,7 @@ describe('makeNewHttpsTransport()', () => { proxy: 'https://example.com', }); - expect(httpProxyAgent).not.toHaveBeenCalled(); + expect(proxyAgentSpy).not.toHaveBeenCalled(); delete process.env.no_proxy; }); @@ -261,7 +262,7 @@ describe('makeNewHttpsTransport()', () => { url: 'https://9e9fd4523d784609a5fc0ebb1080592f@sentry.io:8989/mysubpath/50622', }); - expect(httpProxyAgent).not.toHaveBeenCalled(); + expect(proxyAgentSpy).not.toHaveBeenCalled(); delete process.env.no_proxy; delete process.env.http_proxy; @@ -277,7 +278,7 @@ describe('makeNewHttpsTransport()', () => { url: 'https://9e9fd4523d784609a5fc0ebb1080592f@sentry.io:8989/mysubpath/50622', }); - expect(httpProxyAgent).not.toHaveBeenCalled(); + expect(proxyAgentSpy).not.toHaveBeenCalled(); delete process.env.no_proxy; delete process.env.http_proxy; From 2996c62f08bfb5b0176aed11ef2315d8718ee259 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 8 Mar 2023 17:37:00 +0100 Subject: [PATCH 36/44] ref(browser): Improve type safety of breadcrumbs integration (#7382) --- .../browser/src/integrations/breadcrumbs.ts | 41 ++++++++++--------- packages/types/src/index.ts | 1 + packages/types/src/instrument.ts | 23 +++++++++++ packages/utils/src/instrument.ts | 17 +------- 4 files changed, 47 insertions(+), 35 deletions(-) create mode 100644 packages/types/src/instrument.ts diff --git a/packages/browser/src/integrations/breadcrumbs.ts b/packages/browser/src/integrations/breadcrumbs.ts index b54aad03e9b2..d48c2d1efbd9 100644 --- a/packages/browser/src/integrations/breadcrumbs.ts +++ b/packages/browser/src/integrations/breadcrumbs.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable max-lines */ import { getCurrentHub } from '@sentry/core'; -import type { Event, Integration } from '@sentry/types'; +import type { Event as SentryEvent, HandlerDataFetch, Integration, SentryWrappedXMLHttpRequest } from '@sentry/types'; import { addInstrumentationHandler, getEventDescription, @@ -14,6 +14,8 @@ import { import { WINDOW } from '../helpers'; +type HandlerData = Record; + /** JSDoc */ interface BreadcrumbsOptions { console: boolean; @@ -99,7 +101,7 @@ export class Breadcrumbs implements Integration { /** * Adds a breadcrumb for Sentry events or transactions if this option is enabled. */ - public addSentryBreadcrumb(event: Event): void { + public addSentryBreadcrumb(event: SentryEvent): void { if (this.options.sentry) { getCurrentHub().addBreadcrumb( { @@ -120,10 +122,8 @@ export class Breadcrumbs implements Integration { * A HOC that creaes a function that creates breadcrumbs from DOM API calls. * This is a HOC so that we get access to dom options in the closure. */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function _domBreadcrumb(dom: BreadcrumbsOptions['dom']): (handlerData: { [key: string]: any }) => void { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - function _innerDomBreadcrumb(handlerData: { [key: string]: any }): void { +function _domBreadcrumb(dom: BreadcrumbsOptions['dom']): (handlerData: HandlerData) => void { + function _innerDomBreadcrumb(handlerData: HandlerData): void { let target; let keyAttrs = typeof dom === 'object' ? dom.serializeAttribute : undefined; @@ -143,9 +143,10 @@ function _domBreadcrumb(dom: BreadcrumbsOptions['dom']): (handlerData: { [key: s // Accessing event.target can throw (see getsentry/raven-js#838, #768) try { - target = handlerData.event.target - ? htmlTreeAsString(handlerData.event.target as Node, { keyAttrs, maxStringLength }) - : htmlTreeAsString(handlerData.event as unknown as Node, { keyAttrs, maxStringLength }); + const event = handlerData.event as Event | Node; + target = _isEvent(event) + ? htmlTreeAsString(event.target, { keyAttrs, maxStringLength }) + : htmlTreeAsString(event, { keyAttrs, maxStringLength }); } catch (e) { target = ''; } @@ -173,8 +174,7 @@ function _domBreadcrumb(dom: BreadcrumbsOptions['dom']): (handlerData: { [key: s /** * Creates breadcrumbs from console API calls */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function _consoleBreadcrumb(handlerData: { [key: string]: any }): void { +function _consoleBreadcrumb(handlerData: HandlerData & { args: unknown[]; level: string }): void { // This is a hack to fix a Vue3-specific bug that causes an infinite loop of // console warnings. This happens when a Vue template is rendered with // an undeclared variable, which we try to stringify, ultimately causing @@ -216,8 +216,7 @@ function _consoleBreadcrumb(handlerData: { [key: string]: any }): void { /** * Creates breadcrumbs from XHR API calls */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function _xhrBreadcrumb(handlerData: { [key: string]: any }): void { +function _xhrBreadcrumb(handlerData: HandlerData & { xhr: SentryWrappedXMLHttpRequest }): void { if (handlerData.endTimestamp) { // We only capture complete, non-sentry requests if (handlerData.xhr.__sentry_own_request__) { @@ -249,8 +248,7 @@ function _xhrBreadcrumb(handlerData: { [key: string]: any }): void { /** * Creates breadcrumbs from fetch API calls */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function _fetchBreadcrumb(handlerData: { [key: string]: any }): void { +function _fetchBreadcrumb(handlerData: HandlerData & HandlerDataFetch): void { // We only capture complete fetch requests if (!handlerData.endTimestamp) { return; @@ -280,7 +278,7 @@ function _fetchBreadcrumb(handlerData: { [key: string]: any }): void { category: 'fetch', data: { ...handlerData.fetchData, - status_code: handlerData.response.status, + status_code: handlerData.response && handlerData.response.status, }, type: 'http', }, @@ -295,10 +293,9 @@ function _fetchBreadcrumb(handlerData: { [key: string]: any }): void { /** * Creates breadcrumbs from history API calls */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function _historyBreadcrumb(handlerData: { [key: string]: any }): void { - let from = handlerData.from; - let to = handlerData.to; +function _historyBreadcrumb(handlerData: HandlerData & { from: string; to: string }): void { + let from: string | undefined = handlerData.from; + let to: string | undefined = handlerData.to; const parsedLoc = parseUrl(WINDOW.location.href); let parsedFrom = parseUrl(from); const parsedTo = parseUrl(to); @@ -325,3 +322,7 @@ function _historyBreadcrumb(handlerData: { [key: string]: any }): void { }, }); } + +function _isEvent(event: unknown): event is Event { + return event && !!(event as Record).target; +} diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 7f7ed86cfc9a..30df53a682d5 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -94,5 +94,6 @@ export type { export type { User, UserFeedback } from './user'; export type { WrappedFunction } from './wrappedfunction'; export type { Instrumenter } from './instrumenter'; +export type { HandlerDataFetch, SentryWrappedXMLHttpRequest } from './instrument'; export type { BrowserClientReplayOptions } from './browseroptions'; diff --git a/packages/types/src/instrument.ts b/packages/types/src/instrument.ts new file mode 100644 index 000000000000..85045217c45b --- /dev/null +++ b/packages/types/src/instrument.ts @@ -0,0 +1,23 @@ +type XHRSendInput = null | Blob | BufferSource | FormData | URLSearchParams | string; + +export interface SentryWrappedXMLHttpRequest extends XMLHttpRequest { + [key: string]: any; + __sentry_xhr__?: { + method?: string; + url?: string; + status_code?: number; + body?: XHRSendInput; + }; +} + +interface SentryFetchData { + method: string; + url: string; +} + +export interface HandlerDataFetch { + args: any[]; + fetchData: SentryFetchData; + startTimestamp: number; + response?: Response; +} diff --git a/packages/utils/src/instrument.ts b/packages/utils/src/instrument.ts index cc3c1986b06d..68ee52789de9 100644 --- a/packages/utils/src/instrument.ts +++ b/packages/utils/src/instrument.ts @@ -1,7 +1,7 @@ /* eslint-disable max-lines */ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/ban-types */ -import type { WrappedFunction } from '@sentry/types'; +import type { HandlerDataFetch, SentryWrappedXMLHttpRequest, WrappedFunction } from '@sentry/types'; import { isInstanceOf, isString } from './is'; import { CONSOLE_LEVELS, logger } from './logger'; @@ -136,7 +136,7 @@ function instrumentFetch(): void { fill(WINDOW, 'fetch', function (originalFetch: () => void): () => void { return function (...args: any[]): void { - const handlerData = { + const handlerData: HandlerDataFetch = { args, fetchData: { method: getFetchMethod(args), @@ -175,19 +175,6 @@ function instrumentFetch(): void { }); } -type XHRSendInput = null | Blob | BufferSource | FormData | URLSearchParams | string; - -/** JSDoc */ -interface SentryWrappedXMLHttpRequest extends XMLHttpRequest { - [key: string]: any; - __sentry_xhr__?: { - method?: string; - url?: string; - status_code?: number; - body?: XHRSendInput; - }; -} - /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /** Extract `method` from fetch call arguments */ function getFetchMethod(fetchArgs: any[] = []): string { From 3eeef091434f3ee36c2566b1db5cce8ffe9897ca Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Wed, 8 Mar 2023 20:16:12 +0100 Subject: [PATCH 37/44] feat(core): Add lifecycle hooks (#7370) Co-authored-by: Francesco Novy --- packages/core/src/baseclient.ts | 36 +++++++++++++++++++++++ packages/core/test/lib/base.test.ts | 45 ++++++++++++++++++++++++++++- packages/types/src/client.ts | 27 +++++++++++++++++ 3 files changed, 107 insertions(+), 1 deletion(-) diff --git a/packages/core/src/baseclient.ts b/packages/core/src/baseclient.ts index b551cfafb8e8..bf1ae616c4d6 100644 --- a/packages/core/src/baseclient.ts +++ b/packages/core/src/baseclient.ts @@ -17,6 +17,7 @@ import type { SessionAggregates, Severity, SeverityLevel, + Transaction, TransactionEvent, Transport, } from '@sentry/types'; @@ -97,6 +98,9 @@ export abstract class BaseClient implements Client { /** Holds flushable */ private _outcomes: { [key: string]: number } = {}; + // eslint-disable-next-line @typescript-eslint/ban-types + private _hooks: Record = {}; + /** * Initializes this client instance. * @@ -351,6 +355,38 @@ export abstract class BaseClient implements Client { } } + // Keep on() & emit() signatures in sync with types' client.ts interface + + /** @inheritdoc */ + public on(hook: 'startTransaction' | 'finishTransaction', callback: (transaction: Transaction) => void): void; + + /** @inheritdoc */ + public on(hook: 'beforeEnvelope', callback: (envelope: Envelope) => void): void; + + /** @inheritdoc */ + public on(hook: string, callback: unknown): void { + if (!this._hooks[hook]) { + this._hooks[hook] = []; + } + + // @ts-ignore We assue the types are correct + this._hooks[hook].push(callback); + } + + /** @inheritdoc */ + public emit(hook: 'startTransaction' | 'finishTransaction', transaction: Transaction): void; + + /** @inheritdoc */ + public emit(hook: 'beforeEnvelope', envelope: Envelope): void; + + /** @inheritdoc */ + public emit(hook: string, ...rest: unknown[]): void { + if (this._hooks[hook]) { + // @ts-ignore we cannot enforce the callback to match the hook + this._hooks[hook].forEach(callback => callback(...rest)); + } + } + /** Updates existing session based on the provided event */ protected _updateSessionFromEvent(session: Session, event: Event): void { let crashed = false; diff --git a/packages/core/test/lib/base.test.ts b/packages/core/test/lib/base.test.ts index d7382ceeeacb..4ee65114fe79 100644 --- a/packages/core/test/lib/base.test.ts +++ b/packages/core/test/lib/base.test.ts @@ -1,4 +1,4 @@ -import type { Event, Span } from '@sentry/types'; +import type { Client, Envelope, Event, Span, Transaction } from '@sentry/types'; import { dsnToString, logger, SentryError, SyncPromise } from '@sentry/utils'; import { Hub, makeSession, Scope } from '../../src'; @@ -1730,4 +1730,47 @@ describe('BaseClient', () => { expect(clearedOutcomes4.length).toEqual(0); }); }); + + describe('hooks', () => { + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); + + // Make sure types work for both Client & BaseClient + const scenarios = [ + ['BaseClient', new TestClient(options)], + ['Client', new TestClient(options) as Client], + ] as const; + + describe.each(scenarios)('with client %s', (_, client) => { + it('should call a startTransaction hook', () => { + expect.assertions(1); + + const mockTransaction = { + traceId: '86f39e84263a4de99c326acab3bfe3bd', + } as Transaction; + + client.on?.('startTransaction', transaction => { + expect(transaction).toEqual(mockTransaction); + }); + + client.emit?.('startTransaction', mockTransaction); + }); + + it('should call a beforeEnvelope hook', () => { + expect.assertions(1); + + const mockEnvelope = [ + { + event_id: '12345', + }, + {}, + ] as Envelope; + + client.on?.('beforeEnvelope', envelope => { + expect(envelope).toEqual(mockEnvelope); + }); + + client.emit?.('beforeEnvelope', mockEnvelope); + }); + }); + }); }); diff --git a/packages/types/src/client.ts b/packages/types/src/client.ts index 28d23025ce84..71e2ac5a96d6 100644 --- a/packages/types/src/client.ts +++ b/packages/types/src/client.ts @@ -1,6 +1,7 @@ import type { EventDropReason } from './clientreport'; import type { DataCategory } from './datacategory'; import type { DsnComponents } from './dsn'; +import type { Envelope } from './envelope'; import type { Event, EventHint } from './event'; import type { Integration, IntegrationClass } from './integration'; import type { ClientOptions } from './options'; @@ -8,6 +9,7 @@ import type { Scope } from './scope'; import type { SdkMetadata } from './sdkmetadata'; import type { Session, SessionAggregates } from './session'; import type { Severity, SeverityLevel } from './severity'; +import type { Transaction } from './transaction'; import type { Transport } from './transport'; /** @@ -147,4 +149,29 @@ export interface Client { * @param event The dropped event. */ recordDroppedEvent(reason: EventDropReason, dataCategory: DataCategory, event?: Event): void; + + // HOOKS + // TODO(v8): Make the hooks non-optional. + + /** + * Register a callback for transaction start and finish. + */ + on?(hook: 'startTransaction' | 'finishTransaction', callback: (transaction: Transaction) => void): void; + + /** + * Register a callback for transaction start and finish. + */ + on?(hook: 'beforeEnvelope', callback: (envelope: Envelope) => void): void; + + /** + * Fire a hook event for transaction start and finish. Expects to be given a transaction as the + * second argument. + */ + emit?(hook: 'startTransaction' | 'finishTransaction', transaction: Transaction): void; + + /* + * Fire a hook event for envelope creation and sending. Expects to be given an envelope as the + * second argument. + */ + emit?(hook: 'beforeEnvelope', envelope: Envelope): void; } From 486d4bea3bbbcff4792fe3e399f905ad458ba03e Mon Sep 17 00:00:00 2001 From: Jonas Date: Wed, 8 Mar 2023 18:52:10 -0500 Subject: [PATCH 38/44] ref(node): store split file in cache for contextlines (#7383) * ref(contextlines): store split file in cache * ref(contextlines): remove benchmark * ref(contextlines): fix readSourceFile signature --- .../node/src/integrations/contextlines.ts | 36 +++++++++++-------- packages/node/test/context-lines.test.ts | 27 ++++++++++++++ 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/packages/node/src/integrations/contextlines.ts b/packages/node/src/integrations/contextlines.ts index f3cebc1d4037..bad96ae43fb2 100644 --- a/packages/node/src/integrations/contextlines.ts +++ b/packages/node/src/integrations/contextlines.ts @@ -3,7 +3,7 @@ import { addContextToFrame } from '@sentry/utils'; import { readFile } from 'fs'; import { LRUMap } from 'lru_map'; -const FILE_CONTENT_CACHE = new LRUMap(100); +const FILE_CONTENT_CACHE = new LRUMap(100); const DEFAULT_LINES_OF_CONTEXT = 7; // TODO: Replace with promisify when minimum supported node >= v8 @@ -65,7 +65,7 @@ export class ContextLines implements Integration { // keep a lookup map of which files we've already enqueued to read, // so we don't enqueue the same file multiple times which would cause multiple i/o reads const enqueuedReadSourceFileTasks: Record = {}; - const readSourceFileTasks: Promise[] = []; + const readSourceFileTasks: Promise[] = []; if (this._contextLines > 0 && event.exception?.values) { for (const exception of event.exception.values) { @@ -102,8 +102,8 @@ export class ContextLines implements Integration { // and attempt to add source context to frames. if (this._contextLines > 0 && event.exception?.values) { for (const exception of event.exception.values) { - if (exception.stacktrace?.frames) { - this.addSourceContextToFrames(exception.stacktrace.frames); + if (exception.stacktrace && exception.stacktrace.frames) { + await this.addSourceContextToFrames(exception.stacktrace.frames); } } } @@ -116,12 +116,11 @@ export class ContextLines implements Integration { for (const frame of frames) { // Only add context if we have a filename and it hasn't already been added if (frame.filename && frame.context_line === undefined) { - const sourceFile = FILE_CONTENT_CACHE.get(frame.filename); + const sourceFileLines = FILE_CONTENT_CACHE.get(frame.filename); - if (sourceFile) { + if (sourceFileLines) { try { - const lines = sourceFile.split('\n'); - addContextToFrame(lines, frame, this._contextLines); + addContextToFrame(sourceFileLines, frame, this._contextLines); } catch (e) { // anomaly, being defensive in case // unlikely to ever happen in practice but can definitely happen in theory @@ -134,25 +133,34 @@ export class ContextLines implements Integration { /** * Reads file contents and caches them in a global LRU cache. + * If reading fails, mark the file as null in the cache so we don't try again. * * @param filename filepath to read content from. */ -async function _readSourceFile(filename: string): Promise { +async function _readSourceFile(filename: string): Promise { const cachedFile = FILE_CONTENT_CACHE.get(filename); - // We have a cache hit + + // We have already attempted to read this file and failed, do not try again + if (cachedFile === null) { + return null; + } + + // We have a cache hit, return it if (cachedFile !== undefined) { return cachedFile; } - let content: string | null = null; - // Guard from throwing if readFile fails, this enables us to use Promise.all and // not have it short circuiting if one of the promises rejects + since context lines are added // on a best effort basis, we want to throw here anyways. + + // If we made it to here, it means that our file is not cache nor marked as failed, so attempt to read it + let content: string[] | null = null; try { - content = await readTextFileAsync(filename); + const rawFileContents = await readTextFileAsync(filename); + content = rawFileContents.split('\n'); } catch (_) { - // + // if we fail, we will mark the file as null in the cache and short circuit next time we try to read it } FILE_CONTENT_CACHE.set(filename, content); diff --git a/packages/node/test/context-lines.test.ts b/packages/node/test/context-lines.test.ts index de6f6f382cd8..b469796214b1 100644 --- a/packages/node/test/context-lines.test.ts +++ b/packages/node/test/context-lines.test.ts @@ -107,4 +107,31 @@ describe('ContextLines', () => { expect(readFileSpy).toHaveBeenCalledTimes(0); }); }); + test.only('does not attempt to readfile multiple times if it fails', async () => { + expect.assertions(1); + contextLines = new ContextLines({}); + + readFileSpy.mockImplementation(() => { + throw new Error("ENOENT: no such file or directory, open '/does/not/exist.js'"); + }); + + await addContext([ + { + colno: 1, + filename: '/does/not/exist.js', + lineno: 1, + function: 'fxn1', + }, + ]); + await addContext([ + { + colno: 1, + filename: '/does/not/exist.js', + lineno: 1, + function: 'fxn1', + }, + ]); + + expect(readFileSpy).toHaveBeenCalledTimes(1); + }); }); From 67a0dcf7c51d7379ad8426e788c8eb1c90e75477 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Wed, 8 Mar 2023 20:37:21 -0500 Subject: [PATCH 39/44] feat(replay): Attach an error `cause` to send exceptions (#7350) Attach the original exception as a `cause` when we throw "Unable to send replay" exceptions so that we know what is causing issues with sending replays. --- packages/replay/src/util/sendReplay.ts | 12 +++++++++++- packages/replay/src/util/sendReplayRequest.ts | 13 +++++++++++-- .../replay/test/integration/sendReplayEvent.test.ts | 5 +++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/packages/replay/src/util/sendReplay.ts b/packages/replay/src/util/sendReplay.ts index e393c8611866..f10bb223d3d9 100644 --- a/packages/replay/src/util/sendReplay.ts +++ b/packages/replay/src/util/sendReplay.ts @@ -41,7 +41,17 @@ export async function sendReplay( // If an error happened here, it's likely that uploading the attachment // failed, we'll can retry with the same events payload if (retryConfig.count >= RETRY_MAX_COUNT) { - throw new Error(`${UNABLE_TO_SEND_REPLAY} - max retries exceeded`); + const error = new Error(`${UNABLE_TO_SEND_REPLAY} - max retries exceeded`); + + try { + // In case browsers don't allow this property to be writable + // @ts-ignore This needs lib es2022 and newer + error.cause = err; + } catch { + // nothing to do + } + + throw error; } // will retry in intervals of 5, 10, 30 diff --git a/packages/replay/src/util/sendReplayRequest.ts b/packages/replay/src/util/sendReplayRequest.ts index 06e35330937e..2d512915ba47 100644 --- a/packages/replay/src/util/sendReplayRequest.ts +++ b/packages/replay/src/util/sendReplayRequest.ts @@ -115,8 +115,17 @@ export async function sendReplayRequest({ try { response = await transport.send(envelope); - } catch { - throw new Error(UNABLE_TO_SEND_REPLAY); + } catch (err) { + const error = new Error(UNABLE_TO_SEND_REPLAY); + + try { + // In case browsers don't allow this property to be writable + // @ts-ignore This needs lib es2022 and newer + error.cause = err; + } catch { + // nothing to do + } + throw error; } // TODO (v8): we can remove this guard once transport.send's type signature doesn't include void anymore diff --git a/packages/replay/test/integration/sendReplayEvent.test.ts b/packages/replay/test/integration/sendReplayEvent.test.ts index 356cfb33630c..867499890bb7 100644 --- a/packages/replay/test/integration/sendReplayEvent.test.ts +++ b/packages/replay/test/integration/sendReplayEvent.test.ts @@ -391,6 +391,11 @@ describe('Integration | sendReplayEvent', () => { expect(spyHandleException).toHaveBeenCalledTimes(5); expect(spyHandleException).toHaveBeenLastCalledWith(new Error('Unable to send Replay - max retries exceeded')); + const spyHandleExceptionCall = spyHandleException.mock.calls; + expect(spyHandleExceptionCall[spyHandleExceptionCall.length - 1][0].cause.message).toEqual( + 'Something bad happened', + ); + // No activity has occurred, session's last activity should remain the same expect(replay.session?.lastActivity).toBe(BASE_TIMESTAMP); From c192c9aa942bb98426c10ad03dc7a009cac8af8d Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Thu, 9 Mar 2023 02:30:25 -0500 Subject: [PATCH 40/44] test(replay): Add integration tests for input masking on change (#7260) --------- Co-authored-by: Francesco Novy --- .../suites/replay/privacyInput/init.js | 19 +++ .../suites/replay/privacyInput/template.html | 15 ++ .../suites/replay/privacyInput/test.ts | 111 ++++++++++++++ .../suites/replay/privacyInputMaskAll/init.js | 19 +++ .../replay/privacyInputMaskAll/template.html | 13 ++ .../suites/replay/privacyInputMaskAll/test.ts | 135 ++++++++++++++++++ .../suites/replay/sessionExpiry/test.ts | 2 +- packages/integration-tests/utils/fixtures.ts | 15 ++ .../integration-tests/utils/replayHelpers.ts | 50 +++++-- 9 files changed, 369 insertions(+), 10 deletions(-) create mode 100644 packages/integration-tests/suites/replay/privacyInput/init.js create mode 100644 packages/integration-tests/suites/replay/privacyInput/template.html create mode 100644 packages/integration-tests/suites/replay/privacyInput/test.ts create mode 100644 packages/integration-tests/suites/replay/privacyInputMaskAll/init.js create mode 100644 packages/integration-tests/suites/replay/privacyInputMaskAll/template.html create mode 100644 packages/integration-tests/suites/replay/privacyInputMaskAll/test.ts diff --git a/packages/integration-tests/suites/replay/privacyInput/init.js b/packages/integration-tests/suites/replay/privacyInput/init.js new file mode 100644 index 000000000000..a09c517b6a92 --- /dev/null +++ b/packages/integration-tests/suites/replay/privacyInput/init.js @@ -0,0 +1,19 @@ +import * as Sentry from '@sentry/browser'; +import { Replay } from '@sentry/replay'; + +window.Sentry = Sentry; +window.Replay = new Replay({ + flushMinDelay: 200, + flushMaxDelay: 200, + useCompression: false, + maskAllInputs: false, +}); + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + sampleRate: 0, + replaysSessionSampleRate: 1.0, + replaysOnErrorSampleRate: 0.0, + + integrations: [window.Replay], +}); diff --git a/packages/integration-tests/suites/replay/privacyInput/template.html b/packages/integration-tests/suites/replay/privacyInput/template.html new file mode 100644 index 000000000000..735abb395522 --- /dev/null +++ b/packages/integration-tests/suites/replay/privacyInput/template.html @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/packages/integration-tests/suites/replay/privacyInput/test.ts b/packages/integration-tests/suites/replay/privacyInput/test.ts new file mode 100644 index 000000000000..f95e857d5637 --- /dev/null +++ b/packages/integration-tests/suites/replay/privacyInput/test.ts @@ -0,0 +1,111 @@ +import { expect } from '@playwright/test'; +import { IncrementalSource } from '@sentry-internal/rrweb'; +import type { inputData } from '@sentry-internal/rrweb/typings/types'; + +import { sentryTest } from '../../../utils/fixtures'; +import type { IncrementalRecordingSnapshot } from '../../../utils/replayHelpers'; +import { + getIncrementalRecordingSnapshots, + shouldSkipReplayTest, + waitForReplayRequest, +} from '../../../utils/replayHelpers'; + +function isInputMutation( + snap: IncrementalRecordingSnapshot, +): snap is IncrementalRecordingSnapshot & { data: inputData } { + return snap.data.source == IncrementalSource.Input; +} + +sentryTest( + 'should mask input initial value and its changes', + async ({ browserName, forceFlushReplay, getLocalTestPath, page }) => { + // TODO(replay): This is flakey on firefox and webkit (~1%) where we do not always get the latest mutation. + if (shouldSkipReplayTest() || ['firefox', 'webkit'].includes(browserName)) { + sentryTest.skip(); + } + + const reqPromise0 = waitForReplayRequest(page, 0); + const reqPromise1 = waitForReplayRequest(page, 1); + const reqPromise2 = waitForReplayRequest(page, 2); + const reqPromise3 = waitForReplayRequest(page, 3); + + await page.route('https://dsn.ingest.sentry.io/**/*', route => { + return route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ id: 'test-id' }), + }); + }); + + const url = await getLocalTestPath({ testDir: __dirname }); + + await page.goto(url); + + await reqPromise0; + + const text = 'test'; + + await page.locator('#input').fill(text); + await forceFlushReplay(); + const snapshots = getIncrementalRecordingSnapshots(await reqPromise1).filter(isInputMutation); + const lastSnapshot = snapshots[snapshots.length - 1]; + expect(lastSnapshot.data.text).toBe(text); + + await page.locator('#input-masked').fill(text); + await forceFlushReplay(); + const snapshots2 = getIncrementalRecordingSnapshots(await reqPromise2).filter(isInputMutation); + const lastSnapshot2 = snapshots2[snapshots2.length - 1]; + expect(lastSnapshot2.data.text).toBe('*'.repeat(text.length)); + + await page.locator('#input-ignore').fill(text); + await forceFlushReplay(); + const snapshots3 = getIncrementalRecordingSnapshots(await reqPromise3).filter(isInputMutation); + expect(snapshots3.length).toBe(0); + }, +); + +sentryTest( + 'should mask textarea initial value and its changes', + async ({ browserName, forceFlushReplay, getLocalTestPath, page }) => { + // TODO(replay): This is flakey on firefox and webkit (~1%) where we do not always get the latest mutation. + if (shouldSkipReplayTest() || ['firefox', 'webkit'].includes(browserName)) { + sentryTest.skip(); + } + + const reqPromise0 = waitForReplayRequest(page, 0); + const reqPromise1 = waitForReplayRequest(page, 1); + const reqPromise2 = waitForReplayRequest(page, 2); + const reqPromise3 = waitForReplayRequest(page, 3); + + await page.route('https://dsn.ingest.sentry.io/**/*', route => { + return route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ id: 'test-id' }), + }); + }); + + const url = await getLocalTestPath({ testDir: __dirname }); + + await page.goto(url); + await reqPromise0; + + const text = 'test'; + await page.locator('#textarea').fill(text); + await forceFlushReplay(); + const snapshots = getIncrementalRecordingSnapshots(await reqPromise1).filter(isInputMutation); + const lastSnapshot = snapshots[snapshots.length - 1]; + expect(lastSnapshot.data.text).toBe(text); + + await page.locator('#textarea-masked').fill(text); + await forceFlushReplay(); + const snapshots2 = getIncrementalRecordingSnapshots(await reqPromise2).filter(isInputMutation); + const lastSnapshot2 = snapshots2[snapshots2.length - 1]; + expect(lastSnapshot2.data.text).toBe('*'.repeat(text.length)); + + await page.locator('#textarea-ignore').fill(text); + await forceFlushReplay(); + const snapshots3 = getIncrementalRecordingSnapshots(await reqPromise3).filter(isInputMutation); + expect(snapshots3.length).toBe(0); + }, +); diff --git a/packages/integration-tests/suites/replay/privacyInputMaskAll/init.js b/packages/integration-tests/suites/replay/privacyInputMaskAll/init.js new file mode 100644 index 000000000000..6345c0f75f4e --- /dev/null +++ b/packages/integration-tests/suites/replay/privacyInputMaskAll/init.js @@ -0,0 +1,19 @@ +import * as Sentry from '@sentry/browser'; +import { Replay } from '@sentry/replay'; + +window.Sentry = Sentry; +window.Replay = new Replay({ + flushMinDelay: 200, + flushMaxDelay: 200, + useCompression: false, + maskAllInputs: true, +}); + +Sentry.init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + sampleRate: 0, + replaysSessionSampleRate: 1.0, + replaysOnErrorSampleRate: 0.0, + + integrations: [window.Replay], +}); diff --git a/packages/integration-tests/suites/replay/privacyInputMaskAll/template.html b/packages/integration-tests/suites/replay/privacyInputMaskAll/template.html new file mode 100644 index 000000000000..404bed05a6d0 --- /dev/null +++ b/packages/integration-tests/suites/replay/privacyInputMaskAll/template.html @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/packages/integration-tests/suites/replay/privacyInputMaskAll/test.ts b/packages/integration-tests/suites/replay/privacyInputMaskAll/test.ts new file mode 100644 index 000000000000..9b4470118422 --- /dev/null +++ b/packages/integration-tests/suites/replay/privacyInputMaskAll/test.ts @@ -0,0 +1,135 @@ +import { expect } from '@playwright/test'; +import { IncrementalSource } from '@sentry-internal/rrweb'; +import type { inputData } from '@sentry-internal/rrweb/typings/types'; + +import { sentryTest } from '../../../utils/fixtures'; +import type { IncrementalRecordingSnapshot } from '../../../utils/replayHelpers'; +import { + getIncrementalRecordingSnapshots, + shouldSkipReplayTest, + waitForReplayRequest, +} from '../../../utils/replayHelpers'; + +function isInputMutation( + snap: IncrementalRecordingSnapshot, +): snap is IncrementalRecordingSnapshot & { data: inputData } { + return snap.data.source == IncrementalSource.Input; +} + +sentryTest( + 'should mask input initial value and its changes from `maskAllInputs` and allow unmasked selector', + async ({ browserName, forceFlushReplay, getLocalTestPath, page }) => { + // TODO(replay): This is flakey on firefox and webkit (~1%) where we do not always get the latest mutation. + if (shouldSkipReplayTest() || ['firefox', 'webkit'].includes(browserName)) { + sentryTest.skip(); + } + + // We want to ensure to check the correct event payloads + let firstInputMutationSegmentId: number | undefined = undefined; + const reqPromise0 = waitForReplayRequest(page, 0); + const reqPromise1 = waitForReplayRequest(page, (event, res) => { + const check = + firstInputMutationSegmentId === undefined && getIncrementalRecordingSnapshots(res).some(isInputMutation); + + if (check) { + firstInputMutationSegmentId = event.segment_id; + } + + return check; + }); + const reqPromise2 = waitForReplayRequest(page, (event, res) => { + return ( + typeof firstInputMutationSegmentId === 'number' && + firstInputMutationSegmentId < event.segment_id && + getIncrementalRecordingSnapshots(res).some(isInputMutation) + ); + }); + + await page.route('https://dsn.ingest.sentry.io/**/*', route => { + return route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ id: 'test-id' }), + }); + }); + + const url = await getLocalTestPath({ testDir: __dirname }); + + await page.goto(url); + await reqPromise0; + + const text = 'test'; + + await page.locator('#input').fill(text); + await forceFlushReplay(); + + const snapshots = getIncrementalRecordingSnapshots(await reqPromise1).filter(isInputMutation); + const lastSnapshot = snapshots[snapshots.length - 1]; + expect(lastSnapshot.data.text).toBe('*'.repeat(text.length)); + + await page.locator('#input-unmasked').fill(text); + await forceFlushReplay(); + const snapshots2 = getIncrementalRecordingSnapshots(await reqPromise2).filter(isInputMutation); + const lastSnapshot2 = snapshots2[snapshots2.length - 1]; + expect(lastSnapshot2.data.text).toBe(text); + }, +); + +sentryTest( + 'should mask textarea initial value and its changes from `maskAllInputs` and allow unmasked selector', + async ({ browserName, forceFlushReplay, getLocalTestPath, page }) => { + // TODO(replay): This is flakey on firefox and webkit (~1%) where we do not always get the latest mutation. + if (shouldSkipReplayTest() || ['firefox', 'webkit'].includes(browserName)) { + sentryTest.skip(); + } + + // We want to ensure to check the correct event payloads + let firstInputMutationSegmentId: number | undefined = undefined; + const reqPromise0 = waitForReplayRequest(page, 0); + const reqPromise1 = waitForReplayRequest(page, (event, res) => { + const check = + firstInputMutationSegmentId === undefined && getIncrementalRecordingSnapshots(res).some(isInputMutation); + + if (check) { + firstInputMutationSegmentId = event.segment_id; + } + + return check; + }); + const reqPromise2 = waitForReplayRequest(page, (event, res) => { + return ( + typeof firstInputMutationSegmentId === 'number' && + firstInputMutationSegmentId < event.segment_id && + getIncrementalRecordingSnapshots(res).some(isInputMutation) + ); + }); + + await page.route('https://dsn.ingest.sentry.io/**/*', route => { + return route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ id: 'test-id' }), + }); + }); + + const url = await getLocalTestPath({ testDir: __dirname }); + + await page.goto(url); + + await reqPromise0; + + const text = 'test'; + + await page.locator('#textarea').fill(text); + await forceFlushReplay(); + const snapshots = getIncrementalRecordingSnapshots(await reqPromise1).filter(isInputMutation); + const lastSnapshot = snapshots[snapshots.length - 1]; + expect(lastSnapshot.data.text).toBe('*'.repeat(text.length)); + + await page.locator('#textarea-unmasked').fill(text); + await forceFlushReplay(); + const snapshots2 = getIncrementalRecordingSnapshots(await reqPromise2).filter(isInputMutation); + const lastSnapshot2 = snapshots2[snapshots2.length - 1]; + expect(lastSnapshot2.data.text).toBe(text); + }, +); diff --git a/packages/integration-tests/suites/replay/sessionExpiry/test.ts b/packages/integration-tests/suites/replay/sessionExpiry/test.ts index c574ac570ec6..d817e7175840 100644 --- a/packages/integration-tests/suites/replay/sessionExpiry/test.ts +++ b/packages/integration-tests/suites/replay/sessionExpiry/test.ts @@ -14,7 +14,7 @@ import { // Session should expire after 2s - keep in sync with init.js const SESSION_TIMEOUT = 2000; -sentryTest('handles an expired session RUN', async ({ getLocalTestPath, page }) => { +sentryTest('handles an expired session', async ({ getLocalTestPath, page }) => { if (shouldSkipReplayTest()) { sentryTest.skip(); } diff --git a/packages/integration-tests/utils/fixtures.ts b/packages/integration-tests/utils/fixtures.ts index 0d4c75353700..05ac906ad2d2 100644 --- a/packages/integration-tests/utils/fixtures.ts +++ b/packages/integration-tests/utils/fixtures.ts @@ -25,6 +25,7 @@ export type TestFixtures = { _autoSnapshotSuffix: void; testDir: string; getLocalTestPath: (options: { testDir: string }) => Promise; + forceFlushReplay: () => Promise; runInChromium: (fn: (...args: unknown[]) => unknown, args?: unknown[]) => unknown; runInFirefox: (fn: (...args: unknown[]) => unknown, args?: unknown[]) => unknown; runInWebkit: (fn: (...args: unknown[]) => unknown, args?: unknown[]) => unknown; @@ -92,6 +93,20 @@ const sentryTest = base.extend({ return fn(...args); }); }, + + forceFlushReplay: ({ page }, use) => { + return use(() => + page.evaluate(` + Object.defineProperty(document, 'visibilityState', { + configurable: true, + get: function () { + return 'hidden'; + }, + }); + document.dispatchEvent(new Event('visibilitychange')); + `), + ); + }, }); export { sentryTest }; diff --git a/packages/integration-tests/utils/replayHelpers.ts b/packages/integration-tests/utils/replayHelpers.ts index c5c3e1f50ae9..8722fe245a23 100644 --- a/packages/integration-tests/utils/replayHelpers.ts +++ b/packages/integration-tests/utils/replayHelpers.ts @@ -1,3 +1,5 @@ +import type { fullSnapshotEvent, incrementalSnapshotEvent } from '@sentry-internal/rrweb'; +import { EventType } from '@sentry-internal/rrweb'; import type { InternalEventContext, RecordingEvent, @@ -20,10 +22,18 @@ export type PerformanceSpan = { data: Record; }; -type RecordingSnapshot = eventWithTime & { +export type FullRecordingSnapshot = eventWithTime & { timestamp: 0; + data: fullSnapshotEvent['data']; }; +export type IncrementalRecordingSnapshot = eventWithTime & { + timestamp: 0; + data: incrementalSnapshotEvent['data']; +}; + +export type RecordingSnapshot = FullRecordingSnapshot | IncrementalRecordingSnapshot; + /** * Waits for a replay request to be sent by the page and returns it. * @@ -36,7 +46,13 @@ type RecordingSnapshot = eventWithTime & { * @param segmentId the segment_id of the replay event * @returns */ -export function waitForReplayRequest(page: Page, segmentId?: number): Promise { +export function waitForReplayRequest( + page: Page, + segmentIdOrCallback?: number | ((event: ReplayEvent, res: Response) => boolean), +): Promise { + const segmentId = typeof segmentIdOrCallback === 'number' ? segmentIdOrCallback : undefined; + const callback = typeof segmentIdOrCallback === 'function' ? segmentIdOrCallback : undefined; + return page.waitForResponse(res => { const req = res.request(); @@ -52,6 +68,10 @@ export function waitForReplayRequest(page: Page, segmentId?: number): Promise event.type === 5).map(event => event.data as CustomRecordingEvent); + return recordingEvents.filter(isCustomSnapshot).map(event => event.data); } -function getReplayBreadcrumbs(recordingEvents: RecordingEvent[], category?: string): Breadcrumb[] { +function getReplayBreadcrumbs(recordingEvents: RecordingSnapshot[], category?: string): Breadcrumb[] { return getAllCustomRrwebRecordingEvents(recordingEvents) .filter(data => data.tag === 'breadcrumb') .map(data => data.payload) @@ -144,16 +176,16 @@ function getReplayPerformanceSpans(recordingEvents: RecordingEvent[]): Performan .map(data => data.payload) as PerformanceSpan[]; } -export function getFullRecordingSnapshots(resOrReq: Request | Response): RecordingSnapshot[] { +export function getFullRecordingSnapshots(resOrReq: Request | Response): FullRecordingSnapshot[] { const replayRequest = getRequest(resOrReq); const events = getDecompressedRecordingEvents(replayRequest); - return events.filter(event => event.type === 2); + return events.filter(isFullSnapshot); } -export function getIncrementalRecordingSnapshots(resOrReq: Request | Response): RecordingSnapshot[] { +export function getIncrementalRecordingSnapshots(resOrReq: Request | Response): IncrementalRecordingSnapshot[] { const replayRequest = getRequest(resOrReq); const events = getDecompressedRecordingEvents(replayRequest); - return events.filter(event => event.type === 3); + return events.filter(isIncrementalSnapshot); } function getDecompressedRecordingEvents(resOrReq: Request | Response): RecordingSnapshot[] { @@ -166,7 +198,7 @@ function getDecompressedRecordingEvents(resOrReq: Request | Response): Recording event => typeof event.data === 'object' && event.data && (event.data as Record).source !== 1, ) .map(event => { - return { ...event, timestamp: 0 }; + return { ...event, timestamp: 0 } as RecordingSnapshot; }) ); } From 295ea3d22036e1a3201be14d9adca4414670707c Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Thu, 9 Mar 2023 09:44:12 +0100 Subject: [PATCH 41/44] feat(core): Emit hooks for transaction start/finish (#7387) --- packages/core/src/tracing/hubextensions.ts | 6 ++++++ packages/core/src/tracing/transaction.ts | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/core/src/tracing/hubextensions.ts b/packages/core/src/tracing/hubextensions.ts index 17d847e5e8d8..9624df4b709e 100644 --- a/packages/core/src/tracing/hubextensions.ts +++ b/packages/core/src/tracing/hubextensions.ts @@ -186,6 +186,9 @@ The transaction will not be sampled. Please use the ${configInstrumenter} instru if (transaction.sampled) { transaction.initSpanRecorder(options._experiments && (options._experiments.maxSpans as number)); } + if (client && client.emit) { + client.emit('startTransaction', transaction); + } return transaction; } @@ -213,6 +216,9 @@ export function startIdleTransaction( if (transaction.sampled) { transaction.initSpanRecorder(options._experiments && (options._experiments.maxSpans as number)); } + if (client && client.emit) { + client.emit('startTransaction', transaction); + } return transaction; } diff --git a/packages/core/src/tracing/transaction.ts b/packages/core/src/tracing/transaction.ts index 440a8b69b41d..eba498b7e654 100644 --- a/packages/core/src/tracing/transaction.ts +++ b/packages/core/src/tracing/transaction.ts @@ -141,11 +141,15 @@ export class Transaction extends SpanClass implements TransactionInterface { // just sets the end timestamp super.finish(endTimestamp); + const client = this._hub.getClient(); + if (client && client.emit) { + client.emit('finishTransaction', this); + } + if (this.sampled !== true) { // At this point if `sampled !== true` we want to discard the transaction. __DEBUG_BUILD__ && logger.log('[Tracing] Discarding transaction because its trace was not chosen to be sampled.'); - const client = this._hub.getClient(); if (client) { client.recordDroppedEvent('sample_rate', 'transaction'); } From 361c5a43e18ca444ae9e1278cf3b7fc6c3bbfd8e Mon Sep 17 00:00:00 2001 From: Ash Anand <0Calories@users.noreply.github.com> Date: Thu, 9 Mar 2023 04:05:27 -0500 Subject: [PATCH 42/44] feat(tracing): Track PerformanceObserver interactions as spans (#7331) Co-authored-by: Abhijeet Prasad --- .../interactions/assets/script.js | 10 ++- .../browsertracing/interactions/init.js | 1 + .../browsertracing/interactions/template.html | 2 +- .../browsertracing/interactions/test.ts | 70 ++++++++++++++----- .../tracing/src/browser/browsertracing.ts | 10 ++- packages/tracing/src/browser/metrics/index.ts | 28 ++++++++ .../tracing/src/browser/web-vitals/types.ts | 1 + 7 files changed, 100 insertions(+), 22 deletions(-) diff --git a/packages/integration-tests/suites/tracing/browsertracing/interactions/assets/script.js b/packages/integration-tests/suites/tracing/browsertracing/interactions/assets/script.js index 5a2aef02028d..89d814bd397d 100644 --- a/packages/integration-tests/suites/tracing/browsertracing/interactions/assets/script.js +++ b/packages/integration-tests/suites/tracing/browsertracing/interactions/assets/script.js @@ -1,4 +1,4 @@ -(() => { +const delay = e => { const startTime = Date.now(); function getElasped() { @@ -6,7 +6,11 @@ return time - startTime; } - while (getElasped() < 105) { + while (getElasped() < 70) { // } -})(); + + e.target.classList.add('clicked'); +}; + +document.querySelector('[data-test-id=interaction-button]').addEventListener('click', delay); diff --git a/packages/integration-tests/suites/tracing/browsertracing/interactions/init.js b/packages/integration-tests/suites/tracing/browsertracing/interactions/init.js index 5229401c2ef5..d30222b7f47e 100644 --- a/packages/integration-tests/suites/tracing/browsertracing/interactions/init.js +++ b/packages/integration-tests/suites/tracing/browsertracing/interactions/init.js @@ -10,6 +10,7 @@ Sentry.init({ idleTimeout: 1000, _experiments: { enableInteractions: true, + enableLongTask: false, }, }), ], diff --git a/packages/integration-tests/suites/tracing/browsertracing/interactions/template.html b/packages/integration-tests/suites/tracing/browsertracing/interactions/template.html index e74a9c17eeb2..e16deb9ee519 100644 --- a/packages/integration-tests/suites/tracing/browsertracing/interactions/template.html +++ b/packages/integration-tests/suites/tracing/browsertracing/interactions/template.html @@ -5,7 +5,7 @@
Rendered Before Long Task
- + diff --git a/packages/integration-tests/suites/tracing/browsertracing/interactions/test.ts b/packages/integration-tests/suites/tracing/browsertracing/interactions/test.ts index b9a70ebda3ec..faff888fc2e8 100644 --- a/packages/integration-tests/suites/tracing/browsertracing/interactions/test.ts +++ b/packages/integration-tests/suites/tracing/browsertracing/interactions/test.ts @@ -1,12 +1,23 @@ import type { Route } from '@playwright/test'; import { expect } from '@playwright/test'; -import type { Event } from '@sentry/types'; +import type { Event, Span, SpanContext, Transaction } from '@sentry/types'; import { sentryTest } from '../../../../utils/fixtures'; import { getFirstSentryEnvelopeRequest, getMultipleSentryEnvelopeRequests } from '../../../../utils/helpers'; +type TransactionJSON = ReturnType & { + spans: ReturnType[]; + contexts: SpanContext; + platform: string; + type: string; +}; + +const wait = (time: number) => new Promise(res => setTimeout(res, time)); + sentryTest('should capture interaction transaction.', async ({ browserName, getLocalTestPath, page }) => { - if (browserName !== 'chromium') { + const supportedBrowsers = ['chromium', 'firefox']; + + if (!supportedBrowsers.includes(browserName)) { sentryTest.skip(); } @@ -14,24 +25,49 @@ sentryTest('should capture interaction transaction.', async ({ browserName, getL const url = await getLocalTestPath({ testDir: __dirname }); - await getFirstSentryEnvelopeRequest(page, url); + await page.goto(url); + await getFirstSentryEnvelopeRequest(page); await page.locator('[data-test-id=interaction-button]').click(); + await page.locator('.clicked[data-test-id=interaction-button]').isVisible(); + + const envelopes = await getMultipleSentryEnvelopeRequests(page, 1); + expect(envelopes).toHaveLength(1); - const envelopes = await getMultipleSentryEnvelopeRequests(page, 1); const eventData = envelopes[0]; - expect(eventData).toEqual( - expect.objectContaining({ - contexts: expect.objectContaining({ - trace: expect.objectContaining({ - op: 'ui.action.click', - }), - }), - platform: 'javascript', - spans: [], - tags: {}, - type: 'transaction', - }), - ); + expect(eventData.contexts).toMatchObject({ trace: { op: 'ui.action.click' } }); + expect(eventData.platform).toBe('javascript'); + expect(eventData.type).toBe('transaction'); + expect(eventData.spans).toHaveLength(1); + + const interactionSpan = eventData.spans![0]; + expect(interactionSpan.op).toBe('ui.interaction.click'); + expect(interactionSpan.description).toBe('body > button.clicked'); + expect(interactionSpan.timestamp).toBeDefined(); + + const interactionSpanDuration = (interactionSpan.timestamp! - interactionSpan.start_timestamp) * 1000; + expect(interactionSpanDuration).toBeGreaterThan(70); + expect(interactionSpanDuration).toBeLessThan(200); +}); + +sentryTest('should create only one transaction per interaction', async ({ browserName, getLocalTestPath, page }) => { + const supportedBrowsers = ['chromium', 'firefox']; + + if (!supportedBrowsers.includes(browserName)) { + sentryTest.skip(); + } + + await page.route('**/path/to/script.js', (route: Route) => route.fulfill({ path: `${__dirname}/assets/script.js` })); + + const url = await getLocalTestPath({ testDir: __dirname }); + await page.goto(url); + await getFirstSentryEnvelopeRequest(page); + + for (let i = 0; i < 4; i++) { + await wait(100); + await page.locator('[data-test-id=interaction-button]').click(); + const envelope = await getMultipleSentryEnvelopeRequests(page, 1); + expect(envelope[0].spans).toHaveLength(1); + } }); diff --git a/packages/tracing/src/browser/browsertracing.ts b/packages/tracing/src/browser/browsertracing.ts index edd2baf71d9f..28615763a949 100644 --- a/packages/tracing/src/browser/browsertracing.ts +++ b/packages/tracing/src/browser/browsertracing.ts @@ -5,7 +5,12 @@ import type { EventProcessor, Integration, Transaction, TransactionContext, Tran import { baggageHeaderToDynamicSamplingContext, getDomElement, logger } from '@sentry/utils'; import { registerBackgroundTabDetection } from './backgroundtab'; -import { addPerformanceEntries, startTrackingLongTasks, startTrackingWebVitals } from './metrics'; +import { + addPerformanceEntries, + startTrackingInteractions, + startTrackingLongTasks, + startTrackingWebVitals, +} from './metrics'; import type { RequestInstrumentationOptions } from './request'; import { defaultRequestInstrumentationOptions, instrumentOutgoingRequests } from './request'; import { instrumentRoutingWithDefaults } from './router'; @@ -189,6 +194,9 @@ export class BrowserTracing implements Integration { if (this.options.enableLongTask) { startTrackingLongTasks(); } + if (this.options._experiments.enableInteractions) { + startTrackingInteractions(); + } } /** diff --git a/packages/tracing/src/browser/metrics/index.ts b/packages/tracing/src/browser/metrics/index.ts index 2d37ef8c1919..7f0107408502 100644 --- a/packages/tracing/src/browser/metrics/index.ts +++ b/packages/tracing/src/browser/metrics/index.ts @@ -71,6 +71,34 @@ export function startTrackingLongTasks(): void { observe('longtask', entryHandler); } +/** + * Start tracking interaction events. + */ +export function startTrackingInteractions(): void { + const entryHandler = (entries: PerformanceEventTiming[]): void => { + for (const entry of entries) { + const transaction = getActiveTransaction() as IdleTransaction | undefined; + if (!transaction) { + return; + } + + if (entry.name === 'click') { + const startTime = msToSec((browserPerformanceTimeOrigin as number) + entry.startTime); + const duration = msToSec(entry.duration); + + transaction.startChild({ + description: htmlTreeAsString(entry.target), + op: `ui.interaction.${entry.name}`, + startTimestamp: startTime, + endTimestamp: startTime + duration, + }); + } + } + }; + + observe('event', entryHandler, { durationThreshold: 0 }); +} + /** Starts tracking the Cumulative Layout Shift on the current page. */ function _trackCLS(): void { // See: diff --git a/packages/tracing/src/browser/web-vitals/types.ts b/packages/tracing/src/browser/web-vitals/types.ts index ef8de70c12bb..b4096b2678f6 100644 --- a/packages/tracing/src/browser/web-vitals/types.ts +++ b/packages/tracing/src/browser/web-vitals/types.ts @@ -135,6 +135,7 @@ declare global { interface PerformanceEventTiming extends PerformanceEntry { duration: DOMHighResTimeStamp; interactionId?: number; + readonly target: Node | null; } // https://wicg.github.io/layout-instability/#sec-layout-shift-attribution From 1d6d216f6ae093396950d7426db04d67e0e675f4 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Thu, 9 Mar 2023 11:12:41 +0100 Subject: [PATCH 43/44] fix(tracing): Record LCP and CLS on transaction finish (#7386) --- .../tracing/metrics/web-vitals-lcp/test.ts | 2 -- .../tracing/src/browser/browsertracing.ts | 5 +++- packages/tracing/src/browser/metrics/index.ts | 27 ++++++++++++++----- .../tracing/src/browser/web-vitals/getCLS.ts | 14 +++++++--- .../tracing/src/browser/web-vitals/getLCP.ts | 8 ++++-- .../src/browser/web-vitals/types/base.ts | 2 ++ .../test/browser/browsertracing.test.ts | 22 ++++++++++++++- 7 files changed, 63 insertions(+), 17 deletions(-) diff --git a/packages/integration-tests/suites/tracing/metrics/web-vitals-lcp/test.ts b/packages/integration-tests/suites/tracing/metrics/web-vitals-lcp/test.ts index 28b85d518e80..7511abf60d09 100644 --- a/packages/integration-tests/suites/tracing/metrics/web-vitals-lcp/test.ts +++ b/packages/integration-tests/suites/tracing/metrics/web-vitals-lcp/test.ts @@ -17,8 +17,6 @@ sentryTest('should capture a LCP vital with element details.', async ({ browserN const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); - // Force closure of LCP listener. - await page.click('body'); const eventData = await getFirstSentryEnvelopeRequest(page); expect(eventData.measurements).toBeDefined(); diff --git a/packages/tracing/src/browser/browsertracing.ts b/packages/tracing/src/browser/browsertracing.ts index 28615763a949..3575c0a20e91 100644 --- a/packages/tracing/src/browser/browsertracing.ts +++ b/packages/tracing/src/browser/browsertracing.ts @@ -169,6 +169,8 @@ export class BrowserTracing implements Integration { private _latestRouteName?: string; private _latestRouteSource?: TransactionSource; + private _collectWebVitals: () => void; + public constructor(_options?: Partial) { this.options = { ...DEFAULT_BROWSER_TRACING_OPTIONS, @@ -190,7 +192,7 @@ export class BrowserTracing implements Integration { this.options.tracePropagationTargets = _options.tracingOrigins; } - startTrackingWebVitals(); + this._collectWebVitals = startTrackingWebVitals(); if (this.options.enableLongTask) { startTrackingLongTasks(); } @@ -311,6 +313,7 @@ export class BrowserTracing implements Integration { heartbeatInterval, ); idleTransaction.registerBeforeFinishCallback(transaction => { + this._collectWebVitals(); addPerformanceEntries(transaction); }); diff --git a/packages/tracing/src/browser/metrics/index.ts b/packages/tracing/src/browser/metrics/index.ts index 7f0107408502..788f21aafaa4 100644 --- a/packages/tracing/src/browser/metrics/index.ts +++ b/packages/tracing/src/browser/metrics/index.ts @@ -33,17 +33,30 @@ let _clsEntry: LayoutShift | undefined; /** * Start tracking web vitals + * + * @returns A function that forces web vitals collection */ -export function startTrackingWebVitals(): void { +export function startTrackingWebVitals(): () => void { const performance = getBrowserPerformanceAPI(); if (performance && browserPerformanceTimeOrigin) { if (performance.mark) { WINDOW.performance.mark('sentry-tracing-init'); } - _trackCLS(); - _trackLCP(); _trackFID(); + const clsCallback = _trackCLS(); + const lcpCallback = _trackLCP(); + + return (): void => { + if (clsCallback) { + clsCallback(); + } + if (lcpCallback) { + lcpCallback(); + } + }; } + + return () => undefined; } /** @@ -100,11 +113,11 @@ export function startTrackingInteractions(): void { } /** Starts tracking the Cumulative Layout Shift on the current page. */ -function _trackCLS(): void { +function _trackCLS(): ReturnType { // See: // https://web.dev/evolving-cls/ // https://web.dev/cls-web-tooling/ - onCLS(metric => { + return onCLS(metric => { const entry = metric.entries.pop(); if (!entry) { return; @@ -117,8 +130,8 @@ function _trackCLS(): void { } /** Starts tracking the Largest Contentful Paint on the current page. */ -function _trackLCP(): void { - onLCP(metric => { +function _trackLCP(): ReturnType { + return onLCP(metric => { const entry = metric.entries.pop(); if (!entry) { return; diff --git a/packages/tracing/src/browser/web-vitals/getCLS.ts b/packages/tracing/src/browser/web-vitals/getCLS.ts index 3abddfac07cb..fdd1e867adfa 100644 --- a/packages/tracing/src/browser/web-vitals/getCLS.ts +++ b/packages/tracing/src/browser/web-vitals/getCLS.ts @@ -18,7 +18,7 @@ import { bindReporter } from './lib/bindReporter'; import { initMetric } from './lib/initMetric'; import { observe } from './lib/observe'; import { onHidden } from './lib/onHidden'; -import type { CLSMetric, ReportCallback } from './types'; +import type { CLSMetric, ReportCallback, StopListening } from './types'; /** * Calculates the [CLS](https://web.dev/cls/) value for the current page and @@ -41,7 +41,7 @@ import type { CLSMetric, ReportCallback } from './types'; * hidden. As a result, the `callback` function might be called multiple times * during the same page load._ */ -export const onCLS = (onReport: ReportCallback): void => { +export const onCLS = (onReport: ReportCallback): StopListening | undefined => { const metric = initMetric('CLS', 0); let report: ReturnType; @@ -89,9 +89,15 @@ export const onCLS = (onReport: ReportCallback): void => { if (po) { report = bindReporter(onReport, metric); - onHidden(() => { + const stopListening = (): void => { handleEntries(po.takeRecords() as CLSMetric['entries']); report(true); - }); + }; + + onHidden(stopListening); + + return stopListening; } + + return; }; diff --git a/packages/tracing/src/browser/web-vitals/getLCP.ts b/packages/tracing/src/browser/web-vitals/getLCP.ts index bf834c07ce4e..37e37c01eebd 100644 --- a/packages/tracing/src/browser/web-vitals/getLCP.ts +++ b/packages/tracing/src/browser/web-vitals/getLCP.ts @@ -20,7 +20,7 @@ import { getVisibilityWatcher } from './lib/getVisibilityWatcher'; import { initMetric } from './lib/initMetric'; import { observe } from './lib/observe'; import { onHidden } from './lib/onHidden'; -import type { LCPMetric, ReportCallback } from './types'; +import type { LCPMetric, ReportCallback, StopListening } from './types'; const reportedMetricIDs: Record = {}; @@ -30,7 +30,7 @@ const reportedMetricIDs: Record = {}; * relevant `largest-contentful-paint` performance entry used to determine the * value). The reported value is a `DOMHighResTimeStamp`. */ -export const onLCP = (onReport: ReportCallback): void => { +export const onLCP = (onReport: ReportCallback): StopListening | undefined => { const visibilityWatcher = getVisibilityWatcher(); const metric = initMetric('LCP'); let report: ReturnType; @@ -75,5 +75,9 @@ export const onLCP = (onReport: ReportCallback): void => { }); onHidden(stopListening, true); + + return stopListening; } + + return; }; diff --git a/packages/tracing/src/browser/web-vitals/types/base.ts b/packages/tracing/src/browser/web-vitals/types/base.ts index 5dc45f00558d..ea2764c8ea64 100644 --- a/packages/tracing/src/browser/web-vitals/types/base.ts +++ b/packages/tracing/src/browser/web-vitals/types/base.ts @@ -104,3 +104,5 @@ export interface ReportOpts { * loading. This is equivalent to the corresponding `readyState` value. */ export type LoadState = 'loading' | 'dom-interactive' | 'dom-content-loaded' | 'complete'; + +export type StopListening = () => void; diff --git a/packages/tracing/test/browser/browsertracing.test.ts b/packages/tracing/test/browser/browsertracing.test.ts index b89a6d791267..e2bee71db0a8 100644 --- a/packages/tracing/test/browser/browsertracing.test.ts +++ b/packages/tracing/test/browser/browsertracing.test.ts @@ -28,7 +28,14 @@ jest.mock('@sentry/utils', () => { }; }); -jest.mock('../../src/browser/metrics'); +const mockStartTrackingWebVitals = jest.fn().mockReturnValue(() => () => {}); + +jest.mock('../../src/browser/metrics', () => ({ + addPerformanceEntries: jest.fn(), + startTrackingInteractions: jest.fn(), + startTrackingLongTasks: jest.fn(), + startTrackingWebVitals: () => mockStartTrackingWebVitals(), +})); const instrumentOutgoingRequestsMock = jest.fn(); jest.mock('./../../src/browser/request', () => { @@ -57,6 +64,8 @@ describe('BrowserTracing', () => { hub = new Hub(new BrowserClient(options)); makeMain(hub); document.head.innerHTML = ''; + + mockStartTrackingWebVitals.mockClear(); }); afterEach(() => { @@ -371,6 +380,17 @@ describe('BrowserTracing', () => { jest.advanceTimersByTime(2000); expect(mockFinish).toHaveBeenCalledTimes(1); }); + + it('calls `_collectWebVitals` if enabled', () => { + createBrowserTracing(true, { routingInstrumentation: customInstrumentRouting }); + const transaction = getActiveTransaction(hub) as IdleTransaction; + + const span = transaction.startChild(); // activities = 1 + span.finish(); // activities = 0 + + jest.advanceTimersByTime(TRACING_DEFAULTS.idleTimeout); + expect(mockStartTrackingWebVitals).toHaveBeenCalledTimes(1); + }); }); describe('heartbeatInterval', () => { From 290b89543d1cb1e5c51385212f1466d9de471470 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Thu, 9 Mar 2023 12:43:07 +0100 Subject: [PATCH 44/44] meta(changelog): Update changelog for 7.42.0 --- CHANGELOG.md | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e30b3c97422..6eddb94ba9eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,30 @@ - "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott -- fix(replay): Ensure `` is masked ([#69](https://github.com/getsentry/rrweb/pull/69)) +## 7.42.0 + +- feat(core): Add lifecycle hooks (#7370) +- feat(core): Emit hooks for transaction start/finish (#7387) +- feat(nextjs): Connect traces for server components (#7320) +- feat(replay): Attach an error `cause` to send exceptions (#7350) +- feat(replay): Consider user input in form field as "user activity" (#7355) +- feat(replay): Update rrweb to 1.105.0 & add breadcrumb when encountering large mutation (#7314) +- feat(tracing): Expose cancelIdleTimeout and add option to make it permanent (#7236) +- feat(tracing): Track PerformanceObserver interactions as spans (#7331) +- fix(core): Ensure `originalException` has type `unknown` (#7361) +- fix(core): Avoid using `Object.values()` (#7360) +- fix(react): Make redux integration be configurable via `normalizeDepth` (#7379) +- fix(tracing): Record LCP and CLS on transaction finish (#7386) +- ref(browser): Improve type safety of breadcrumbs integration (#7382) +- ref(node): Parallelize disk io when reading source files for context lines (#7374) +- ref(node): Partially remove dynamic `require` calls (#7377) + +**Replay `rrweb` changes:** + +`@sentry-internal/rrweb` was updated from 1.104.1 to 1.105.0 (#7314): + +- feat: Add `onMutation` option to record ([#70](https://github.com/getsentry/rrweb/pull/69)) +- fix: Ensure `` is masked ([#69](https://github.com/getsentry/rrweb/pull/69)) ## 7.41.0