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 ( ); } 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( ); await waitFor(() => { expect(eventStatsMock).toHaveBeenCalledTimes(1); }); // Change eventView reference data.eventView = data.eventView.clone(); wrapper.rerender( ); await waitFor(() => { expect(eventStatsMock).toHaveBeenCalledTimes(1); }); // Change eventView statsperiod const modifiedData = initializeData({ statsPeriod: '14d', }); wrapper.rerender( ); 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( ); await waitFor(() => { expect(eventsTrendsStats).toHaveBeenCalledTimes(1); }); // Change eventView reference data.eventView = data.eventView.clone(); wrapper.rerender( ); await waitFor(() => { expect(eventsTrendsStats).toHaveBeenCalledTimes(1); }); // Change eventView statsperiod const modifiedData = initializeData({ statsPeriod: '14d', }); wrapper.rerender( ); 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( ); 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( ); 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( ); 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( ); 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( ); 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( ); 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( ); 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( ); 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( ); 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( ); 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( ); 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( ); 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( ); 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( ); 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( ); 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( ); expect(await screen.findByTestId('performance-widget-title')).toHaveTextContent( 'Most Related Issues' ); expect(issuesListMock).toHaveBeenCalledTimes(1); wrapper.rerender( ); 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( ); 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( ); 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( ); 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( ); 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( ); 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( ); 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( ); 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( ); 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( ); 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( ); 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( ); 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( ); 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' ); }); });