Skip to content

Commit eab0354

Browse files
committed
try tests in CI - new INP tests
1 parent f0a6094 commit eab0354

File tree

6 files changed

+212
-50
lines changed

6 files changed

+212
-50
lines changed

dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/init.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ Sentry.init({
1111
_experiments: {
1212
enableInteractions: true,
1313
},
14-
enableInp: true,
1514
}),
1615
],
1716
tracesSampleRate: 1,

dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/test.ts

Lines changed: 23 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -113,60 +113,34 @@ sentryTest(
113113
},
114114
);
115115

116-
sentryTest('should capture an INP click event span. @firefox', async ({ browserName, getLocalTestPath, page }) => {
117-
const supportedBrowsers = ['chromium', 'firefox'];
118-
119-
if (shouldSkipTracingTest() || !supportedBrowsers.includes(browserName)) {
120-
sentryTest.skip();
121-
}
122-
123-
await page.route('**/path/to/script.js', (route: Route) => route.fulfill({ path: `${__dirname}/assets/script.js` }));
124-
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
125-
return route.fulfill({
126-
status: 200,
127-
contentType: 'application/json',
128-
body: JSON.stringify({ id: 'test-id' }),
129-
});
130-
});
131-
132-
const url = await getLocalTestPath({ testDir: __dirname });
133-
134-
await page.goto(url);
135-
await getFirstSentryEnvelopeRequest<SentryEvent>(page); // waiting for page load
136-
137-
const spanEnvelopesPromise = getMultipleSentryEnvelopeRequests<SpanJSON>(page, 1, {
138-
envelopeType: 'span',
139-
});
140-
141-
await page.locator('[data-test-id=interaction-button]').click();
142-
await page.locator('.clicked[data-test-id=interaction-button]').isVisible();
116+
sentryTest(
117+
'should use the element name for a clicked element when no component name',
118+
async ({ browserName, getLocalTestPath, page }) => {
119+
const supportedBrowsers = ['chromium', 'firefox'];
143120

144-
// eslint-disable-next-line no-console
145-
console.log('buttons clicked');
121+
if (shouldSkipTracingTest() || !supportedBrowsers.includes(browserName)) {
122+
sentryTest.skip();
123+
}
146124

147-
// Wait for the interaction transaction from the experimental enableInteractions (in init.js)
148-
await getMultipleSentryEnvelopeRequests<TransactionJSON>(page, 1);
125+
await page.route('**/path/to/script.js', (route: Route) =>
126+
route.fulfill({ path: `${__dirname}/assets/script.js` }),
127+
);
149128

150-
// eslint-disable-next-line no-console
151-
console.log('waited for interaction ev');
129+
const url = await getLocalTestPath({ testDir: __dirname });
152130

153-
// Page hide to trigger INP
154-
await page.evaluate(() => {
155-
window.dispatchEvent(new Event('pagehide'));
156-
});
131+
await page.goto(url);
132+
await getFirstSentryEnvelopeRequest<SentryEvent>(page);
157133

158-
// eslint-disable-next-line no-console
159-
console.log('pagehide done');
134+
await page.locator('[data-test-id=styled-button]').click();
160135

161-
// Get the INP span envelope
162-
const spanEnvelopes = await spanEnvelopesPromise;
136+
const envelopes = await getMultipleSentryEnvelopeRequests<TransactionJSON>(page, 1);
137+
expect(envelopes).toHaveLength(1);
138+
const eventData = envelopes[0];
163139

164-
// eslint-disable-next-line no-console
165-
console.log('spanevents', spanEnvelopes);
140+
expect(eventData.spans).toHaveLength(1);
166141

167-
expect(spanEnvelopes[0].op).toBe('ui.interaction.click');
168-
expect(spanEnvelopes[0].description).toBe('body > button.clicked');
169-
expect(spanEnvelopes[0].exclusive_time).toBeGreaterThan(0);
170-
expect(spanEnvelopes[0].measurements?.inp.value).toBeGreaterThan(0);
171-
expect(spanEnvelopes[0].measurements?.inp.unit).toBe('millisecond');
172-
});
142+
const interactionSpan = eventData.spans![0];
143+
expect(interactionSpan.op).toBe('ui.interaction.click');
144+
expect(interactionSpan.description).toBe('body > StyledButton');
145+
},
146+
);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const delay = (delay = 70) => e => {
2+
const startTime = Date.now();
3+
4+
function getElasped() {
5+
const time = Date.now();
6+
return time - startTime;
7+
}
8+
9+
while (getElasped() < delay) {
10+
//
11+
}
12+
13+
e.target.classList.add('clicked');
14+
};
15+
16+
document.querySelector('[data-test-id=slow-interaction-button]').addEventListener('click', delay(200));
17+
document.querySelector('[data-test-id=interaction-button]').addEventListener('click', delay());
18+
document.querySelector('[data-test-id=annotated-button]').addEventListener('click', delay());
19+
document.querySelector('[data-test-id=styled-button]').addEventListener('click', delay());
20+
21+
document.querySelector('[data-test-id=click-me-button]').addEventListener('click', function (e) {
22+
this.textContent = 'Clicked!';
23+
requestAnimationFrame(() => {
24+
e.target.classList.add('clicked');
25+
requestAnimationFrame(() => {
26+
this.textContent = 'Click me';
27+
});
28+
});
29+
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import * as Sentry from '@sentry/browser';
2+
3+
window.Sentry = Sentry;
4+
5+
Sentry.init({
6+
dsn: 'https://[email protected]/1337',
7+
integrations: [
8+
Sentry.browserTracingIntegration({
9+
idleTimeout: 1000,
10+
enableLongTask: false,
11+
enableInp: true,
12+
}),
13+
],
14+
tracesSampleRate: 1,
15+
});
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
</head>
6+
<body>
7+
<div>Rendered Before Long Task</div>
8+
<button data-test-id="interaction-button">Click Me</button>
9+
<button data-test-id="slow-interaction-button">Also Click Me</button>
10+
<button data-test-id="annotated-button" data-sentry-component="AnnotatedButton" data-sentry-element="StyledButton">Click Me</button>
11+
<button data-test-id="styled-button" data-sentry-element="StyledButton">Click Me</button>
12+
<button data-test-id="click-me-button">Subscribe</button>
13+
14+
<script src="https://example.com/path/to/script.js"></script>
15+
</body>
16+
</html>
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import type { Route } from '@playwright/test';
2+
import { expect } from '@playwright/test';
3+
import type { Event as SentryEvent, SpanJSON } from '@sentry/types';
4+
5+
import { sentryTest } from '../../../../utils/fixtures';
6+
import {
7+
getFirstSentryEnvelopeRequest,
8+
getMultipleSentryEnvelopeRequests,
9+
shouldSkipTracingTest,
10+
} from '../../../../utils/helpers';
11+
12+
sentryTest('should capture an INP click event span.', async ({ browserName, getLocalTestPath, page }) => {
13+
const supportedBrowsers = ['chromium'];
14+
15+
if (shouldSkipTracingTest() || !supportedBrowsers.includes(browserName)) {
16+
sentryTest.skip();
17+
}
18+
19+
await page.route('**/path/to/script.js', (route: Route) => route.fulfill({ path: `${__dirname}/assets/script.js` }));
20+
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
21+
return route.fulfill({
22+
status: 200,
23+
contentType: 'application/json',
24+
body: JSON.stringify({ id: 'test-id' }),
25+
});
26+
});
27+
28+
const url = await getLocalTestPath({ testDir: __dirname });
29+
30+
await page.goto(url);
31+
await getFirstSentryEnvelopeRequest<SentryEvent>(page); // wait for page load
32+
33+
const spanEnvelopesPromise = getMultipleSentryEnvelopeRequests<SpanJSON>(page, 1, {
34+
// envelopeType: 'span', // todo: does not work with envelopType
35+
});
36+
37+
await page.locator('[data-test-id=interaction-button]').click();
38+
await page.locator('.clicked[data-test-id=interaction-button]').isVisible();
39+
40+
// eslint-disable-next-line no-console
41+
console.log('buttons clicked');
42+
43+
// Page hide to trigger INP
44+
await page.evaluate(() => {
45+
// eslint-disable-next-line no-console
46+
console.log('dispatching event');
47+
window.dispatchEvent(new Event('pagehide'));
48+
});
49+
50+
// eslint-disable-next-line no-console
51+
console.log('event dispatched');
52+
53+
// Get the INP span envelope
54+
const spanEnvelopes = await spanEnvelopesPromise;
55+
56+
// eslint-disable-next-line no-console
57+
console.log('waited for envelope');
58+
59+
// expect(spanEnvelopes).toBe(1);
60+
61+
expect(spanEnvelopes).toHaveLength(1);
62+
expect(spanEnvelopes[0].op).toBe('ui.interaction.click');
63+
expect(spanEnvelopes[0].description).toBe('body > button.clicked');
64+
expect(spanEnvelopes[0].exclusive_time).toBeGreaterThan(0);
65+
expect(spanEnvelopes[0].measurements?.inp.value).toBeGreaterThan(0);
66+
expect(spanEnvelopes[0].measurements?.inp.unit).toBe('millisecond');
67+
});
68+
69+
sentryTest(
70+
'should choose the slowest interaction click event when INP is triggered.',
71+
async ({ browserName, getLocalTestPath, page }) => {
72+
const supportedBrowsers = ['chromium'];
73+
74+
if (shouldSkipTracingTest() || !supportedBrowsers.includes(browserName)) {
75+
sentryTest.skip();
76+
}
77+
78+
await page.route('**/path/to/script.js', (route: Route) =>
79+
route.fulfill({ path: `${__dirname}/assets/script.js` }),
80+
);
81+
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
82+
return route.fulfill({
83+
status: 200,
84+
contentType: 'application/json',
85+
body: JSON.stringify({ id: 'test-id' }),
86+
});
87+
});
88+
89+
const url = await getLocalTestPath({ testDir: __dirname });
90+
91+
await page.goto(url);
92+
await getFirstSentryEnvelopeRequest<SentryEvent>(page);
93+
94+
const spanEnvelopesPromise = getMultipleSentryEnvelopeRequests<SpanJSON>(page, 1, {
95+
// envelopeType: 'span',
96+
});
97+
98+
await page.locator('[data-test-id=interaction-button]').click();
99+
await page.locator('.clicked[data-test-id=interaction-button]').isVisible();
100+
101+
// eslint-disable-next-line no-console
102+
console.log('2 - clicked first time');
103+
104+
await page.locator('[data-test-id=slow-interaction-button]').click();
105+
await page.locator('.clicked[data-test-id=slow-interaction-button]').isVisible();
106+
107+
// eslint-disable-next-line no-console
108+
console.log('2 - clicked second time');
109+
110+
// Page hide to trigger INP
111+
await page.evaluate(() => {
112+
window.dispatchEvent(new Event('pagehide'));
113+
});
114+
115+
// eslint-disable-next-line no-console
116+
console.log('2 - dispatched event');
117+
118+
// Get the INP span envelope
119+
const spanEnvelopes = await spanEnvelopesPromise;
120+
121+
// expect(spanEnvelopes).toBe(2);
122+
expect(spanEnvelopes).toHaveLength(1);
123+
expect(spanEnvelopes[0].op).toBe('ui.interaction.click');
124+
expect(spanEnvelopes[0].description).toBe('body > button.clicked');
125+
expect(spanEnvelopes[0].exclusive_time).toBeGreaterThan(150);
126+
expect(spanEnvelopes[0].measurements?.inp.value).toBeGreaterThan(150);
127+
expect(spanEnvelopes[0].measurements?.inp.unit).toBe('millisecond');
128+
},
129+
);

0 commit comments

Comments
 (0)