Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
properFullEnvelopeRequestParser,
shouldSkipTracingTest,
} from '../../../utils/helpers';
import { validateProfile, validateProfilePayloadMetadata } from '../test-utils';
import { validateProfile, validateProfileItemHeader, validateProfilePayloadMetadata } from '../test-utils';

sentryTest(
'does not send profile envelope when document-policy is not set',
Expand Down Expand Up @@ -48,7 +48,7 @@ sentryTest('sends profile_chunk envelopes in manual mode', async ({ page, getLoc
const envelopeItemHeader = profileChunkEnvelopeItem[0];
const envelopeItemPayload1 = profileChunkEnvelopeItem[1];

expect(envelopeItemHeader).toHaveProperty('type', 'profile_chunk');
validateProfileItemHeader(envelopeItemHeader);
expect(envelopeItemPayload1.profile).toBeDefined();

const profilerId1 = envelopeItemPayload1.profiler_id;
Expand All @@ -71,7 +71,7 @@ sentryTest('sends profile_chunk envelopes in manual mode', async ({ page, getLoc
const envelopeItemHeader2 = profileChunkEnvelopeItem2[0];
const envelopeItemPayload2 = profileChunkEnvelopeItem2[1];

expect(envelopeItemHeader2).toHaveProperty('type', 'profile_chunk');
validateProfileItemHeader(envelopeItemHeader2);
expect(envelopeItemPayload2.profile).toBeDefined();

expect(envelopeItemPayload2.profiler_id).toBe(profilerId1); // same profiler id for the whole session
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ interface ValidateProfileOptions {
isChunkFormat?: boolean;
}

export function validateProfileItemHeader(header: Record<string, unknown>): void {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

really sorry for the nitpicking here but I'm curious on your thoughts: I don't particularly like the pattern of these "validator" functions. Here's why:

  • I have to jump when debugging tests to get to the actual assertions
  • the stack traces when the test fails point to this validator instead of the failed test. Not ideal when the validator is used in a lot of places

Also specifically for this case: We only check that the header includes some properties but we don't assert on its entire content.

I get that the larger validateProfile helper, encapsulates a lot more assertions. Making it more justified. But for this case, with only two assertions, I'd personally avoid DRY and directly add the assertions; or even change it to just one expect(header).toEqual(...) for extra robustness.

Feel free to ignore/overrule me here :D I might be missing a reason for this.

Copy link
Copy Markdown
Member Author

@s1gr1d s1gr1d Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used this validator function here to make sure that when testing the headers, this set of assertions is used - so not a crazy reason that would overrule your concerns :D

Yes, it would make sense to just change it to this one-line assertion. The function only makes sense for the very large chunk-testing part.

Changed it to: expect(itemHeader).toEqual({ type: 'profile_chunk', platform: 'javascript' });

expect(header).toHaveProperty('type', 'profile_chunk');
expect(header).toHaveProperty('platform', 'javascript');
}

/**
* Validates the metadata of a profile chunk envelope.
* https://develop.sentry.dev/sdk/telemetry/profiles/sample-format-v2/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
properFullEnvelopeRequestParser,
shouldSkipTracingTest,
} from '../../../utils/helpers';
import { validateProfile, validateProfilePayloadMetadata } from '../test-utils';
import { validateProfile, validateProfileItemHeader, validateProfilePayloadMetadata } from '../test-utils';

sentryTest(
'does not send profile envelope when document-policy is not set',
Expand Down Expand Up @@ -51,7 +51,7 @@ sentryTest(
const envelopeItemHeader = profileChunkEnvelopeItem[0];
const envelopeItemPayload1 = profileChunkEnvelopeItem[1];

expect(envelopeItemHeader).toHaveProperty('type', 'profile_chunk');
validateProfileItemHeader(envelopeItemHeader);
expect(envelopeItemPayload1.profile).toBeDefined();

validateProfilePayloadMetadata(envelopeItemPayload1);
Expand All @@ -77,7 +77,7 @@ sentryTest(
const envelopeItemHeader2 = profileChunkEnvelopeItem2[0];
const envelopeItemPayload2 = profileChunkEnvelopeItem2[1];

expect(envelopeItemHeader2).toHaveProperty('type', 'profile_chunk');
validateProfileItemHeader(envelopeItemHeader2);
expect(envelopeItemPayload2.profile).toBeDefined();

validateProfilePayloadMetadata(envelopeItemPayload2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
shouldSkipTracingTest,
waitForTransactionRequestOnUrl,
} from '../../../utils/helpers';
import { validateProfile, validateProfilePayloadMetadata } from '../test-utils';
import { validateProfile, validateProfileItemHeader, validateProfilePayloadMetadata } from '../test-utils';

sentryTest(
'does not send profile envelope when document-policy is not set',
Expand Down Expand Up @@ -52,7 +52,7 @@ sentryTest(
const envelopeItemHeader = profileChunkEnvelopeItem[0];
const envelopeItemPayload = profileChunkEnvelopeItem[1];

expect(envelopeItemHeader).toHaveProperty('type', 'profile_chunk');
validateProfileItemHeader(envelopeItemHeader);
expect(envelopeItemPayload.profile).toBeDefined();

validateProfilePayloadMetadata(envelopeItemPayload);
Expand Down
2 changes: 1 addition & 1 deletion packages/browser/src/profiling/UIProfiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ export class UIProfiler implements ContinuousProfiler<Client> {
...(sdkInfo && { sdk: sdkInfo }),
...(!!tunnel && dsn && { dsn: dsnToString(dsn) }),
},
[[{ type: 'profile_chunk' }, chunk]],
[[{ type: 'profile_chunk', platform: 'javascript' }, chunk]],
);

client.sendEnvelope(envelope).then(null, reason => {
Expand Down
3 changes: 3 additions & 0 deletions packages/browser/test/profiling/UIProfiler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ describe('Browser Profiling v2 trace lifecycle', () => {
const transactionEnvelopeHeader = send.mock.calls?.[0]?.[0]?.[1]?.[0]?.[0];
const profileChunkEnvelopeHeader = send.mock.calls?.[1]?.[0]?.[1]?.[0]?.[0];
expect(profileChunkEnvelopeHeader?.type).toBe('profile_chunk');
expect(profileChunkEnvelopeHeader?.platform).toBe('javascript');
Comment thread
cursor[bot] marked this conversation as resolved.
expect(transactionEnvelopeHeader?.type).toBe('transaction');
});

Expand Down Expand Up @@ -207,6 +208,7 @@ describe('Browser Profiling v2 trace lifecycle', () => {
expect(mockConstructor.mock.calls.length).toBe(2);
const firstChunkHeader = send.mock.calls?.[0]?.[0]?.[1]?.[0]?.[0];
expect(firstChunkHeader?.type).toBe('profile_chunk');
expect(firstChunkHeader?.platform).toBe('javascript');

// Second chunk after another 60s
vi.advanceTimersByTime(60_000);
Expand Down Expand Up @@ -679,6 +681,7 @@ describe('Browser Profiling v2 manual lifecycle', () => {
expect(send).toHaveBeenCalledTimes(1);
const envelopeHeader = send.mock.calls?.[0]?.[0]?.[1]?.[0]?.[0];
expect(envelopeHeader?.type).toBe('profile_chunk');
expect(envelopeHeader?.platform).toBe('javascript');
});

it('calling start and stop while profile session is running prints warnings', async () => {
Expand Down
Loading