Skip to content

Commit 737e7e4

Browse files
RulaKhaledclaude
andcommitted
test(e2e): Assert Vue TanStack Router web vitals on streamed spans
Web vitals are no longer collected on segment spans, but they are still sent: TTFB, FP and FCP as attributes on the pageload span, and LCP as a standalone `ui.webvital.lcp` span. The port dropped the old `measurements` asserts without replacing them, which left Vue with no web vitals coverage at all. Extends the root route pageload test to assert both, mirroring the already ported solid-tanstack-router app. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WQM2HA4xdirxTSCtQvDRP6
1 parent ea250e4 commit 737e7e4

1 file changed

Lines changed: 27 additions & 1 deletion

File tree

‎dev-packages/e2e-tests/test-applications/vue-tanstack-router/tests/routing-instrumentation.test.ts‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,31 @@ test('sends a pageload span with a parameterized URL', async ({ page }) => {
2525
});
2626
});
2727

28-
test('sends a pageload span for the root route', async ({ page }) => {
28+
test('sends a pageload span for the root route with web vital attributes and a standalone LCP span', async ({
29+
page,
30+
}) => {
2931
const pageloadSpanPromise = waitForStreamedSpan('vue-tanstack-router', span => {
3032
return span.is_segment && getSpanOp(span) === 'pageload';
3133
});
3234

35+
const lcpSpanPromise = waitForStreamedSpan('vue-tanstack-router', span => {
36+
return getSpanOp(span) === 'ui.webvital.lcp';
37+
});
38+
3339
await page.goto(`/`);
3440

3541
const pageloadSpan = await pageloadSpanPromise;
3642

43+
// LCP is only reported once the page is hidden or a navigation happens
44+
await page.evaluate(() => {
45+
Object.defineProperty(document, 'visibilityState', { value: 'hidden', configurable: true });
46+
document.dispatchEvent(new Event('visibilitychange'));
47+
});
48+
49+
const lcpSpan = await lcpSpanPromise;
50+
51+
const webVitalNumber = { value: expect.any(Number), type: expect.stringMatching(/^(integer|double)$/) };
52+
3753
expect(pageloadSpan).toMatchObject({
3854
name: '/',
3955
is_segment: true,
@@ -44,8 +60,18 @@ test('sends a pageload span for the root route', async ({ page }) => {
4460
'url.template': { type: 'string', value: '/' },
4561
'url.path': { type: 'string', value: '/' },
4662
'url.full': { type: 'string', value: expect.stringMatching(/^https?:\/\/localhost:\d+\/$/) },
63+
'browser.web_vital.ttfb.value': webVitalNumber,
64+
'browser.web_vital.fp.value': webVitalNumber,
65+
'browser.web_vital.fcp.value': webVitalNumber,
4766
},
4867
});
68+
69+
expect(lcpSpan.attributes).toMatchObject({
70+
'sentry.op': { type: 'string', value: 'ui.webvital.lcp' },
71+
'sentry.origin': { type: 'string', value: 'auto.http.browser.lcp' },
72+
'sentry.pageload.span_id': { type: 'string', value: pageloadSpan.span_id },
73+
'browser.web_vital.lcp.value': webVitalNumber,
74+
});
4975
});
5076

5177
test('sends a navigation span with a parameterized URL', async ({ page }) => {

0 commit comments

Comments
 (0)