diff --git a/packages/integration-tests/.gitignore b/packages/integration-tests/.gitignore new file mode 100644 index 000000000000..87364a273f79 --- /dev/null +++ b/packages/integration-tests/.gitignore @@ -0,0 +1 @@ +test-results diff --git a/packages/integration-tests/suites/replay/privacyBlock/init.js b/packages/integration-tests/suites/replay/privacyBlock/init.js new file mode 100644 index 000000000000..31d8a00ed0fd --- /dev/null +++ b/packages/integration-tests/suites/replay/privacyBlock/init.js @@ -0,0 +1,20 @@ +import * as Sentry from '@sentry/browser'; +import { Replay } from '@sentry/replay'; + +window.Sentry = Sentry; +window.Replay = new Replay({ + flushMinDelay: 200, + flushMaxDelay: 200, + useCompression: false, + blockAllMedia: false, + block: ['link[rel="icon"]', 'video', '.nested-hide'], +}); + +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/privacyBlock/template.html b/packages/integration-tests/suites/replay/privacyBlock/template.html new file mode 100644 index 000000000000..1742e26f18f1 --- /dev/null +++ b/packages/integration-tests/suites/replay/privacyBlock/template.html @@ -0,0 +1,22 @@ + + + + + + + + +
This should be masked by default
+
This should be unmasked due to data attribute
+ +
Title should be masked
+ + + + + +
+
This should be hidden.
+
+ + diff --git a/packages/integration-tests/suites/replay/privacyBlock/test.ts b/packages/integration-tests/suites/replay/privacyBlock/test.ts new file mode 100644 index 000000000000..8b000b07e461 --- /dev/null +++ b/packages/integration-tests/suites/replay/privacyBlock/test.ts @@ -0,0 +1,35 @@ +import { expect } from '@playwright/test'; + +import { sentryTest } from '../../../utils/fixtures'; +import { + getFullRecordingSnapshots, + normalize, + shouldSkipReplayTest, + waitForReplayRequest, +} from '../../../utils/replayHelpers'; + +sentryTest('should allow to manually block elements', 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 snapshots = getFullRecordingSnapshots(await reqPromise0); + expect(snapshots.length).toEqual(1); + + const stringifiedSnapshot = normalize(snapshots[0], { normalizeNumberAttributes: ['rr_width', 'rr_height'] }); + + expect(stringifiedSnapshot).toMatchSnapshot('privacy.json'); +}); 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 new file mode 100644 index 000000000000..a120d5e44a5e --- /dev/null +++ b/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy-chromium.json @@ -0,0 +1,319 @@ +{ + "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 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "aria-label": "***** **", + "onclick": "console.log('Test log')" + }, + "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": "" + }, + "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": "*********** ****** ** ******" + }, + "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" + }, + "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 + }, + { + "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 + }, + { + "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" + }, + "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" + }, + "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" + }, + "childNodes": [], + "id": 40 + }, + { + "type": 3, + "textContent": "\n ", + "id": 41 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 42 + } + ], + "id": 8 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ 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 new file mode 100644 index 000000000000..a120d5e44a5e --- /dev/null +++ b/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy-firefox.json @@ -0,0 +1,319 @@ +{ + "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 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "aria-label": "***** **", + "onclick": "console.log('Test log')" + }, + "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": "" + }, + "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": "*********** ****** ** ******" + }, + "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" + }, + "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 + }, + { + "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 + }, + { + "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" + }, + "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" + }, + "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" + }, + "childNodes": [], + "id": 40 + }, + { + "type": 3, + "textContent": "\n ", + "id": 41 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 42 + } + ], + "id": 8 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ 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 new file mode 100644 index 000000000000..a120d5e44a5e --- /dev/null +++ b/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy-webkit.json @@ -0,0 +1,319 @@ +{ + "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 + }, + { + "type": 2, + "tagName": "button", + "attributes": { + "aria-label": "***** **", + "onclick": "console.log('Test log')" + }, + "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": "" + }, + "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": "*********** ****** ** ******" + }, + "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" + }, + "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 + }, + { + "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 + }, + { + "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" + }, + "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" + }, + "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" + }, + "childNodes": [], + "id": 40 + }, + { + "type": 3, + "textContent": "\n ", + "id": 41 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 42 + } + ], + "id": 8 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ 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 new file mode 100644 index 000000000000..4b08d64a07b3 --- /dev/null +++ b/packages/integration-tests/suites/replay/privacyBlock/test.ts-snapshots/privacy.json @@ -0,0 +1,319 @@ +{ + "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": "0px", + "rr_height": "0px" + }, + "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')" + }, + "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": "" + }, + "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": "*********** ****** ** ******" + }, + "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" + }, + "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 + }, + { + "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 + }, + { + "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" + }, + "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": "30px", + "rr_height": "30px" + }, + "childNodes": [], + "id": 38 + }, + { + "type": 3, + "textContent": "\n ", + "id": 39 + }, + { + "type": 2, + "tagName": "div", + "attributes": { + "class": "nested-hide", + "rr_width": "1264px", + "rr_height": "18px" + }, + "childNodes": [], + "id": 40 + }, + { + "type": 3, + "textContent": "\n ", + "id": 41 + }, + { + "type": 3, + "textContent": "\n\n", + "id": 42 + } + ], + "id": 8 + } + ], + "id": 3 + } + ], + "id": 1 + }, + "initialOffset": { + "left": 0, + "top": 0 + } +} \ No newline at end of file diff --git a/packages/integration-tests/suites/replay/privacy/init.js b/packages/integration-tests/suites/replay/privacyDefault/init.js similarity index 100% rename from packages/integration-tests/suites/replay/privacy/init.js rename to packages/integration-tests/suites/replay/privacyDefault/init.js diff --git a/packages/integration-tests/suites/replay/privacy/template.html b/packages/integration-tests/suites/replay/privacyDefault/template.html similarity index 86% rename from packages/integration-tests/suites/replay/privacy/template.html rename to packages/integration-tests/suites/replay/privacyDefault/template.html index 2eb0f8df7b37..a8279dad4d17 100644 --- a/packages/integration-tests/suites/replay/privacy/template.html +++ b/packages/integration-tests/suites/replay/privacyDefault/template.html @@ -1,6 +1,9 @@ - + + + +
This should be masked by default
diff --git a/packages/integration-tests/suites/replay/privacy/test.ts b/packages/integration-tests/suites/replay/privacyDefault/test.ts similarity index 53% rename from packages/integration-tests/suites/replay/privacy/test.ts rename to packages/integration-tests/suites/replay/privacyDefault/test.ts index a6315d5d1e66..713431ca3063 100644 --- a/packages/integration-tests/suites/replay/privacy/test.ts +++ b/packages/integration-tests/suites/replay/privacyDefault/test.ts @@ -1,10 +1,12 @@ import { expect } from '@playwright/test'; -import { EventType } from '@sentry-internal/rrweb'; -import type { RecordingEvent } from '@sentry/replay/build/npm/types/types'; import { sentryTest } from '../../../utils/fixtures'; -import { envelopeRequestParser } from '../../../utils/helpers'; -import { shouldSkipReplayTest, waitForReplayRequest } from '../../../utils/replayHelpers'; +import { + getFullRecordingSnapshots, + normalize, + shouldSkipReplayTest, + waitForReplayRequest, +} from '../../../utils/replayHelpers'; sentryTest('should have the correct default privacy settings', async ({ getLocalTestPath, page }) => { if (shouldSkipReplayTest()) { @@ -24,8 +26,11 @@ sentryTest('should have the correct default privacy settings', async ({ getLocal const url = await getLocalTestPath({ testDir: __dirname }); await page.goto(url); - const replayPayload = envelopeRequestParser(await reqPromise0, 5); - const checkoutEvent = replayPayload.find(({ type }) => type === EventType.FullSnapshot); - expect(JSON.stringify(checkoutEvent?.data, null, 2)).toMatchSnapshot('privacy.json'); + const snapshots = getFullRecordingSnapshots(await reqPromise0); + expect(snapshots.length).toEqual(1); + + const stringifiedSnapshot = normalize(snapshots[0], { normalizeNumberAttributes: ['rr_width', 'rr_height'] }); + + expect(stringifiedSnapshot).toMatchSnapshot('privacy.json'); }); diff --git a/packages/integration-tests/suites/replay/privacy/test.ts-snapshots/privacy-chromium.json b/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-chromium.json similarity index 87% rename from packages/integration-tests/suites/replay/privacy/test.ts-snapshots/privacy-chromium.json rename to packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-chromium.json index d0cb968d61ff..f31f8b967d12 100644 --- a/packages/integration-tests/suites/replay/privacy/test.ts-snapshots/privacy-chromium.json +++ b/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-chromium.json @@ -27,6 +27,17 @@ }, "childNodes": [], "id": 5 + }, + { + "type": 2, + "tagName": "link", + "attributes": { + "rel": "icon", + "type": "image/png", + "href": "file://assets/icon/favicon.png" + }, + "childNodes": [], + "id": 6 } ], "id": 4 @@ -34,7 +45,7 @@ { "type": 3, "textContent": "\n ", - "id": 6 + "id": 7 }, { "type": 2, @@ -44,7 +55,7 @@ { "type": 3, "textContent": "\n ", - "id": 8 + "id": 9 }, { "type": 2, @@ -57,15 +68,15 @@ { "type": 3, "textContent": "***** **", - "id": 10 + "id": 11 } ], - "id": 9 + "id": 10 }, { "type": 3, "textContent": "\n ", - "id": 11 + "id": 12 }, { "type": 2, @@ -75,15 +86,15 @@ { "type": 3, "textContent": "**** ****** ** ****** ** *******", - "id": 13 + "id": 14 } ], - "id": 12 + "id": 13 }, { "type": 3, "textContent": "\n ", - "id": 14 + "id": 15 }, { "type": 2, @@ -95,15 +106,15 @@ { "type": 3, "textContent": "This should be unmasked due to data attribute", - "id": 16 + "id": 17 } ], - "id": 15 + "id": 16 }, { "type": 3, "textContent": "\n ", - "id": 17 + "id": 18 }, { "type": 2, @@ -112,12 +123,12 @@ "placeholder": "*********** ****** ** ******" }, "childNodes": [], - "id": 18 + "id": 19 }, { "type": 3, "textContent": "\n ", - "id": 19 + "id": 20 }, { "type": 2, @@ -129,31 +140,31 @@ { "type": 3, "textContent": "***** ****** ** ******", - "id": 21 + "id": 22 } ], - "id": 20 + "id": 21 }, { "type": 3, "textContent": "\n ", - "id": 22 + "id": 23 }, { "type": 2, "tagName": "svg", "attributes": { - "rr_width": "200px", - "rr_height": "200px" + "rr_width": "[200-250]px", + "rr_height": "[200-250]px" }, "childNodes": [], "isSVG": true, - "id": 23 + "id": 24 }, { "type": 3, "textContent": "\n ", - "id": 24 + "id": 25 }, { "type": 2, @@ -172,7 +183,7 @@ }, "childNodes": [], "isSVG": true, - "id": 26 + "id": 27 }, { "type": 2, @@ -180,7 +191,7 @@ "attributes": {}, "childNodes": [], "isSVG": true, - "id": 27 + "id": 28 }, { "type": 2, @@ -188,31 +199,31 @@ "attributes": {}, "childNodes": [], "isSVG": true, - "id": 28 + "id": 29 } ], "isSVG": true, - "id": 25 + "id": 26 }, { "type": 3, "textContent": "\n ", - "id": 29 + "id": 30 }, { "type": 2, "tagName": "img", "attributes": { - "rr_width": "100px", - "rr_height": "100px" + "rr_width": "[100-150]px", + "rr_height": "[100-150]px" }, "childNodes": [], - "id": 30 + "id": 31 }, { "type": 3, "textContent": "\n ", - "id": 31 + "id": 32 }, { "type": 2, @@ -223,35 +234,35 @@ "src": "file:///none.png" }, "childNodes": [], - "id": 32 + "id": 33 }, { "type": 3, "textContent": "\n ", - "id": 33 + "id": 34 }, { "type": 2, "tagName": "video", "attributes": { - "rr_width": "30px", - "rr_height": "30px" + "rr_width": "[0-50]px", + "rr_height": "[0-50]px" }, "childNodes": [], - "id": 34 + "id": 35 }, { "type": 3, "textContent": "\n ", - "id": 35 + "id": 36 }, { "type": 3, "textContent": "\n\n", - "id": 36 + "id": 37 } ], - "id": 7 + "id": 8 } ], "id": 3 diff --git a/packages/integration-tests/suites/replay/privacy/test.ts-snapshots/privacy-firefox.json b/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-firefox.json similarity index 87% rename from packages/integration-tests/suites/replay/privacy/test.ts-snapshots/privacy-firefox.json rename to packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-firefox.json index d0cb968d61ff..d33a2d86b730 100644 --- a/packages/integration-tests/suites/replay/privacy/test.ts-snapshots/privacy-firefox.json +++ b/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-firefox.json @@ -27,6 +27,17 @@ }, "childNodes": [], "id": 5 + }, + { + "type": 2, + "tagName": "link", + "attributes": { + "rel": "icon", + "type": "image/png", + "href": "file:///icon/favicon.png" + }, + "childNodes": [], + "id": 6 } ], "id": 4 @@ -34,7 +45,7 @@ { "type": 3, "textContent": "\n ", - "id": 6 + "id": 7 }, { "type": 2, @@ -44,7 +55,7 @@ { "type": 3, "textContent": "\n ", - "id": 8 + "id": 9 }, { "type": 2, @@ -57,15 +68,15 @@ { "type": 3, "textContent": "***** **", - "id": 10 + "id": 11 } ], - "id": 9 + "id": 10 }, { "type": 3, "textContent": "\n ", - "id": 11 + "id": 12 }, { "type": 2, @@ -75,15 +86,15 @@ { "type": 3, "textContent": "**** ****** ** ****** ** *******", - "id": 13 + "id": 14 } ], - "id": 12 + "id": 13 }, { "type": 3, "textContent": "\n ", - "id": 14 + "id": 15 }, { "type": 2, @@ -95,15 +106,15 @@ { "type": 3, "textContent": "This should be unmasked due to data attribute", - "id": 16 + "id": 17 } ], - "id": 15 + "id": 16 }, { "type": 3, "textContent": "\n ", - "id": 17 + "id": 18 }, { "type": 2, @@ -112,12 +123,12 @@ "placeholder": "*********** ****** ** ******" }, "childNodes": [], - "id": 18 + "id": 19 }, { "type": 3, "textContent": "\n ", - "id": 19 + "id": 20 }, { "type": 2, @@ -129,31 +140,31 @@ { "type": 3, "textContent": "***** ****** ** ******", - "id": 21 + "id": 22 } ], - "id": 20 + "id": 21 }, { "type": 3, "textContent": "\n ", - "id": 22 + "id": 23 }, { "type": 2, "tagName": "svg", "attributes": { - "rr_width": "200px", - "rr_height": "200px" + "rr_width": "[200-250]px", + "rr_height": "[200-250]px" }, "childNodes": [], "isSVG": true, - "id": 23 + "id": 24 }, { "type": 3, "textContent": "\n ", - "id": 24 + "id": 25 }, { "type": 2, @@ -172,7 +183,7 @@ }, "childNodes": [], "isSVG": true, - "id": 26 + "id": 27 }, { "type": 2, @@ -180,7 +191,7 @@ "attributes": {}, "childNodes": [], "isSVG": true, - "id": 27 + "id": 28 }, { "type": 2, @@ -188,31 +199,31 @@ "attributes": {}, "childNodes": [], "isSVG": true, - "id": 28 + "id": 29 } ], "isSVG": true, - "id": 25 + "id": 26 }, { "type": 3, "textContent": "\n ", - "id": 29 + "id": 30 }, { "type": 2, "tagName": "img", "attributes": { - "rr_width": "100px", - "rr_height": "100px" + "rr_width": "[100-150]px", + "rr_height": "[100-150]px" }, "childNodes": [], - "id": 30 + "id": 31 }, { "type": 3, "textContent": "\n ", - "id": 31 + "id": 32 }, { "type": 2, @@ -223,35 +234,35 @@ "src": "file:///none.png" }, "childNodes": [], - "id": 32 + "id": 33 }, { "type": 3, "textContent": "\n ", - "id": 33 + "id": 34 }, { "type": 2, "tagName": "video", "attributes": { - "rr_width": "30px", - "rr_height": "30px" + "rr_width": "[0-50]px", + "rr_height": "[0-50]px" }, "childNodes": [], - "id": 34 + "id": 35 }, { "type": 3, "textContent": "\n ", - "id": 35 + "id": 36 }, { "type": 3, "textContent": "\n\n", - "id": 36 + "id": 37 } ], - "id": 7 + "id": 8 } ], "id": 3 diff --git a/packages/integration-tests/suites/replay/privacy/test.ts-snapshots/privacy-webkit.json b/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-webkit.json similarity index 87% rename from packages/integration-tests/suites/replay/privacy/test.ts-snapshots/privacy-webkit.json rename to packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-webkit.json index d0cb968d61ff..f31f8b967d12 100644 --- a/packages/integration-tests/suites/replay/privacy/test.ts-snapshots/privacy-webkit.json +++ b/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy-webkit.json @@ -27,6 +27,17 @@ }, "childNodes": [], "id": 5 + }, + { + "type": 2, + "tagName": "link", + "attributes": { + "rel": "icon", + "type": "image/png", + "href": "file://assets/icon/favicon.png" + }, + "childNodes": [], + "id": 6 } ], "id": 4 @@ -34,7 +45,7 @@ { "type": 3, "textContent": "\n ", - "id": 6 + "id": 7 }, { "type": 2, @@ -44,7 +55,7 @@ { "type": 3, "textContent": "\n ", - "id": 8 + "id": 9 }, { "type": 2, @@ -57,15 +68,15 @@ { "type": 3, "textContent": "***** **", - "id": 10 + "id": 11 } ], - "id": 9 + "id": 10 }, { "type": 3, "textContent": "\n ", - "id": 11 + "id": 12 }, { "type": 2, @@ -75,15 +86,15 @@ { "type": 3, "textContent": "**** ****** ** ****** ** *******", - "id": 13 + "id": 14 } ], - "id": 12 + "id": 13 }, { "type": 3, "textContent": "\n ", - "id": 14 + "id": 15 }, { "type": 2, @@ -95,15 +106,15 @@ { "type": 3, "textContent": "This should be unmasked due to data attribute", - "id": 16 + "id": 17 } ], - "id": 15 + "id": 16 }, { "type": 3, "textContent": "\n ", - "id": 17 + "id": 18 }, { "type": 2, @@ -112,12 +123,12 @@ "placeholder": "*********** ****** ** ******" }, "childNodes": [], - "id": 18 + "id": 19 }, { "type": 3, "textContent": "\n ", - "id": 19 + "id": 20 }, { "type": 2, @@ -129,31 +140,31 @@ { "type": 3, "textContent": "***** ****** ** ******", - "id": 21 + "id": 22 } ], - "id": 20 + "id": 21 }, { "type": 3, "textContent": "\n ", - "id": 22 + "id": 23 }, { "type": 2, "tagName": "svg", "attributes": { - "rr_width": "200px", - "rr_height": "200px" + "rr_width": "[200-250]px", + "rr_height": "[200-250]px" }, "childNodes": [], "isSVG": true, - "id": 23 + "id": 24 }, { "type": 3, "textContent": "\n ", - "id": 24 + "id": 25 }, { "type": 2, @@ -172,7 +183,7 @@ }, "childNodes": [], "isSVG": true, - "id": 26 + "id": 27 }, { "type": 2, @@ -180,7 +191,7 @@ "attributes": {}, "childNodes": [], "isSVG": true, - "id": 27 + "id": 28 }, { "type": 2, @@ -188,31 +199,31 @@ "attributes": {}, "childNodes": [], "isSVG": true, - "id": 28 + "id": 29 } ], "isSVG": true, - "id": 25 + "id": 26 }, { "type": 3, "textContent": "\n ", - "id": 29 + "id": 30 }, { "type": 2, "tagName": "img", "attributes": { - "rr_width": "100px", - "rr_height": "100px" + "rr_width": "[100-150]px", + "rr_height": "[100-150]px" }, "childNodes": [], - "id": 30 + "id": 31 }, { "type": 3, "textContent": "\n ", - "id": 31 + "id": 32 }, { "type": 2, @@ -223,35 +234,35 @@ "src": "file:///none.png" }, "childNodes": [], - "id": 32 + "id": 33 }, { "type": 3, "textContent": "\n ", - "id": 33 + "id": 34 }, { "type": 2, "tagName": "video", "attributes": { - "rr_width": "30px", - "rr_height": "30px" + "rr_width": "[0-50]px", + "rr_height": "[0-50]px" }, "childNodes": [], - "id": 34 + "id": 35 }, { "type": 3, "textContent": "\n ", - "id": 35 + "id": 36 }, { "type": 3, "textContent": "\n\n", - "id": 36 + "id": 37 } ], - "id": 7 + "id": 8 } ], "id": 3 diff --git a/packages/integration-tests/suites/replay/privacy/test.ts-snapshots/privacy.json b/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy.json similarity index 91% rename from packages/integration-tests/suites/replay/privacy/test.ts-snapshots/privacy.json rename to packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy.json index d0cb968d61ff..f29f31d2eb75 100644 --- a/packages/integration-tests/suites/replay/privacy/test.ts-snapshots/privacy.json +++ b/packages/integration-tests/suites/replay/privacyDefault/test.ts-snapshots/privacy.json @@ -27,6 +27,17 @@ }, "childNodes": [], "id": 5 + }, + { + "type": 2, + "tagName": "link", + "attributes": { + "rel": "icon", + "type": "image/png", + "href": "file://assets/icon/favicon.png" + }, + "childNodes": [], + "id": 6 } ], "id": 4 @@ -34,7 +45,7 @@ { "type": 3, "textContent": "\n ", - "id": 6 + "id": 7 }, { "type": 2, @@ -44,7 +55,7 @@ { "type": 3, "textContent": "\n ", - "id": 8 + "id": 9 }, { "type": 2, @@ -57,15 +68,15 @@ { "type": 3, "textContent": "***** **", - "id": 10 + "id": 11 } ], - "id": 9 + "id": 10 }, { "type": 3, "textContent": "\n ", - "id": 11 + "id": 12 }, { "type": 2, @@ -75,15 +86,15 @@ { "type": 3, "textContent": "**** ****** ** ****** ** *******", - "id": 13 + "id": 14 } ], - "id": 12 + "id": 13 }, { "type": 3, "textContent": "\n ", - "id": 14 + "id": 15 }, { "type": 2, @@ -95,15 +106,15 @@ { "type": 3, "textContent": "This should be unmasked due to data attribute", - "id": 16 + "id": 17 } ], - "id": 15 + "id": 16 }, { "type": 3, "textContent": "\n ", - "id": 17 + "id": 18 }, { "type": 2, @@ -112,12 +123,12 @@ "placeholder": "*********** ****** ** ******" }, "childNodes": [], - "id": 18 + "id": 19 }, { "type": 3, "textContent": "\n ", - "id": 19 + "id": 20 }, { "type": 2, @@ -129,15 +140,15 @@ { "type": 3, "textContent": "***** ****** ** ******", - "id": 21 + "id": 22 } ], - "id": 20 + "id": 21 }, { "type": 3, "textContent": "\n ", - "id": 22 + "id": 23 }, { "type": 2, @@ -148,12 +159,12 @@ }, "childNodes": [], "isSVG": true, - "id": 23 + "id": 24 }, { "type": 3, "textContent": "\n ", - "id": 24 + "id": 25 }, { "type": 2, @@ -172,7 +183,7 @@ }, "childNodes": [], "isSVG": true, - "id": 26 + "id": 27 }, { "type": 2, @@ -180,7 +191,7 @@ "attributes": {}, "childNodes": [], "isSVG": true, - "id": 27 + "id": 28 }, { "type": 2, @@ -188,16 +199,16 @@ "attributes": {}, "childNodes": [], "isSVG": true, - "id": 28 + "id": 29 } ], "isSVG": true, - "id": 25 + "id": 26 }, { "type": 3, "textContent": "\n ", - "id": 29 + "id": 30 }, { "type": 2, @@ -207,12 +218,12 @@ "rr_height": "100px" }, "childNodes": [], - "id": 30 + "id": 31 }, { "type": 3, "textContent": "\n ", - "id": 31 + "id": 32 }, { "type": 2, @@ -223,12 +234,12 @@ "src": "file:///none.png" }, "childNodes": [], - "id": 32 + "id": 33 }, { "type": 3, "textContent": "\n ", - "id": 33 + "id": 34 }, { "type": 2, @@ -238,20 +249,20 @@ "rr_height": "30px" }, "childNodes": [], - "id": 34 + "id": 35 }, { "type": 3, "textContent": "\n ", - "id": 35 + "id": 36 }, { "type": 3, "textContent": "\n\n", - "id": 36 + "id": 37 } ], - "id": 7 + "id": 8 } ], "id": 3 diff --git a/packages/integration-tests/utils/replayHelpers.ts b/packages/integration-tests/utils/replayHelpers.ts index a35520e0a799..8238e986b0cb 100644 --- a/packages/integration-tests/utils/replayHelpers.ts +++ b/packages/integration-tests/utils/replayHelpers.ts @@ -133,7 +133,7 @@ export function getFullRecordingSnapshots(replayRequest: Request): RecordingSnap return events.filter(event => event.type === 2).map(event => event.data as RecordingSnapshot); } -function getincrementalRecordingSnapshots(replayRequest: Request): RecordingSnapshot[] { +function getIncrementalRecordingSnapshots(replayRequest: Request): RecordingSnapshot[] { const events = getDecompressedRecordingEvents(replayRequest) as RecordingEvent[]; return events.filter(event => event.type === 3).map(event => event.data as RecordingSnapshot); } @@ -144,7 +144,7 @@ function getDecompressedRecordingEvents(replayRequest: Request): RecordingEvent[ export function getReplayRecordingContent(replayRequest: Request): RecordingContent { const fullSnapshots = getFullRecordingSnapshots(replayRequest); - const incrementalSnapshots = getincrementalRecordingSnapshots(replayRequest); + const incrementalSnapshots = getIncrementalRecordingSnapshots(replayRequest); const customEvents = getCustomRecordingEvents(replayRequest); return { fullSnapshots, incrementalSnapshots, ...customEvents }; @@ -216,10 +216,42 @@ export function shouldSkipReplayTest(): boolean { * files which break the tests on different machines. * Also, we need to normalize any time offsets as they can vary and cause flakes. */ -export function normalize(obj: unknown): string { +export function normalize( + obj: unknown, + { normalizeNumberAttributes }: { normalizeNumberAttributes?: string[] } = {}, +): string { const rawString = JSON.stringify(obj, null, 2); - const normalizedString = rawString + let normalizedString = rawString .replace(/"file:\/\/.+(\/.*\.html)"/gm, '"$1"') .replace(/"timeOffset":\s*-?\d+/gm, '"timeOffset": [timeOffset]'); + + if (normalizeNumberAttributes?.length) { + // We look for: "attr": "123px", "123", "123%", "123em", "123rem" + const regex = new RegExp( + `"(${normalizeNumberAttributes + .map(attr => `(?:${attr})`) + .join('|')})":\\s*"([\\d\\.]+)((?:px)|%|(?:em)(?:rem))?"`, + 'gm', + ); + + normalizedString = normalizedString.replace(regex, (_, attr, num, unit) => { + // Remove floating points here, to ensure this is a bit less flaky + const integer = parseInt(num, 10); + const normalizedNum = normalizeNumberAttribute(integer); + + return `"${attr}": "${normalizedNum}${unit || ''}"`; + }); + } + return normalizedString; } + +/** + * Map e.g. 16 to [0-50] or 123 to [100-150]. + */ +function normalizeNumberAttribute(num: number): string { + const step = 50; + const stepCount = Math.floor(num / step); + + return `[${stepCount * step}-${(stepCount + 1) * step}]`; +}