import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary'; import {openAddToDashboardModal} from 'sentry/actionCreators/modal'; import {DisplayType, WidgetType} from 'sentry/views/dashboards/types'; import {AddToDashboardButton} from 'sentry/views/explore/components/addToDashboardButton'; import {useResultMode} from 'sentry/views/explore/hooks/useResultsMode'; import {useVisualizes} from 'sentry/views/explore/hooks/useVisualizes'; import {ChartType} from 'sentry/views/insights/common/components/chart'; jest.mock('sentry/actionCreators/modal'); jest.mock('sentry/views/explore/hooks/useVisualizes'); jest.mock('sentry/views/explore/hooks/useResultsMode'); describe('AddToDashboardButton', () => { beforeEach(() => { jest.clearAllMocks(); jest.mocked(useVisualizes).mockReturnValue([ [ { yAxes: ['avg(span.duration)'], chartType: ChartType.LINE, label: 'Custom Explore Widget', }, ], jest.fn(), ]); jest.mocked(useResultMode).mockReturnValue(['samples', jest.fn()]); }); it('renders', async () => { render(); await userEvent.hover(screen.getByLabelText('Add to Dashboard')); expect(await screen.findByText('Add to Dashboard')).toBeInTheDocument(); }); it('opens the dashboard modal with the correct query for samples mode', async () => { render(); await userEvent.click(screen.getByLabelText('Add to Dashboard')); // The table columns are encoded as the fields for the defaultWidgetQuery expect(openAddToDashboardModal).toHaveBeenCalledWith( expect.objectContaining({ // For Add + Stay on Page widget: { title: 'Custom Explore Widget', displayType: DisplayType.LINE, interval: undefined, limit: undefined, widgetType: WidgetType.SPANS, queries: [ { aggregates: ['avg(span.duration)'], columns: [], fields: ['avg(span.duration)'], conditions: '', orderby: '-timestamp', name: '', }, ], }, // For Open in Widget Builder widgetAsQueryParams: expect.objectContaining({ dataset: WidgetType.SPANS, defaultTableColumns: [ 'id', 'project', 'span.op', 'span.description', 'span.duration', 'timestamp', ], defaultTitle: 'Custom Explore Widget', defaultWidgetQuery: 'name=&aggregates=avg(span.duration)&columns=&fields=avg(span.duration)&conditions=&orderby=-timestamp', displayType: DisplayType.LINE, field: [ 'id', 'project', 'span.op', 'span.description', 'span.duration', 'timestamp', ], }), }) ); }); it('opens the dashboard modal with the correct query based on the visualize index', async () => { // Mock a second visualize object jest.mocked(useVisualizes).mockReturnValue([ [ { yAxes: ['avg(span.duration)'], chartType: ChartType.LINE, label: 'Custom Explore Widget', }, { yAxes: ['max(span.duration)'], chartType: ChartType.LINE, label: 'Custom Explore Widget', }, ], jest.fn(), ]); render(); await userEvent.click(screen.getByLabelText('Add to Dashboard')); // The group by and the yAxes are encoded as the fields for the defaultTableQuery expect(openAddToDashboardModal).toHaveBeenCalledWith( expect.objectContaining({ // For Add + Stay on Page widget: { title: 'Custom Explore Widget', displayType: DisplayType.LINE, interval: undefined, limit: undefined, widgetType: WidgetType.SPANS, queries: [ { aggregates: ['max(span.duration)'], columns: [], fields: ['max(span.duration)'], conditions: '', orderby: '-timestamp', name: '', }, ], }, // For Open in Widget Builder widgetAsQueryParams: expect.objectContaining({ dataset: WidgetType.SPANS, defaultTableColumns: [ 'id', 'project', 'span.op', 'span.description', 'span.duration', 'timestamp', ], defaultTitle: 'Custom Explore Widget', defaultWidgetQuery: 'name=&aggregates=max(span.duration)&columns=&fields=max(span.duration)&conditions=&orderby=-timestamp', displayType: DisplayType.LINE, field: [ 'id', 'project', 'span.op', 'span.description', 'span.duration', 'timestamp', ], }), }) ); }); it('uses the yAxes for the aggregate mode', async () => { jest.mocked(useResultMode).mockReturnValue(['aggregate', jest.fn()]); render(); await userEvent.click(screen.getByLabelText('Add to Dashboard')); expect(openAddToDashboardModal).toHaveBeenCalledWith( expect.objectContaining({ // For Add + Stay on Page widget: { title: 'Custom Explore Widget', displayType: DisplayType.LINE, interval: undefined, limit: undefined, widgetType: WidgetType.SPANS, queries: [ { aggregates: ['avg(span.duration)'], columns: [], fields: ['avg(span.duration)'], conditions: '', orderby: '-avg(span.duration)', name: '', }, ], }, // For Open in Widget Builder widgetAsQueryParams: expect.objectContaining({ dataset: WidgetType.SPANS, defaultTableColumns: ['avg(span.duration)'], defaultTitle: 'Custom Explore Widget', defaultWidgetQuery: 'name=&aggregates=avg(span.duration)&columns=&fields=avg(span.duration)&conditions=&orderby=-avg(span.duration)', displayType: DisplayType.LINE, field: ['avg(span.duration)'], }), }) ); }); it('takes the first 3 yAxes', async () => { jest.mocked(useResultMode).mockReturnValue(['aggregate', jest.fn()]); jest.mocked(useVisualizes).mockReturnValue([ [ { yAxes: [ 'avg(span.duration)', 'max(span.duration)', 'min(span.duration)', 'p90(span.duration)', ], chartType: ChartType.LINE, label: 'Custom Explore Widget', }, ], jest.fn(), ]); render(); await userEvent.click(screen.getByLabelText('Add to Dashboard')); expect(openAddToDashboardModal).toHaveBeenCalledWith( expect.objectContaining({ // For Add + Stay on Page widget: { title: 'Custom Explore Widget', displayType: DisplayType.LINE, interval: undefined, limit: undefined, widgetType: WidgetType.SPANS, queries: [ { aggregates: [ 'avg(span.duration)', 'max(span.duration)', 'min(span.duration)', ], columns: [], fields: ['avg(span.duration)', 'max(span.duration)', 'min(span.duration)'], conditions: '', orderby: '-avg(span.duration)', name: '', }, ], }, // For Open in Widget Builder widgetAsQueryParams: expect.objectContaining({ dataset: WidgetType.SPANS, defaultTableColumns: [ 'avg(span.duration)', 'max(span.duration)', 'min(span.duration)', ], defaultTitle: 'Custom Explore Widget', defaultWidgetQuery: 'name=&aggregates=avg(span.duration)%2Cmax(span.duration)%2Cmin(span.duration)&columns=&fields=avg(span.duration)%2Cmax(span.duration)%2Cmin(span.duration)&conditions=&orderby=-avg(span.duration)', displayType: DisplayType.LINE, field: ['avg(span.duration)', 'max(span.duration)', 'min(span.duration)'], }), }) ); }); });