1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297 |
- import type {InitializeDataSettings} from 'sentry-test/performance/initializePerformanceData';
- import {initializeData as _initializeData} from 'sentry-test/performance/initializePerformanceData';
- import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
- import {MetricsCardinalityProvider} from 'sentry/utils/performance/contexts/metricsCardinality';
- import {MEPSettingProvider} from 'sentry/utils/performance/contexts/metricsEnhancedSetting';
- import {PageAlert, PageAlertProvider} from 'sentry/utils/performance/contexts/pageAlert';
- import {PerformanceDisplayProvider} from 'sentry/utils/performance/contexts/performanceDisplayContext';
- import {OrganizationContext} from 'sentry/views/organizationContext';
- import WidgetContainer from 'sentry/views/performance/landing/widgets/components/widgetContainer';
- import {PerformanceWidgetSetting} from 'sentry/views/performance/landing/widgets/widgetDefinitions';
- import {ProjectPerformanceType} from 'sentry/views/performance/utils';
- import {QUERY_LIMIT_PARAM} from '../utils';
- const initializeData = (query = {}, rest: InitializeDataSettings = {}) => {
- const data = _initializeData({
- query: {statsPeriod: '7d', environment: ['prod'], project: [-42], ...query},
- ...rest,
- });
- data.eventView.additionalConditions.addFilterValues('transaction.op', ['pageload']);
- return data;
- };
- function WrappedComponent({data, withStaticFilters = false, ...rest}) {
- return (
- <OrganizationContext.Provider value={data.organization}>
- <MetricsCardinalityProvider
- location={data.router.location}
- organization={data.organization}
- >
- <MEPSettingProvider forceTransactions>
- <PerformanceDisplayProvider
- value={{performanceType: ProjectPerformanceType.ANY}}
- >
- <WidgetContainer
- chartHeight={100}
- allowedCharts={[
- PerformanceWidgetSetting.TPM_AREA,
- PerformanceWidgetSetting.FAILURE_RATE_AREA,
- PerformanceWidgetSetting.USER_MISERY_AREA,
- PerformanceWidgetSetting.DURATION_HISTOGRAM,
- ]}
- rowChartSettings={[]}
- withStaticFilters={withStaticFilters}
- forceDefaultChartSetting
- {...data}
- {...rest}
- />
- </PerformanceDisplayProvider>
- </MEPSettingProvider>
- </MetricsCardinalityProvider>
- </OrganizationContext.Provider>
- );
- }
- const issuesPredicate = (url, options) =>
- url.includes('events') && options.query?.query.includes('error');
- describe('Performance > Widgets > WidgetContainer', function () {
- let wrapper;
- let eventStatsMock;
- let eventsTrendsStats;
- let eventsMock;
- let issuesListMock;
- beforeEach(function () {
- eventStatsMock = MockApiClient.addMockResponse({
- method: 'GET',
- url: `/organizations/org-slug/events-stats/`,
- body: [],
- });
- eventsMock = MockApiClient.addMockResponse({
- method: 'GET',
- url: `/organizations/org-slug/events/`,
- body: {
- data: [{}],
- meta: {},
- },
- match: [(...args) => !issuesPredicate(...args)],
- });
- issuesListMock = MockApiClient.addMockResponse({
- method: 'GET',
- url: `/organizations/org-slug/events/`,
- body: {
- data: [
- {
- 'issue.id': 123,
- transaction: '/issue/:id/',
- title: 'Error: Something is broken.',
- 'project.id': 1,
- count: 3100,
- issue: 'JAVASCRIPT-ABCD',
- },
- ],
- },
- match: [(...args) => issuesPredicate(...args)],
- });
- eventsTrendsStats = MockApiClient.addMockResponse({
- method: 'GET',
- url: '/organizations/org-slug/events-trends-stats/',
- body: [],
- });
- MockApiClient.addMockResponse({
- method: 'GET',
- url: `/organizations/org-slug/metrics-compatibility/`,
- body: [],
- });
- MockApiClient.addMockResponse({
- method: 'GET',
- url: `/organizations/org-slug/metrics-compatibility-sums/`,
- body: [],
- });
- });
- afterEach(function () {
- if (wrapper) {
- wrapper.unmount();
- wrapper = undefined;
- }
- });
- it('Check requests when changing widget props', async function () {
- const data = initializeData();
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.TPM_AREA}
- />
- );
- await waitFor(() => {
- expect(eventStatsMock).toHaveBeenCalledTimes(1);
- });
- // Change eventView reference
- data.eventView = data.eventView.clone();
- wrapper.rerender(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.TPM_AREA}
- />
- );
- await waitFor(() => {
- expect(eventStatsMock).toHaveBeenCalledTimes(1);
- });
- // Change eventView statsperiod
- const modifiedData = initializeData({
- statsPeriod: '14d',
- });
- wrapper.rerender(
- <WrappedComponent
- data={modifiedData}
- defaultChartSetting={PerformanceWidgetSetting.TPM_AREA}
- />
- );
- await waitFor(() => {
- expect(eventStatsMock).toHaveBeenCalledTimes(2);
- });
- expect(eventStatsMock).toHaveBeenNthCalledWith(
- 2,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- interval: '1h',
- partial: '1',
- query: 'transaction.op:pageload',
- statsPeriod: '28d',
- yAxis: 'tpm()',
- }),
- })
- );
- });
- it('Check requests when changing widget props for GenericDiscoverQuery based widget', async function () {
- const data = initializeData();
- wrapper = render(
- <MEPSettingProvider forceTransactions>
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.MOST_IMPROVED}
- />
- </MEPSettingProvider>
- );
- await waitFor(() => {
- expect(eventsTrendsStats).toHaveBeenCalledTimes(1);
- });
- // Change eventView reference
- data.eventView = data.eventView.clone();
- wrapper.rerender(
- <MEPSettingProvider forceTransactions>
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.MOST_IMPROVED}
- />
- </MEPSettingProvider>
- );
- await waitFor(() => {
- expect(eventsTrendsStats).toHaveBeenCalledTimes(1);
- });
- // Change eventView statsperiod
- const modifiedData = initializeData({
- statsPeriod: '14d',
- });
- wrapper.rerender(
- <MEPSettingProvider forceTransactions>
- <WrappedComponent
- data={modifiedData}
- defaultChartSetting={PerformanceWidgetSetting.MOST_IMPROVED}
- />
- </MEPSettingProvider>
- );
- await waitFor(() => {
- expect(eventsTrendsStats).toHaveBeenCalledTimes(2);
- });
- expect(eventsTrendsStats).toHaveBeenNthCalledWith(
- 2,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- cursor: '0:0:1',
- environment: ['prod'],
- field: ['transaction', 'project'],
- interval: undefined,
- middle: undefined,
- noPagination: true,
- per_page: QUERY_LIMIT_PARAM,
- project: ['-42'],
- query:
- 'transaction.op:pageload tpm():>0.01 count_percentage():>0.25 count_percentage():<4 trend_percentage():>0% confidence():>6',
- sort: 'trend_percentage()',
- statsPeriod: '14d',
- trendFunction: 'p95(transaction.duration)',
- trendType: 'improved',
- }),
- })
- );
- });
- it('should call PageError Provider when errors are present', async function () {
- const data = initializeData();
- eventStatsMock = MockApiClient.addMockResponse({
- method: 'GET',
- url: `/organizations/org-slug/events-stats/`,
- statusCode: 400,
- body: {
- detail: 'Request did not work :(',
- },
- });
- wrapper = render(
- <PageAlertProvider>
- <PageAlert />
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.TPM_AREA}
- />
- </PageAlertProvider>
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Transactions Per Minute'
- );
- expect(eventStatsMock).toHaveBeenCalledTimes(1);
- expect(await screen.findByTestId('page-error-alert')).toHaveTextContent(
- 'Request did not work :('
- );
- });
- it('TPM Widget', async function () {
- const data = initializeData();
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.TPM_AREA}
- />
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Transactions Per Minute'
- );
- expect(eventStatsMock).toHaveBeenCalledTimes(1);
- expect(eventStatsMock).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- interval: '1h',
- partial: '1',
- query: 'transaction.op:pageload',
- statsPeriod: '14d',
- yAxis: 'tpm()',
- }),
- })
- );
- });
- it('Failure Rate Widget', async function () {
- const data = initializeData();
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.FAILURE_RATE_AREA}
- />
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Failure Rate'
- );
- expect(eventStatsMock).toHaveBeenCalledTimes(1);
- expect(eventStatsMock).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- interval: '1h',
- partial: '1',
- query: 'transaction.op:pageload',
- statsPeriod: '14d',
- yAxis: 'failure_rate()',
- }),
- })
- );
- });
- it('Widget with MEP enabled and metric meta set to true', async function () {
- const data = initializeData(
- {},
- {
- features: ['performance-use-metrics'],
- }
- );
- eventStatsMock = MockApiClient.addMockResponse({
- method: 'GET',
- url: `/organizations/org-slug/events-stats/`,
- body: {
- data: [],
- isMetricsData: true,
- },
- });
- eventsMock = MockApiClient.addMockResponse({
- method: 'GET',
- url: `/organizations/org-slug/events/`,
- body: {
- data: [{}],
- meta: {isMetricsData: true},
- },
- });
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.FAILURE_RATE_AREA}
- />
- );
- expect(eventStatsMock).toHaveBeenCalledTimes(1);
- expect(eventStatsMock).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({dataset: 'metrics'}),
- })
- );
- expect(eventsMock).toHaveBeenCalledTimes(1);
- expect(eventsMock).toHaveBeenCalledWith(
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({dataset: 'metrics'}),
- })
- );
- expect(await screen.findByTestId('has-metrics-data-tag')).toHaveTextContent(
- 'processed'
- );
- });
- it('Widget with MEP enabled and metric meta set to undefined', async function () {
- const data = initializeData(
- {},
- {
- features: ['performance-use-metrics'],
- }
- );
- eventStatsMock = MockApiClient.addMockResponse({
- method: 'GET',
- url: `/organizations/org-slug/events-stats/`,
- body: {
- data: [],
- isMetricsData: undefined,
- },
- });
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.FAILURE_RATE_AREA}
- />
- );
- expect(await screen.findByTestId('no-metrics-data-tag')).toBeInTheDocument();
- expect(eventStatsMock).toHaveBeenCalledTimes(1);
- expect(eventStatsMock).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({dataset: 'metrics'}),
- })
- );
- });
- it('Widget with MEP enabled and metric meta set to false', async function () {
- const data = initializeData(
- {},
- {
- features: ['performance-use-metrics'],
- }
- );
- eventStatsMock = MockApiClient.addMockResponse({
- method: 'GET',
- url: `/organizations/org-slug/events-stats/`,
- body: {
- data: [],
- isMetricsData: false,
- },
- });
- eventsMock = MockApiClient.addMockResponse({
- method: 'GET',
- url: `/organizations/org-slug/events/`,
- body: {
- data: [{}],
- meta: {isMetricsData: false},
- },
- });
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.FAILURE_RATE_AREA}
- />
- );
- expect(eventStatsMock).toHaveBeenCalledTimes(1);
- expect(eventStatsMock).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({dataset: 'metrics'}),
- })
- );
- expect(eventsMock).toHaveBeenCalledTimes(1);
- expect(eventsMock).toHaveBeenCalledWith(
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({dataset: 'metrics'}),
- })
- );
- expect(await screen.findByTestId('has-metrics-data-tag')).toHaveTextContent(
- 'indexed'
- );
- });
- it('User misery Widget', async function () {
- const data = initializeData();
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.USER_MISERY_AREA}
- />
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'User Misery'
- );
- expect(eventStatsMock).toHaveBeenCalledTimes(1);
- expect(eventStatsMock).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- interval: '1h',
- partial: '1',
- query: 'transaction.op:pageload',
- statsPeriod: '14d',
- yAxis: 'user_misery()',
- }),
- })
- );
- });
- it('Worst LCP widget', async function () {
- const data = initializeData();
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.WORST_LCP_VITALS}
- />
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Worst LCP Web Vitals'
- );
- expect(await screen.findByTestId('view-all-button')).toHaveTextContent('View All');
- expect(eventsMock).toHaveBeenCalledTimes(1);
- expect(eventsMock).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- environment: ['prod'],
- field: [
- 'transaction',
- 'title',
- 'project.id',
- 'count_web_vitals(measurements.lcp, poor)',
- 'count_web_vitals(measurements.lcp, meh)',
- 'count_web_vitals(measurements.lcp, good)',
- ],
- per_page: 4,
- project: ['-42'],
- query: 'transaction.op:pageload',
- sort: '-count_web_vitals(measurements.lcp, poor)',
- statsPeriod: '7d',
- }),
- })
- );
- });
- it('Worst LCP widget - MEP', async function () {
- const data = initializeData(
- {},
- {
- features: ['performance-use-metrics'],
- }
- );
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.WORST_LCP_VITALS}
- />
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Worst LCP Web Vitals'
- );
- expect(await screen.findByTestId('view-all-button')).toHaveTextContent('View All');
- expect(eventsMock).toHaveBeenCalledTimes(1);
- expect(eventsMock).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- environment: ['prod'],
- field: [
- 'transaction',
- 'title',
- 'project.id',
- 'count_web_vitals(measurements.lcp, poor)',
- 'count_web_vitals(measurements.lcp, meh)',
- 'count_web_vitals(measurements.lcp, good)',
- ],
- per_page: 4,
- project: ['-42'],
- query: 'transaction.op:pageload !transaction:"<< unparameterized >>"',
- sort: '-count_web_vitals(measurements.lcp, poor)',
- statsPeriod: '7d',
- }),
- })
- );
- });
- it('Worst FCP widget', async function () {
- const data = initializeData();
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.WORST_FCP_VITALS}
- />
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Worst FCP Web Vitals'
- );
- expect(await screen.findByTestId('view-all-button')).toHaveTextContent('View All');
- expect(eventsMock).toHaveBeenCalledTimes(1);
- expect(eventsMock).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- environment: ['prod'],
- field: [
- 'transaction',
- 'title',
- 'project.id',
- 'count_web_vitals(measurements.fcp, poor)',
- 'count_web_vitals(measurements.fcp, meh)',
- 'count_web_vitals(measurements.fcp, good)',
- ],
- per_page: 4,
- project: ['-42'],
- query: 'transaction.op:pageload',
- sort: '-count_web_vitals(measurements.fcp, poor)',
- statsPeriod: '7d',
- }),
- })
- );
- });
- it('Worst FID widget', async function () {
- const data = initializeData();
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.WORST_FID_VITALS}
- />
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Worst FID Web Vitals'
- );
- expect(await screen.findByTestId('view-all-button')).toHaveTextContent('View All');
- expect(eventsMock).toHaveBeenCalledTimes(1);
- expect(eventsMock).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- environment: ['prod'],
- field: [
- 'transaction',
- 'title',
- 'project.id',
- 'count_web_vitals(measurements.fid, poor)',
- 'count_web_vitals(measurements.fid, meh)',
- 'count_web_vitals(measurements.fid, good)',
- ],
- per_page: 4,
- project: ['-42'],
- query: 'transaction.op:pageload',
- sort: '-count_web_vitals(measurements.fid, poor)',
- statsPeriod: '7d',
- }),
- })
- );
- });
- it('LCP Histogram Widget', async function () {
- const data = initializeData();
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.LCP_HISTOGRAM}
- />
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'LCP Distribution'
- );
- // TODO(k-fish): Add histogram mock
- });
- it('FCP Histogram Widget', async function () {
- const data = initializeData();
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.FCP_HISTOGRAM}
- />
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'FCP Distribution'
- );
- // TODO(k-fish): Add histogram mock
- });
- it('Most errors widget', async function () {
- const data = initializeData();
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.MOST_RELATED_ERRORS}
- />
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Most Related Errors'
- );
- expect(eventsMock).toHaveBeenCalledTimes(1);
- expect(eventsMock).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- environment: ['prod'],
- field: ['transaction', 'project.id', 'failure_count()'],
- per_page: QUERY_LIMIT_PARAM,
- project: ['-42'],
- query: 'transaction.op:pageload failure_count():>0',
- sort: '-failure_count()',
- statsPeriod: '7d',
- }),
- })
- );
- });
- it('Most related issues widget', async function () {
- const data = initializeData();
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.MOST_RELATED_ISSUES}
- />
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Most Related Issues'
- );
- expect(issuesListMock).toHaveBeenCalledTimes(1);
- expect(issuesListMock).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- environment: ['prod'],
- field: ['issue', 'transaction', 'title', 'project.id', 'count()'],
- per_page: QUERY_LIMIT_PARAM,
- project: ['-42'],
- query: 'event.type:error !tags[transaction]:"" count():>0',
- sort: '-count()',
- statsPeriod: '7d',
- }),
- })
- );
- });
- it('Switching from issues to errors widget', async function () {
- const data = initializeData();
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.MOST_RELATED_ISSUES}
- />
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Most Related Issues'
- );
- expect(issuesListMock).toHaveBeenCalledTimes(1);
- wrapper.rerender(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.MOST_RELATED_ERRORS}
- />
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Most Related Errors'
- );
- expect(eventsMock).toHaveBeenCalledTimes(1);
- expect(eventStatsMock).toHaveBeenCalledTimes(1);
- });
- it('Most improved trends widget', async function () {
- const data = initializeData();
- wrapper = render(
- <MEPSettingProvider forceTransactions>
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.MOST_IMPROVED}
- />
- </MEPSettingProvider>
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Most Improved'
- );
- expect(eventsTrendsStats).toHaveBeenCalledTimes(1);
- expect(eventsTrendsStats).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- environment: ['prod'],
- field: ['transaction', 'project'],
- interval: undefined,
- middle: undefined,
- per_page: QUERY_LIMIT_PARAM,
- project: ['-42'],
- query:
- 'transaction.op:pageload tpm():>0.01 count_percentage():>0.25 count_percentage():<4 trend_percentage():>0% confidence():>6',
- sort: 'trend_percentage()',
- statsPeriod: '7d',
- trendFunction: 'p95(transaction.duration)',
- trendType: 'improved',
- }),
- })
- );
- });
- it('Most time spent in db queries widget', async function () {
- const data = initializeData();
- wrapper = render(
- <MEPSettingProvider forceTransactions>
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.MOST_TIME_SPENT_DB_QUERIES}
- />
- </MEPSettingProvider>
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Most Time-Consuming Queries'
- );
- expect(await screen.findByRole('button', {name: 'View All'})).toHaveAttribute(
- 'href',
- '/insights/database/'
- );
- expect(eventsMock).toHaveBeenCalledTimes(1);
- expect(eventsMock).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- dataset: 'spansMetrics',
- environment: ['prod'],
- field: [
- 'span.op',
- 'span.group',
- 'project.id',
- 'span.description',
- 'sum(span.self_time)',
- 'avg(span.self_time)',
- 'time_spent_percentage()',
- ],
- per_page: QUERY_LIMIT_PARAM,
- project: ['-42'],
- query: 'has:span.description span.module:db transaction.op:pageload',
- sort: '-time_spent_percentage()',
- statsPeriod: '7d',
- }),
- })
- );
- });
- it('Most time consuming domains widget', async function () {
- const data = initializeData();
- wrapper = render(
- <MEPSettingProvider forceTransactions>
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.MOST_TIME_CONSUMING_DOMAINS}
- />
- </MEPSettingProvider>
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Most Time-Consuming Domains'
- );
- expect(await screen.findByRole('button', {name: 'View All'})).toHaveAttribute(
- 'href',
- '/insights/http/'
- );
- expect(eventsMock).toHaveBeenCalledTimes(1);
- expect(eventsMock).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- dataset: 'spansMetrics',
- environment: ['prod'],
- field: [
- 'project.id',
- 'span.domain',
- 'sum(span.self_time)',
- 'avg(span.self_time)',
- 'time_spent_percentage()',
- ],
- per_page: QUERY_LIMIT_PARAM,
- project: ['-42'],
- query: 'span.module:http',
- sort: '-time_spent_percentage()',
- statsPeriod: '7d',
- }),
- })
- );
- });
- it('Most time consuming resources widget', async function () {
- const data = initializeData();
- wrapper = render(
- <MEPSettingProvider forceTransactions>
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.MOST_TIME_CONSUMING_RESOURCES}
- />
- </MEPSettingProvider>
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Most Time-Consuming Assets'
- );
- expect(await screen.findByRole('button', {name: 'View All'})).toHaveAttribute(
- 'href',
- '/insights/browser/assets/'
- );
- expect(eventsMock).toHaveBeenCalledTimes(1);
- expect(eventsMock).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- dataset: 'spansMetrics',
- environment: ['prod'],
- field: [
- 'span.description',
- 'span.op',
- 'project.id',
- 'span.group',
- 'sum(span.self_time)',
- 'avg(span.self_time)',
- 'time_spent_percentage()',
- ],
- per_page: QUERY_LIMIT_PARAM,
- project: ['-42'],
- query:
- '!span.description:browser-extension://* resource.render_blocking_status:blocking ( span.op:resource.script OR file_extension:css OR file_extension:[woff,woff2,ttf,otf,eot] OR file_extension:[jpg,jpeg,png,gif,svg,webp,apng,avif] OR span.op:resource.img ) transaction.op:pageload',
- sort: '-time_spent_percentage()',
- statsPeriod: '7d',
- }),
- })
- );
- });
- it('Highest cache miss rate transactions widget', async function () {
- const data = initializeData();
- wrapper = render(
- <MEPSettingProvider forceTransactions>
- <WrappedComponent
- data={data}
- defaultChartSetting={
- PerformanceWidgetSetting.HIGHEST_CACHE_MISS_RATE_TRANSACTIONS
- }
- />
- </MEPSettingProvider>
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Highest Cache Miss Rates'
- );
- expect(await screen.findByRole('button', {name: 'View All'})).toHaveAttribute(
- 'href',
- '/insights/caches/'
- );
- expect(eventsMock).toHaveBeenCalledTimes(1);
- expect(eventsMock).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- cursor: '0:0:1',
- dataset: 'spansMetrics',
- environment: ['prod'],
- field: ['transaction', 'project.id', 'cache_miss_rate()'],
- noPagination: true,
- per_page: QUERY_LIMIT_PARAM,
- project: ['-42'],
- query: 'span.op:[cache.get_item,cache.get]',
- statsPeriod: '7d',
- referrer:
- 'api.performance.generic-widget-chart.highest-cache--miss-rate-transactions',
- sort: '-cache_miss_rate()',
- }),
- })
- );
- });
- it('Best Page Opportunities widget', async function () {
- const data = initializeData();
- wrapper = render(
- <MEPSettingProvider forceTransactions>
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.HIGHEST_OPPORTUNITY_PAGES}
- />
- </MEPSettingProvider>
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Best Page Opportunities'
- );
- expect(eventsMock).toHaveBeenCalledTimes(2);
- 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.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.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',
- }),
- })
- );
- });
- it('Most regressed trends widget', async function () {
- const data = initializeData();
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.MOST_REGRESSED}
- />
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Most Regressed'
- );
- expect(eventsTrendsStats).toHaveBeenCalledTimes(1);
- expect(eventsTrendsStats).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- environment: ['prod'],
- field: ['transaction', 'project'],
- interval: undefined,
- middle: undefined,
- per_page: QUERY_LIMIT_PARAM,
- project: ['-42'],
- query:
- 'transaction.op:pageload tpm():>0.01 count_percentage():>0.25 count_percentage():<4 trend_percentage():>0% confidence():>6',
- sort: '-trend_percentage()',
- statsPeriod: '7d',
- trendFunction: 'p95(transaction.duration)',
- trendType: 'regression',
- }),
- })
- );
- });
- it('Most slow frames widget', async function () {
- const data = initializeData();
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.MOST_SLOW_FRAMES}
- />
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Most Slow Frames'
- );
- expect(eventsMock).toHaveBeenCalledTimes(1);
- expect(eventsMock).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- cursor: '0:0:1',
- environment: ['prod'],
- field: ['transaction', 'project.id', 'epm()', 'avg(measurements.frames_slow)'],
- noPagination: true,
- per_page: QUERY_LIMIT_PARAM,
- project: ['-42'],
- query: 'transaction.op:pageload epm():>0.01 avg(measurements.frames_slow):>0',
- sort: '-avg(measurements.frames_slow)',
- statsPeriod: '7d',
- }),
- })
- );
- expect(await screen.findByTestId('empty-state')).toBeInTheDocument();
- });
- it('Most slow frames widget - MEP', async function () {
- const data = initializeData(
- {},
- {
- features: ['performance-use-metrics'],
- }
- );
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.MOST_SLOW_FRAMES}
- />
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Most Slow Frames'
- );
- expect(eventsMock).toHaveBeenCalledTimes(1);
- expect(eventsMock).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- cursor: '0:0:1',
- environment: ['prod'],
- field: ['transaction', 'project.id', 'epm()', 'avg(measurements.frames_slow)'],
- noPagination: true,
- per_page: QUERY_LIMIT_PARAM,
- project: ['-42'],
- query: 'transaction.op:pageload epm():>0.01 avg(measurements.frames_slow):>0',
- sort: '-avg(measurements.frames_slow)',
- statsPeriod: '7d',
- }),
- })
- );
- expect(await screen.findByTestId('empty-state')).toBeInTheDocument();
- });
- it('Most frozen frames widget', async function () {
- const data = initializeData();
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.MOST_FROZEN_FRAMES}
- />
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Most Frozen Frames'
- );
- expect(eventsMock).toHaveBeenCalledTimes(1);
- expect(eventsMock).toHaveBeenNthCalledWith(
- 1,
- expect.anything(),
- expect.objectContaining({
- query: expect.objectContaining({
- cursor: '0:0:1',
- environment: ['prod'],
- field: [
- 'transaction',
- 'project.id',
- 'epm()',
- 'avg(measurements.frames_frozen)',
- ],
- noPagination: true,
- per_page: QUERY_LIMIT_PARAM,
- project: ['-42'],
- query: 'transaction.op:pageload epm():>0.01 avg(measurements.frames_frozen):>0',
- sort: '-avg(measurements.frames_frozen)',
- statsPeriod: '7d',
- }),
- })
- );
- expect(await screen.findByTestId('empty-state')).toBeInTheDocument();
- });
- it('Able to change widget type from menu', async function () {
- const data = initializeData();
- const setRowChartSettings = jest.fn(() => {});
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.FAILURE_RATE_AREA}
- setRowChartSettings={setRowChartSettings}
- />
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Failure Rate'
- );
- expect(eventStatsMock).toHaveBeenCalledTimes(1);
- expect(setRowChartSettings).toHaveBeenCalledTimes(0);
- await userEvent.click(await screen.findByLabelText('More'));
- await userEvent.click(await screen.findByText('User Misery'));
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'User Misery'
- );
- expect(eventStatsMock).toHaveBeenCalledTimes(2);
- expect(setRowChartSettings).toHaveBeenCalledTimes(1);
- });
- it('Chart settings passed from the row are disabled in the menu', async function () {
- const data = initializeData();
- const setRowChartSettings = jest.fn(() => {});
- wrapper = render(
- <WrappedComponent
- data={data}
- defaultChartSetting={PerformanceWidgetSetting.FAILURE_RATE_AREA}
- setRowChartSettings={setRowChartSettings}
- rowChartSettings={[
- PerformanceWidgetSetting.FAILURE_RATE_AREA,
- PerformanceWidgetSetting.USER_MISERY_AREA,
- ]}
- />
- );
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Failure Rate'
- );
- // Open context menu
- await userEvent.click(await screen.findByLabelText('More'));
- // Check that the "User Misery" option is disabled by clicking on it,
- // expecting that the selected option doesn't change
- const userMiseryOption = await screen.findByRole('option', {name: 'User Misery'});
- await userEvent.click(userMiseryOption);
- expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent(
- 'Failure Rate'
- );
- });
- });
|