import {Fragment} from 'react'; import {initializeData as _initializeData} from 'sentry-test/performance/initializePerformanceData'; import {render, screen, waitFor} from 'sentry-test/reactTestingLibrary'; import {GenericQueryBatcher} from 'sentry/utils/performance/contexts/genericQueryBatcher'; import {MEPSettingProvider} from 'sentry/utils/performance/contexts/metricsEnhancedSetting'; 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'; const initializeData = () => { const data = _initializeData({ query: {statsPeriod: '7d', environment: ['prod'], project: [-42]}, }); data.eventView.additionalConditions.addFilterValues('transaction.op', ['pageload']); return data; }; const BASIC_QUERY_PARAMS = { interval: '1h', partial: '1', query: 'transaction.op:pageload', statsPeriod: '14d', }; function WrappedComponent({data, ...rest}: any) { return ( ); } describe('Performance > Widgets > Query Batching', function () { let eventsMock: jest.Mock; let eventStatsMock: jest.Mock; beforeEach(function () { eventsMock = MockApiClient.addMockResponse({ method: 'GET', url: '/organizations/org-slug/events/', body: { data: [ { 'tpm()': 53.12, 'user_misery()': 0.023, 'failure_rate()': 0.012, }, ], meta: { isMetricsData: false, }, }, }); eventStatsMock = MockApiClient.addMockResponse({ method: 'GET', url: `/organizations/org-slug/events-stats/`, body: { 'tpm()': { data: [ [ 1636822800, [ { count: 30.0, }, ], ], [ 1636995600, [ { count: 60.1, }, ], ], ], order: 1, start: 1636822800, end: 1636995600, }, 'user_misery()': { data: [ [ 1636822800, [ { count: 0.02, }, ], ], [ 1636995600, [ { count: 0.03, }, ], ], ], order: 1, start: 1636822800, end: 1636995600, }, 'failure_rate()': { data: [ [ 1636822800, [ { count: 0.002, }, ], ], [ 1636995600, [ { count: 0.001, }, ], ], ], order: 2, start: 1636822800, end: 1636995600, }, }, }); }); it('EventsRequest and DiscoverQuery based component fires queries without provider', async function () { const data = initializeData(); render( , { organization: data.organization, } ); expect(await screen.findByTestId('performance-widget-title')).toBeInTheDocument(); expect(eventStatsMock).toHaveBeenCalledTimes(1); expect(eventStatsMock).toHaveBeenNthCalledWith( 1, expect.anything(), expect.objectContaining({ query: expect.objectContaining({ ...BASIC_QUERY_PARAMS, yAxis: 'tpm()', }), }) ); expect(eventsMock).toHaveBeenCalledTimes(1); expect(eventsMock).toHaveBeenNthCalledWith( 1, expect.anything(), expect.objectContaining({ query: expect.objectContaining({ environment: ['prod'], statsPeriod: '7d', field: ['tpm()'], }), }) ); }); it('Multiple EventsRequest and DiscoverQuery based components fire individual queries without provider', async function () { const data = initializeData(); render( , { organization: data.organization, } ); expect(await screen.findAllByTestId('performance-widget-title')).toHaveLength(3); expect(eventStatsMock).toHaveBeenCalledTimes(3); expect(eventsMock).toHaveBeenCalledTimes(3); expect(eventStatsMock).toHaveBeenNthCalledWith( 1, expect.anything(), expect.objectContaining({ query: expect.objectContaining({ ...BASIC_QUERY_PARAMS, yAxis: 'tpm()', }), }) ); }); it('Multiple EventsRequest and DiscoverQuery based components merge queries with provider', async function () { const data = initializeData(); render( , { organization: data.organization, } ); await waitFor(() => expect(eventStatsMock).toHaveBeenCalled()); await waitFor(() => expect(eventsMock).toHaveBeenCalled()); expect(eventsMock).toHaveBeenNthCalledWith( 1, '/organizations/org-slug/events/', expect.objectContaining({ query: expect.objectContaining({ environment: ['prod'], field: ['tpm()', 'failure_rate()', 'user_misery()'], statsPeriod: '7d', }), }) ); expect(eventsMock).toHaveBeenCalledTimes(1); expect(eventStatsMock).toHaveBeenNthCalledWith( 1, expect.anything(), expect.objectContaining({ query: expect.objectContaining({ ...BASIC_QUERY_PARAMS, yAxis: ['tpm()', 'failure_rate()', 'user_misery()'], }), }) ); expect(eventStatsMock).toHaveBeenCalledTimes(1); expect(await screen.findAllByTestId('widget-state-has-data')).toHaveLength(3); }); it('Multiple EventsRequest and DiscoverQuery based components merge queries with provider and add MEP', async function () { const data = initializeData(); render( , { organization: data.organization, } ); expect(await screen.findAllByTestId('performance-widget-title')).toHaveLength(3); expect(eventStatsMock).toHaveBeenNthCalledWith( 1, expect.anything(), expect.objectContaining({ query: expect.objectContaining({ ...BASIC_QUERY_PARAMS, yAxis: ['tpm()', 'failure_rate()', 'user_misery()'], }), }) ); expect(eventStatsMock).toHaveBeenCalledTimes(1); expect(await screen.findAllByTestId('widget-state-has-data')).toHaveLength(3); }); it('Errors work correctly', async function () { eventStatsMock = MockApiClient.addMockResponse({ method: 'GET', url: `/organizations/org-slug/events-stats/`, statusCode: 404, body: {}, }); const data = initializeData(); render( , { organization: data.organization, } ); expect(await screen.findAllByTestId('performance-widget-title')).toHaveLength(3); expect(eventStatsMock).toHaveBeenNthCalledWith( 1, expect.anything(), expect.objectContaining({ query: expect.objectContaining({ ...BASIC_QUERY_PARAMS, yAxis: ['tpm()', 'failure_rate()', 'user_misery()'], }), }) ); expect(eventStatsMock).toHaveBeenCalledTimes(1); expect(await screen.findAllByTestId('widget-state-is-errored')).toHaveLength(3); }); });