import {OrganizationFixture} from 'sentry-fixture/organization';
import {render, screen, waitForElementToBeRemoved} from 'sentry-test/reactTestingLibrary';
import {useLocation} from 'sentry/utils/useLocation';
import usePageFilters from 'sentry/utils/usePageFilters';
import WebVitalsLandingPage from 'sentry/views/performance/browser/webVitals/webVitalsLandingPage';
jest.mock('sentry/utils/useLocation');
jest.mock('sentry/utils/usePageFilters');
describe('WebVitalsLandingPage', 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: {},
});
});
afterEach(function () {
jest.resetAllMocks();
});
it('renders', async () => {
render(, {organization});
await waitForElementToBeRemoved(() => screen.queryAllByTestId('loading-indicator'));
// Project performance score ring query
expect(eventsMock).toHaveBeenNthCalledWith(
1,
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 >>"',
}),
})
);
// Table query
expect(eventsMock).toHaveBeenNthCalledWith(
2,
expect.anything(),
expect.objectContaining({
query: expect.objectContaining({
dataset: 'metrics',
field: [
'transaction',
'p75(measurements.lcp)',
'p75(measurements.fcp)',
'p75(measurements.cls)',
'p75(measurements.ttfb)',
'p75(measurements.fid)',
'p75(measurements.inp)',
'opportunity_score(measurements.score.total)',
'avg(measurements.score.total)',
'count()',
'count_scores(measurements.score.lcp)',
'count_scores(measurements.score.fcp)',
'count_scores(measurements.score.cls)',
'count_scores(measurements.score.fid)',
'count_scores(measurements.score.inp)',
'count_scores(measurements.score.ttfb)',
],
query:
'transaction.op:[pageload,""] span.op:[ui.interaction.click,ui.interaction.hover,ui.interaction.drag,ui.interaction.press,""] !transaction:"<< unparameterized >>" avg(measurements.score.total):>=0',
}),
})
);
// Raw web vital metric tile queries
expect(eventsMock).toHaveBeenNthCalledWith(
3,
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 >>"',
}),
})
);
});
it('renders FID deprecation alert', async () => {
jest.mocked(useLocation).mockReturnValue({
pathname: '',
search: '',
query: {useStoredScores: 'true'},
hash: '',
state: undefined,
action: 'PUSH',
key: '',
});
render(, {organization});
await screen.findByText(/\(Interaction to Next Paint\) will replace/);
await screen.findByText(
/\(First Input Delay\) in our performance score calculation./
);
});
});