import {OrganizationFixture} from 'sentry-fixture/organization';
import {render, waitFor} from 'sentry-test/reactTestingLibrary';
import {useLocation} from 'sentry/utils/useLocation';
import usePageFilters from 'sentry/utils/usePageFilters';
import PageOverview from 'sentry/views/performance/browser/webVitals/pageOverview';
jest.mock('sentry/utils/useLocation');
jest.mock('sentry/utils/usePageFilters');
describe('PageOverview', function () {
const organization = OrganizationFixture({
features: ['insights-initial-modules'],
});
let eventsMock;
beforeEach(function () {
jest.mocked(useLocation).mockReturnValue({
pathname: '',
search: '',
query: {},
hash: '',
state: undefined,
action: 'PUSH',
key: '',
});
jest.mocked(usePageFilters).mockReturnValue({
isReady: true,
desyncedFilters: new Set(),
pinnedFilters: new Set(),
shouldPersist: true,
selection: {
datetime: {
period: '10d',
start: null,
end: null,
utc: false,
},
environments: [],
projects: [],
},
});
eventsMock = MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/events/`,
body: {
data: [],
},
});
MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/events-stats/`,
body: {},
});
MockApiClient.addMockResponse({
url: `/organizations/${organization.slug}/spans-aggregation/`,
body: {},
});
});
afterEach(function () {
jest.clearAllMocks();
});
it('renders', () => {
render(, {organization});
// Raw web vital metric tile queries
expect(eventsMock).toHaveBeenNthCalledWith(
1,
expect.anything(),
expect.objectContaining({
query: expect.objectContaining({
dataset: 'metrics',
field: [
'p75(measurements.lcp)',
'p75(measurements.fcp)',
'p75(measurements.cls)',
'p75(measurements.ttfb)',
'p75(measurements.fid)',
'p75(measurements.inp)',
'p75(transaction.duration)',
'count_web_vitals(measurements.lcp, any)',
'count_web_vitals(measurements.fcp, any)',
'count_web_vitals(measurements.cls, any)',
'count_web_vitals(measurements.fid, any)',
'count_web_vitals(measurements.ttfb, any)',
'count()',
],
query:
'transaction.op:[pageload,""] span.op:[ui.interaction.click,ui.interaction.hover,ui.interaction.drag,ui.interaction.press,""] !transaction:"<< unparameterized >>"',
}),
})
);
// Project performance score ring query
expect(eventsMock).toHaveBeenNthCalledWith(
2,
expect.anything(),
expect.objectContaining({
query: expect.objectContaining({
dataset: 'metrics',
field: [
'performance_score(measurements.score.lcp)',
'performance_score(measurements.score.fcp)',
'performance_score(measurements.score.cls)',
`performance_score(measurements.score.inp)`,
'performance_score(measurements.score.ttfb)',
'avg(measurements.score.total)',
'avg(measurements.score.weight.lcp)',
'avg(measurements.score.weight.fcp)',
'avg(measurements.score.weight.cls)',
`avg(measurements.score.weight.inp)`,
'avg(measurements.score.weight.ttfb)',
'count()',
'count_scores(measurements.score.total)',
'count_scores(measurements.score.lcp)',
'count_scores(measurements.score.fcp)',
'count_scores(measurements.score.cls)',
'count_scores(measurements.score.ttfb)',
`count_scores(measurements.score.inp)`,
],
query:
'transaction.op:[pageload,""] span.op:[ui.interaction.click,ui.interaction.hover,ui.interaction.drag,ui.interaction.press,""] !transaction:"<< unparameterized >>"',
}),
})
);
});
it('renders interaction samples', async () => {
const organizationWithInp = OrganizationFixture({
features: ['insights-initial-modules'],
});
jest.mocked(useLocation).mockReturnValue({
pathname: '',
search: '',
query: {useStoredScores: 'true', transaction: '/', type: 'interactions'},
hash: '',
state: undefined,
action: 'PUSH',
key: '',
});
render(, {organization: organizationWithInp});
await waitFor(() =>
expect(eventsMock).toHaveBeenCalledWith(
'/organizations/org-slug/events/',
expect.objectContaining({
query: expect.objectContaining({
dataset: 'spansIndexed',
field: [
'measurements.inp',
'measurements.score.inp',
'measurements.score.weight.inp',
'measurements.score.total',
'span_id',
'timestamp',
'profile_id',
'replay.id',
'user',
'origin.transaction',
'project',
'browser.name',
'span.self_time',
'span.description',
],
query:
'has:message !span.description: span.op:ui.interaction.click measurements.score.weight.inp:>0 origin.transaction:/',
}),
})
)
);
});
it('escapes transaction name before querying discover', async () => {
const organizationWithInp = OrganizationFixture({
features: ['insights-initial-modules'],
});
jest.mocked(useLocation).mockReturnValue({
pathname: '',
search: '',
query: {
useStoredScores: 'true',
transaction: '/page-with-a-*/',
type: 'interactions',
},
hash: '',
state: undefined,
action: 'PUSH',
key: '',
});
render(, {organization: organizationWithInp});
await waitFor(() =>
expect(eventsMock).toHaveBeenCalledWith(
'/organizations/org-slug/events/',
expect.objectContaining({
query: expect.objectContaining({
dataset: 'spansIndexed',
field: [
'measurements.inp',
'measurements.score.inp',
'measurements.score.weight.inp',
'measurements.score.total',
'span_id',
'timestamp',
'profile_id',
'replay.id',
'user',
'origin.transaction',
'project',
'browser.name',
'span.self_time',
'span.description',
],
query:
'has:message !span.description: span.op:ui.interaction.click measurements.score.weight.inp:>0 origin.transaction:"/page-with-a-\\*/"',
}),
})
)
);
});
});