From bec7d0172a335817be904edd4cd464829b726993 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Tue, 2 Apr 2024 17:38:28 -0400 Subject: [PATCH 01/12] Use data element as fallback in tree --- packages/utils/src/browser.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/utils/src/browser.ts b/packages/utils/src/browser.ts index 5024038822b9..9157eaf31ce1 100644 --- a/packages/utils/src/browser.ts +++ b/packages/utils/src/browser.ts @@ -88,8 +88,12 @@ function _htmlElementAsString(el: unknown, keyAttrs?: string[]): string { // @ts-expect-error WINDOW has HTMLElement if (WINDOW.HTMLElement) { // If using the component name annotation plugin, this value may be available on the DOM node - if (elem instanceof HTMLElement && elem.dataset && elem.dataset['sentryComponent']) { - return elem.dataset['sentryComponent']; + if (elem instanceof HTMLElement && elem.dataset) { + if (elem.dataset['sentryComponent']) { + return elem.dataset['sentryComponent']; + } else if (elem.dataset['sentryElement']) { + return elem.dataset['sentryElement']; + } } } From ea399c97b04470c6047e334216b26064a0f6b7d6 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Tue, 2 Apr 2024 18:38:02 -0400 Subject: [PATCH 02/12] update getComponentName --- packages/utils/src/browser.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/utils/src/browser.ts b/packages/utils/src/browser.ts index 9157eaf31ce1..69afe92853d8 100644 --- a/packages/utils/src/browser.ts +++ b/packages/utils/src/browser.ts @@ -188,8 +188,12 @@ export function getComponentName(elem: unknown): string | null { return null; } - if (currentElem instanceof HTMLElement && currentElem.dataset['sentryComponent']) { - return currentElem.dataset['sentryComponent']; + if (currentElem instanceof HTMLElement) { + if (currentElem.dataset['sentryComponent']) { + return currentElem.dataset['sentryComponent']; + } else if (currentElem.dataset['sentryElement']) { + return currentElem.dataset['sentryElement']; + } } currentElem = currentElem.parentNode; From 52b564326aa75054b511ac3771c30a655a2fa254 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Wed, 3 Apr 2024 11:37:47 -0400 Subject: [PATCH 03/12] add test --- .../integrations/Breadcrumbs/dom/click/template.html | 3 ++- .../suites/integrations/Breadcrumbs/dom/click/test.ts | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/click/template.html b/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/click/template.html index e54da47ff09d..977701b32bc2 100644 --- a/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/click/template.html +++ b/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/click/template.html @@ -7,6 +7,7 @@ - + + diff --git a/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/click/test.ts b/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/click/test.ts index 0b877fb7c8d8..d6dd646b9965 100644 --- a/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/click/test.ts +++ b/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/click/test.ts @@ -78,6 +78,7 @@ sentryTest( await page.goto(url); await page.locator('#annotated-button').click(); + await page.locator('#annotated-button-2').click(); const [eventData] = await Promise.all([promise, page.evaluate('Sentry.captureException("test exception")')]); @@ -88,6 +89,12 @@ sentryTest( message: 'body > AnnotatedButton', data: { 'ui.component_name': 'AnnotatedButton' }, }, + { + timestamp: expect.any(Number), + category: 'ui.click', + message: 'body > StyledButton', + data: { 'ui.component_name': 'StyledButton' }, + }, ]); }, ); From c5254d953689277b140a31d16d262adc671dc2dc Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Wed, 3 Apr 2024 11:52:42 -0400 Subject: [PATCH 04/12] fix typo --- .../suites/integrations/Breadcrumbs/dom/click/template.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/click/template.html b/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/click/template.html index 977701b32bc2..97d2b9069eb4 100644 --- a/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/click/template.html +++ b/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/click/template.html @@ -8,6 +8,6 @@ - + From 81b718efca0b541c17eaab3480d5681a4ff0454b Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Wed, 3 Apr 2024 16:46:06 -0400 Subject: [PATCH 05/12] add more tests --- .../Breadcrumbs/dom/textInput/template.html | 3 +- .../Breadcrumbs/dom/textInput/test.ts | 7 ++++ .../replay/captureComponentName/template.html | 6 ++-- .../replay/captureComponentName/test.ts | 36 +++++++++++++++++++ .../interactions/template.html | 3 +- .../interactions/test.ts | 7 +++- .../util/getAttributesToRecord.ts | 1 + packages/utils/src/browser.ts | 4 +-- 8 files changed, 60 insertions(+), 7 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/textInput/template.html b/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/textInput/template.html index a16ca41e45da..38934ca803a4 100644 --- a/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/textInput/template.html +++ b/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/textInput/template.html @@ -7,6 +7,7 @@ - + + diff --git a/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/textInput/test.ts b/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/textInput/test.ts index b4549a105c7a..d7544fbf891e 100644 --- a/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/textInput/test.ts +++ b/dev-packages/browser-integration-tests/suites/integrations/Breadcrumbs/dom/textInput/test.ts @@ -83,6 +83,7 @@ sentryTest( await page.goto(url); await page.locator('#annotated-input').pressSequentially('John', { delay: 1 }); + await page.locator('#annotated-input-2').pressSequentially('John', { delay: 1 }); await page.evaluate('Sentry.captureException("test exception")'); const eventData = await promise; @@ -95,6 +96,12 @@ sentryTest( message: 'body > AnnotatedInput', data: { 'ui.component_name': 'AnnotatedInput' }, }, + { + timestamp: expect.any(Number), + category: 'ui.input', + message: 'body > StyledInput', + data: { 'ui.component_name': 'StyledInput' }, + }, ]); }, ); diff --git a/dev-packages/browser-integration-tests/suites/replay/captureComponentName/template.html b/dev-packages/browser-integration-tests/suites/replay/captureComponentName/template.html index 1cb45daa349a..2501d595be00 100644 --- a/dev-packages/browser-integration-tests/suites/replay/captureComponentName/template.html +++ b/dev-packages/browser-integration-tests/suites/replay/captureComponentName/template.html @@ -4,7 +4,9 @@ - - + + + + diff --git a/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts b/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts index 99b7a71273e3..7e45c27fc941 100644 --- a/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts @@ -37,6 +37,12 @@ sentryTest('captures component name attribute when available', async ({ forceFlu await page.keyboard.press('Control+A'); await page.keyboard.type('Hello', { delay: 10 }); + await page.locator('#button2').click(); + + await page.locator('#input2').focus(); + await page.keyboard.press('Control+A'); + await page.keyboard.type('Hello', { delay: 10 }); + await forceFlushReplay(); const { breadcrumbs } = getCustomRecordingEvents(await reqPromise1); const { breadcrumbs: breadcrumbs2 } = getCustomRecordingEvents(await reqPromise2); @@ -79,5 +85,35 @@ sentryTest('captures component name attribute when available', async ({ forceFlu }, }, }, + { + timestamp: expect.any(Number), + type: 'default', + category: 'ui.click', + message: 'body > StyledCoolButton', + data: { + nodeId: expect.any(Number), + node: { + attributes: { id: 'button', 'data-sentry-element': 'StyledCoolButton' }, + id: expect.any(Number), + tagName: 'button', + textContent: '**', + }, + }, + }, + { + timestamp: expect.any(Number), + type: 'default', + category: 'ui.input', + message: 'body > StyledCoolInput', + data: { + nodeId: expect.any(Number), + node: { + attributes: { id: 'input', 'data-sentry-element': 'StyledCoolInput' }, + id: expect.any(Number), + tagName: 'input', + textContent: '', + }, + }, + }, ]); }); diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/template.html b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/template.html index 3357fb20a94e..d3bda54d7443 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/template.html +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/template.html @@ -6,7 +6,8 @@
Rendered Before Long Task
- + + diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/test.ts b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/test.ts index 224d352ec851..b773d20ebda3 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/test.ts @@ -100,15 +100,20 @@ sentryTest( await getFirstSentryEnvelopeRequest(page); await page.locator('[data-test-id=annotated-button]').click(); + await page.locator('[data-test-id=styled-button]').click(); const envelopes = await getMultipleSentryEnvelopeRequests(page, 1); expect(envelopes).toHaveLength(1); const eventData = envelopes[0]; - expect(eventData.spans).toHaveLength(1); + expect(eventData.spans).toHaveLength(2); const interactionSpan = eventData.spans![0]; expect(interactionSpan.op).toBe('ui.interaction.click'); expect(interactionSpan.description).toBe('body > AnnotatedButton'); + + const interactionSpan2 = eventData.spans![1]; + expect(interactionSpan2.op).toBe('ui.interaction.click'); + expect(interactionSpan2.description).toBe('body > StyledButton'); }, ); diff --git a/packages/replay-internal/src/coreHandlers/util/getAttributesToRecord.ts b/packages/replay-internal/src/coreHandlers/util/getAttributesToRecord.ts index f50c2b9f9088..8abdcbc04e75 100644 --- a/packages/replay-internal/src/coreHandlers/util/getAttributesToRecord.ts +++ b/packages/replay-internal/src/coreHandlers/util/getAttributesToRecord.ts @@ -13,6 +13,7 @@ const ATTRIBUTES_TO_RECORD = new Set([ 'disabled', 'aria-disabled', 'data-sentry-component', + 'data-sentry-element', ]); /** diff --git a/packages/utils/src/browser.ts b/packages/utils/src/browser.ts index 69afe92853d8..19b167da5013 100644 --- a/packages/utils/src/browser.ts +++ b/packages/utils/src/browser.ts @@ -170,8 +170,8 @@ export function getDomElement(selector: string): E | null { /** * Given a DOM element, traverses up the tree until it finds the first ancestor node - * that has the `data-sentry-component` attribute. This attribute is added at build-time - * by projects that have the component name annotation plugin installed. + * that has the `data-sentry-component` or `data-sentry-element` attribute with `data-sentry-component` taking + * precendence. This attribute is added at build-time by projects that have the component name annotation plugin installed. * * @returns a string representation of the component for the provided DOM element, or `null` if not found */ From 962f8335eaf51b5421f13faa3a41b2c831417e75 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Wed, 3 Apr 2024 17:16:55 -0400 Subject: [PATCH 06/12] tracing test --- .../interactions/test.ts | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/test.ts b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/test.ts index b773d20ebda3..0da6d7cef036 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/test.ts @@ -106,14 +106,42 @@ sentryTest( expect(envelopes).toHaveLength(1); const eventData = envelopes[0]; - expect(eventData.spans).toHaveLength(2); + expect(eventData.spans).toHaveLength(1); const interactionSpan = eventData.spans![0]; expect(interactionSpan.op).toBe('ui.interaction.click'); expect(interactionSpan.description).toBe('body > AnnotatedButton'); + }, +); + +sentryTest( + 'should use the element name for a clicked element when no component name', + async ({ browserName, getLocalTestPath, page }) => { + const supportedBrowsers = ['chromium', 'firefox']; + + if (shouldSkipTracingTest() || !supportedBrowsers.includes(browserName)) { + sentryTest.skip(); + } + + await page.route('**/path/to/script.js', (route: Route) => + route.fulfill({ path: `${__dirname}/assets/script.js` }), + ); - const interactionSpan2 = eventData.spans![1]; - expect(interactionSpan2.op).toBe('ui.interaction.click'); - expect(interactionSpan2.description).toBe('body > StyledButton'); + const url = await getLocalTestPath({ testDir: __dirname }); + + await page.goto(url); + await getFirstSentryEnvelopeRequest(page); + + await page.locator('[data-test-id=styled-button]').click(); + + const envelopes = await getMultipleSentryEnvelopeRequests(page, 1); + expect(envelopes).toHaveLength(1); + const eventData = envelopes[0]; + + expect(eventData.spans).toHaveLength(1); + + const interactionSpan = eventData.spans![0]; + expect(interactionSpan.op).toBe('ui.interaction.click'); + expect(interactionSpan.description).toBe('body > StyledButton'); }, ); From e81fdf43b6c3adb946093026e2935c65e71ab691 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Wed, 3 Apr 2024 17:25:17 -0400 Subject: [PATCH 07/12] fix test --- .../tracing/browserTracingIntegration/interactions/test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/test.ts b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/test.ts index 0da6d7cef036..5b032ace7f8c 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/test.ts @@ -100,7 +100,6 @@ sentryTest( await getFirstSentryEnvelopeRequest(page); await page.locator('[data-test-id=annotated-button]').click(); - await page.locator('[data-test-id=styled-button]').click(); const envelopes = await getMultipleSentryEnvelopeRequests(page, 1); expect(envelopes).toHaveLength(1); From 70232d2e07eee4f9ae46e234a3be01fdda1aceac Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Wed, 3 Apr 2024 17:41:56 -0400 Subject: [PATCH 08/12] fix test again --- .../replay/captureComponentName/template.html | 2 - .../replay/captureComponentName/test.ts | 40 +------------------ 2 files changed, 2 insertions(+), 40 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/replay/captureComponentName/template.html b/dev-packages/browser-integration-tests/suites/replay/captureComponentName/template.html index 2501d595be00..9e06ca97724f 100644 --- a/dev-packages/browser-integration-tests/suites/replay/captureComponentName/template.html +++ b/dev-packages/browser-integration-tests/suites/replay/captureComponentName/template.html @@ -6,7 +6,5 @@ - - diff --git a/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts b/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts index 7e45c27fc941..898b427f3bd8 100644 --- a/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts @@ -37,12 +37,6 @@ sentryTest('captures component name attribute when available', async ({ forceFlu await page.keyboard.press('Control+A'); await page.keyboard.type('Hello', { delay: 10 }); - await page.locator('#button2').click(); - - await page.locator('#input2').focus(); - await page.keyboard.press('Control+A'); - await page.keyboard.type('Hello', { delay: 10 }); - await forceFlushReplay(); const { breadcrumbs } = getCustomRecordingEvents(await reqPromise1); const { breadcrumbs: breadcrumbs2 } = getCustomRecordingEvents(await reqPromise2); @@ -63,7 +57,7 @@ sentryTest('captures component name attribute when available', async ({ forceFlu data: { nodeId: expect.any(Number), node: { - attributes: { id: 'button', 'data-sentry-component': 'MyCoolButton' }, + attributes: { id: 'button', 'data-sentry-component': 'MyCoolButton', 'data-sentry-element': 'StyledCoolInput' }, id: expect.any(Number), tagName: 'button', textContent: '**', @@ -78,37 +72,7 @@ sentryTest('captures component name attribute when available', async ({ forceFlu data: { nodeId: expect.any(Number), node: { - attributes: { id: 'input', 'data-sentry-component': 'MyCoolInput' }, - id: expect.any(Number), - tagName: 'input', - textContent: '', - }, - }, - }, - { - timestamp: expect.any(Number), - type: 'default', - category: 'ui.click', - message: 'body > StyledCoolButton', - data: { - nodeId: expect.any(Number), - node: { - attributes: { id: 'button', 'data-sentry-element': 'StyledCoolButton' }, - id: expect.any(Number), - tagName: 'button', - textContent: '**', - }, - }, - }, - { - timestamp: expect.any(Number), - type: 'default', - category: 'ui.input', - message: 'body > StyledCoolInput', - data: { - nodeId: expect.any(Number), - node: { - attributes: { id: 'input', 'data-sentry-element': 'StyledCoolInput' }, + attributes: { id: 'input', 'data-sentry-component': 'MyCoolInput', 'data-sentry-element': 'StyledCoolInput' }, id: expect.any(Number), tagName: 'input', textContent: '', From e1e7bbb785725ef34396382117b684a6a693d477 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Wed, 3 Apr 2024 17:50:08 -0400 Subject: [PATCH 09/12] pass CI --- .../suites/replay/captureComponentName/test.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts b/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts index 898b427f3bd8..517cf0bc9f3b 100644 --- a/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts @@ -57,7 +57,11 @@ sentryTest('captures component name attribute when available', async ({ forceFlu data: { nodeId: expect.any(Number), node: { - attributes: { id: 'button', 'data-sentry-component': 'MyCoolButton', 'data-sentry-element': 'StyledCoolInput' }, + attributes: { + id: 'button', + 'data-sentry-component': 'MyCoolButton', + 'data-sentry-element': 'StyledCoolButton', + }, id: expect.any(Number), tagName: 'button', textContent: '**', @@ -72,7 +76,11 @@ sentryTest('captures component name attribute when available', async ({ forceFlu data: { nodeId: expect.any(Number), node: { - attributes: { id: 'input', 'data-sentry-component': 'MyCoolInput', 'data-sentry-element': 'StyledCoolInput' }, + attributes: { + id: 'input', + 'data-sentry-component': 'MyCoolInput', + 'data-sentry-element': 'StyledCoolInput', + }, id: expect.any(Number), tagName: 'input', textContent: '', From 57e7d4d1a53a80340527ddbacdf548249ebb0d69 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Thu, 4 Apr 2024 12:51:17 -0400 Subject: [PATCH 10/12] set component name to data-sentry-element when appropriate --- .../replay/captureComponentName/template.html | 2 + .../replay/captureComponentName/test.ts | 87 ++++++++++++++++++- .../util/getAttributesToRecord.ts | 4 +- .../util/getAttributesToRecord.test.ts | 18 ++++ 4 files changed, 108 insertions(+), 3 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/replay/captureComponentName/template.html b/dev-packages/browser-integration-tests/suites/replay/captureComponentName/template.html index 9e06ca97724f..2501d595be00 100644 --- a/dev-packages/browser-integration-tests/suites/replay/captureComponentName/template.html +++ b/dev-packages/browser-integration-tests/suites/replay/captureComponentName/template.html @@ -6,5 +6,7 @@ + + diff --git a/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts b/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts index 517cf0bc9f3b..9517876fb4b4 100644 --- a/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts @@ -60,7 +60,6 @@ sentryTest('captures component name attribute when available', async ({ forceFlu attributes: { id: 'button', 'data-sentry-component': 'MyCoolButton', - 'data-sentry-element': 'StyledCoolButton', }, id: expect.any(Number), tagName: 'button', @@ -79,7 +78,91 @@ sentryTest('captures component name attribute when available', async ({ forceFlu attributes: { id: 'input', 'data-sentry-component': 'MyCoolInput', - 'data-sentry-element': 'StyledCoolInput', + }, + id: expect.any(Number), + tagName: 'input', + textContent: '', + }, + }, + }, + ]); +}); + +sentryTest('sets element name to component name attribute when no component name', async ({ forceFlushReplay, 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); + await reqPromise0; + await forceFlushReplay(); + + const reqPromise1 = waitForReplayRequest(page, (event, res) => { + return getCustomRecordingEvents(res).breadcrumbs.some(breadcrumb => breadcrumb.category === 'ui.click'); + }); + const reqPromise2 = waitForReplayRequest(page, (event, res) => { + return getCustomRecordingEvents(res).breadcrumbs.some(breadcrumb => breadcrumb.category === 'ui.input'); + }); + + await page.locator('#button2').click(); + + await page.locator('#input2').focus(); + await page.keyboard.press('Control+A'); + await page.keyboard.type('Hello', { delay: 10 }); + + await forceFlushReplay(); + const { breadcrumbs } = getCustomRecordingEvents(await reqPromise1); + const { breadcrumbs: breadcrumbs2 } = getCustomRecordingEvents(await reqPromise2); + + // Combine the two together + breadcrumbs2.forEach(breadcrumb => { + if (!breadcrumbs.some(b => b.category === breadcrumb.category && b.timestamp === breadcrumb.timestamp)) { + breadcrumbs.push(breadcrumb); + } + }); + + expect(breadcrumbs).toEqual([ + { + timestamp: expect.any(Number), + type: 'default', + category: 'ui.click', + message: 'body > StyledCoolButton', + data: { + nodeId: expect.any(Number), + node: { + attributes: { + id: 'button2', + 'data-sentry-component': 'StyledCoolButton', + }, + id: expect.any(Number), + tagName: 'button', + textContent: '**', + }, + }, + }, + { + timestamp: expect.any(Number), + type: 'default', + category: 'ui.input', + message: 'body > StyledCoolInput', + data: { + nodeId: expect.any(Number), + node: { + attributes: { + id: 'input2', + 'data-sentry-component': 'StyledCoolInput', }, id: expect.any(Number), tagName: 'input', diff --git a/packages/replay-internal/src/coreHandlers/util/getAttributesToRecord.ts b/packages/replay-internal/src/coreHandlers/util/getAttributesToRecord.ts index 8abdcbc04e75..d2d062926811 100644 --- a/packages/replay-internal/src/coreHandlers/util/getAttributesToRecord.ts +++ b/packages/replay-internal/src/coreHandlers/util/getAttributesToRecord.ts @@ -13,7 +13,6 @@ const ATTRIBUTES_TO_RECORD = new Set([ 'disabled', 'aria-disabled', 'data-sentry-component', - 'data-sentry-element', ]); /** @@ -21,6 +20,9 @@ const ATTRIBUTES_TO_RECORD = new Set([ */ export function getAttributesToRecord(attributes: Record): Record { const obj: Record = {}; + if (!attributes['data-sentry-component'] && attributes['data-sentry-element']) { + attributes['data-sentry-component'] = attributes['data-sentry-element']; + } for (const key in attributes) { if (ATTRIBUTES_TO_RECORD.has(key)) { let normalizedKey = key; diff --git a/packages/replay-internal/test/unit/coreHandlers/util/getAttributesToRecord.test.ts b/packages/replay-internal/test/unit/coreHandlers/util/getAttributesToRecord.test.ts index 46211820e2c7..393d58427e34 100644 --- a/packages/replay-internal/test/unit/coreHandlers/util/getAttributesToRecord.test.ts +++ b/packages/replay-internal/test/unit/coreHandlers/util/getAttributesToRecord.test.ts @@ -30,3 +30,21 @@ it('records only included attributes', function () { }), ).toEqual({}); }); + +it('records data-sentry-element as data-sentry-component when appropriate', function () { + expect( + getAttributesToRecord({ + ['data-sentry-component']: 'component', + ['data-sentry-element']: 'element', + }), + ).toEqual({ + ['data-sentry-component']: 'component', + }); + expect( + getAttributesToRecord({ + ['data-sentry-element']: 'element', + }), + ).toEqual({ + ['data-sentry-component']: 'element', + }); +}); From 830b947f287e4a44140c44390a6668a6d299905a Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Thu, 4 Apr 2024 14:27:16 -0400 Subject: [PATCH 11/12] fix CI --- .../suites/replay/captureComponentName/test.ts | 2 +- .../browserTracingIntegration/interactions/assets/script.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts b/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts index 9517876fb4b4..9ad1a99c32aa 100644 --- a/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts +++ b/dev-packages/browser-integration-tests/suites/replay/captureComponentName/test.ts @@ -88,7 +88,7 @@ sentryTest('captures component name attribute when available', async ({ forceFlu ]); }); -sentryTest('sets element name to component name attribute when no component name', async ({ forceFlushReplay, getLocalTestPath, page }) => { +sentryTest('sets element name to component name attribute', async ({ forceFlushReplay, getLocalTestPath, page }) => { if (shouldSkipReplayTest()) { sentryTest.skip(); } diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/assets/script.js b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/assets/script.js index a37a2c70ad27..fecb5ca8a758 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/assets/script.js +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/assets/script.js @@ -15,3 +15,4 @@ const delay = e => { document.querySelector('[data-test-id=interaction-button]').addEventListener('click', delay); document.querySelector('[data-test-id=annotated-button]').addEventListener('click', delay); +document.querySelector('[data-test-id=styled-button]').addEventListener('click', delay); From 84677fcbe08b37b01ff84ecd31ccd0e4968ba05e Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Thu, 4 Apr 2024 14:29:51 -0400 Subject: [PATCH 12/12] improve readability --- packages/utils/src/browser.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/utils/src/browser.ts b/packages/utils/src/browser.ts index 19b167da5013..371e7e96c8c2 100644 --- a/packages/utils/src/browser.ts +++ b/packages/utils/src/browser.ts @@ -91,7 +91,8 @@ function _htmlElementAsString(el: unknown, keyAttrs?: string[]): string { if (elem instanceof HTMLElement && elem.dataset) { if (elem.dataset['sentryComponent']) { return elem.dataset['sentryComponent']; - } else if (elem.dataset['sentryElement']) { + } + if (elem.dataset['sentryElement']) { return elem.dataset['sentryElement']; } } @@ -191,7 +192,8 @@ export function getComponentName(elem: unknown): string | null { if (currentElem instanceof HTMLElement) { if (currentElem.dataset['sentryComponent']) { return currentElem.dataset['sentryComponent']; - } else if (currentElem.dataset['sentryElement']) { + } + if (currentElem.dataset['sentryElement']) { return currentElem.dataset['sentryElement']; } }