-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathtest.ts
More file actions
117 lines (98 loc) · 4.3 KB
/
test.ts
File metadata and controls
117 lines (98 loc) · 4.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import { expect } from '@playwright/test';
import type { Event, Profile } from '@sentry/core';
import { sentryTest } from '../../../utils/fixtures';
import {
properEnvelopeRequestParser,
shouldSkipTracingTest,
waitForTransactionRequestOnUrl,
} from '../../../utils/helpers';
sentryTest(
'does not send profile envelope when document-policy is not set',
async ({ page, getLocalTestUrl, browserName }) => {
if (shouldSkipTracingTest() || browserName !== 'chromium') {
// Profiling only works when tracing is enabled
sentryTest.skip();
}
const url = await getLocalTestUrl({ testDir: __dirname });
const req = await waitForTransactionRequestOnUrl(page, url);
const transactionEvent = properEnvelopeRequestParser<Event>(req, 0);
const profileEvent = properEnvelopeRequestParser<Profile>(req, 1);
expect(transactionEvent).toBeDefined();
expect(profileEvent).toBeUndefined();
},
);
sentryTest('sends profile envelope in legacy mode', async ({ page, getLocalTestUrl, browserName }) => {
if (shouldSkipTracingTest() || browserName !== 'chromium') {
// Profiling only works when tracing is enabled
sentryTest.skip();
}
const url = await getLocalTestUrl({ testDir: __dirname, responseHeaders: { 'Document-Policy': 'js-profiling' } });
const req = await waitForTransactionRequestOnUrl(page, url);
const profileEvent = properEnvelopeRequestParser<Profile>(req, 1);
expect(profileEvent).toBeDefined();
const profile = profileEvent.profile;
expect(profileEvent.profile).toBeDefined();
expect(profile.samples).toBeDefined();
expect(profile.stacks).toBeDefined();
expect(profile.frames).toBeDefined();
expect(profile.thread_metadata).toBeDefined();
// Samples
expect(profile.samples.length).toBeGreaterThanOrEqual(2);
for (const sample of profile.samples) {
expect(typeof sample.elapsed_since_start_ns).toBe('string');
expect(sample.elapsed_since_start_ns).toMatch(/^\d+$/); // Numeric string
expect(parseInt(sample.elapsed_since_start_ns, 10)).toBeGreaterThanOrEqual(0);
expect(typeof sample.stack_id).toBe('number');
expect(sample.stack_id).toBeGreaterThanOrEqual(0);
expect(sample.thread_id).toBe('0'); // Should be main thread
}
// Stacks
expect(profile.stacks.length).toBeGreaterThan(0);
for (const stack of profile.stacks) {
expect(Array.isArray(stack)).toBe(true);
for (const frameIndex of stack) {
expect(typeof frameIndex).toBe('number');
expect(frameIndex).toBeGreaterThanOrEqual(0);
expect(frameIndex).toBeLessThan(profile.frames.length);
}
}
// Frames
expect(profile.frames.length).toBeGreaterThan(0);
for (const frame of profile.frames) {
expect(frame).toHaveProperty('function');
expect(frame).toHaveProperty('abs_path');
expect(frame).toHaveProperty('lineno');
expect(frame).toHaveProperty('colno');
expect(typeof frame.function).toBe('string');
expect(typeof frame.abs_path).toBe('string');
expect(typeof frame.lineno).toBe('number');
expect(typeof frame.colno).toBe('number');
}
const functionNames = profile.frames.map(frame => frame.function).filter(name => name !== '');
if ((process.env.PW_BUNDLE || '').endsWith('min')) {
// Function names are minified in minified bundles
expect(functionNames.length).toBeGreaterThan(0);
expect((functionNames as string[]).every(name => name?.length > 0)).toBe(true); // Just make sure they're not empty strings
} else {
expect(functionNames).toEqual(
expect.arrayContaining([
'_startRootSpan',
'withScope',
'createChildOrRootSpan',
'startSpanManual',
'startProfileForSpan',
'startJSSelfProfile',
]),
);
}
expect(profile.thread_metadata).toHaveProperty('0');
expect(profile.thread_metadata['0']).toHaveProperty('name');
expect(profile.thread_metadata['0'].name).toBe('main');
// Test that profile duration makes sense (should be > 20ms based on test setup)
const startTime = parseInt(profile.samples[0].elapsed_since_start_ns, 10);
const endTime = parseInt(profile.samples[profile.samples.length - 1].elapsed_since_start_ns, 10);
const durationNs = endTime - startTime;
const durationMs = durationNs / 1_000_000; // Convert ns to ms
// Should be at least 20ms based on our setTimeout(21) in the test
expect(durationMs).toBeGreaterThan(20);
});