123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 |
- import {act} from 'react-dom/test-utils';
- import {browserHistory} from 'react-router';
- import {selectDropdownMenuItem} from 'sentry-test/dropdownMenu';
- import {mountWithTheme} from 'sentry-test/enzyme';
- import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
- import {triggerPress} from 'sentry-test/utils';
- import {openAddToDashboardModal} from 'sentry/actionCreators/modal';
- import {DisplayModes} from 'sentry/utils/discover/types';
- import {DashboardWidgetSource, DisplayType} from 'sentry/views/dashboardsV2/types';
- import QueryList from 'sentry/views/eventsV2/queryList';
- jest.mock('sentry/actionCreators/modal');
- jest.mock('sentry/components/charts/eventsRequest');
- describe('EventsV2 > QueryList', function () {
- let location,
- savedQueries,
- organization,
- deleteMock,
- duplicateMock,
- queryChangeMock,
- updateHomepageMock,
- wrapper;
- beforeAll(async function () {
- await import('sentry/components/modals/widgetBuilder/addToDashboardModal');
- });
- beforeEach(function () {
- organization = TestStubs.Organization({
- features: [
- 'discover-basic',
- 'discover-query',
- 'discover-query-builder-as-landing-page',
- ],
- });
- savedQueries = [
- TestStubs.DiscoverSavedQuery(),
- TestStubs.DiscoverSavedQuery({name: 'saved query 2', id: '2'}),
- ];
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/events-stats/',
- method: 'GET',
- statusCode: 200,
- body: {data: []},
- });
- deleteMock = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/discover/saved/2/',
- method: 'DELETE',
- statusCode: 200,
- body: {},
- });
- duplicateMock = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/discover/saved/',
- method: 'POST',
- body: {
- id: '3',
- name: 'Saved query copy',
- },
- });
- updateHomepageMock = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/discover/homepage/',
- method: 'PUT',
- statusCode: 204,
- });
- location = {
- pathname: '/organizations/org-slug/discover/queries/',
- query: {cursor: '0:1:1', statsPeriod: '14d'},
- };
- queryChangeMock = jest.fn();
- });
- afterEach(() => {
- jest.clearAllMocks();
- wrapper && wrapper.unmount();
- wrapper = null;
- });
- it('renders an empty list', function () {
- wrapper = mountWithTheme(
- <QueryList
- organization={organization}
- savedQueries={[]}
- savedQuerySearchQuery="no matches"
- pageLinks=""
- onQueryChange={queryChangeMock}
- location={location}
- />
- );
- const content = wrapper.find('QueryCard');
- // No queries
- expect(content).toHaveLength(0);
- expect(wrapper.find('EmptyStateWarning')).toHaveLength(1);
- });
- it('renders pre-built queries and saved ones', function () {
- wrapper = mountWithTheme(
- <QueryList
- organization={organization}
- savedQueries={savedQueries}
- renderPrebuilt
- pageLinks=""
- onQueryChange={queryChangeMock}
- location={location}
- />
- );
- const content = wrapper.find('QueryCard');
- // pre built + saved queries
- expect(content).toHaveLength(5);
- });
- it('can duplicate and trigger change callback', async function () {
- wrapper = mountWithTheme(
- <QueryList
- organization={organization}
- savedQueries={savedQueries}
- pageLinks=""
- onQueryChange={queryChangeMock}
- location={location}
- />
- );
- const card = wrapper.find('QueryCard').last();
- expect(card.find('QueryCardContent').text()).toEqual(savedQueries[1].name);
- await selectDropdownMenuItem({
- wrapper,
- specifiers: {prefix: 'QueryCard', last: true},
- itemKey: 'duplicate',
- });
- expect(duplicateMock).toHaveBeenCalled();
- expect(queryChangeMock).toHaveBeenCalled();
- });
- it('can delete and trigger change callback', async function () {
- wrapper = mountWithTheme(
- <QueryList
- organization={organization}
- savedQueries={savedQueries}
- pageLinks=""
- onQueryChange={queryChangeMock}
- location={location}
- />
- );
- const card = wrapper.find('QueryCard').last();
- expect(card.find('QueryCardContent').text()).toEqual(savedQueries[1].name);
- await selectDropdownMenuItem({
- wrapper,
- specifiers: {prefix: 'QueryCard', last: true},
- itemKey: 'delete',
- });
- expect(deleteMock).toHaveBeenCalled();
- expect(queryChangeMock).toHaveBeenCalled();
- });
- it('returns short url location for saved query', function () {
- wrapper = mountWithTheme(
- <QueryList
- organization={organization}
- savedQueries={savedQueries}
- pageLinks=""
- onQueryChange={queryChangeMock}
- location={location}
- />
- );
- const card = wrapper.find('QueryCard').last();
- const link = card.find('Link').last().prop('to');
- expect(link.pathname).toEqual('/organizations/org-slug/discover/results/');
- expect(link.query).toEqual({
- id: '2',
- statsPeriod: '14d',
- });
- });
- it('can redirect on last query deletion', async function () {
- wrapper = mountWithTheme(
- <QueryList
- organization={organization}
- savedQueries={savedQueries.slice(1)}
- pageLinks=""
- onQueryChange={queryChangeMock}
- location={location}
- />
- );
- const card = wrapper.find('QueryCard').last();
- expect(card.find('QueryCardContent').text()).toEqual(savedQueries[1].name);
- await selectDropdownMenuItem({
- wrapper,
- specifiers: {prefix: 'QueryCard', last: true},
- itemKey: 'delete',
- });
- expect(deleteMock).toHaveBeenCalled();
- expect(queryChangeMock).not.toHaveBeenCalled();
- expect(browserHistory.push).toHaveBeenCalledWith({
- pathname: location.pathname,
- query: {cursor: undefined, statsPeriod: '14d'},
- });
- });
- it('renders Add to Dashboard in context menu with feature flag', async function () {
- const featuredOrganization = TestStubs.Organization({
- features: ['dashboards-edit'],
- });
- wrapper = mountWithTheme(
- <QueryList
- organization={featuredOrganization}
- savedQueries={savedQueries.slice(1)}
- pageLinks=""
- onQueryChange={queryChangeMock}
- location={location}
- />
- );
- let card = wrapper.find('QueryCard').last();
- await act(async () => {
- triggerPress(card.find('DropdownTrigger'));
- await tick();
- wrapper.update();
- });
- card = wrapper.find('QueryCard').last();
- const menuItems = card.find('MenuItemWrap');
- expect(menuItems.length).toEqual(3);
- expect(menuItems.at(0).text()).toEqual('Add to Dashboard');
- expect(menuItems.at(1).text()).toEqual('Duplicate Query');
- expect(menuItems.at(2).text()).toEqual('Delete Query');
- });
- it('only renders Delete Query and Duplicate Query in context menu', async function () {
- wrapper = mountWithTheme(
- <QueryList
- organization={organization}
- savedQueries={savedQueries.slice(1)}
- pageLinks=""
- onQueryChange={queryChangeMock}
- location={location}
- />
- );
- let card = wrapper.find('QueryCard').last();
- await act(async () => {
- triggerPress(card.find('DropdownTrigger'));
- await tick();
- wrapper.update();
- });
- card = wrapper.find('QueryCard').last();
- const menuItems = card.find('MenuItemWrap');
- expect(menuItems.length).toEqual(3);
- expect(menuItems.at(0).text()).toEqual('Set as Default');
- expect(menuItems.at(1).text()).toEqual('Duplicate Query');
- expect(menuItems.at(2).text()).toEqual('Delete Query');
- });
- it('passes yAxis from the savedQuery to MiniGraph', function () {
- const featuredOrganization = TestStubs.Organization({
- features: ['dashboards-edit'],
- });
- const yAxis = ['count()', 'failure_count()'];
- const savedQueryWithMultiYAxis = {
- ...savedQueries.slice(1)[0],
- yAxis,
- };
- wrapper = mountWithTheme(
- <QueryList
- organization={featuredOrganization}
- savedQueries={[savedQueryWithMultiYAxis]}
- pageLinks=""
- onQueryChange={queryChangeMock}
- location={location}
- />
- );
- const miniGraph = wrapper.find('MiniGraph');
- expect(miniGraph.props().yAxis).toEqual(['count()', 'failure_count()']);
- });
- it('Set as Default updates the homepage query', function () {
- render(
- <QueryList
- organization={organization}
- savedQueries={savedQueries.slice(1)}
- pageLinks=""
- onQueryChange={queryChangeMock}
- location={location}
- />
- );
- userEvent.click(screen.getByTestId('menu-trigger'));
- userEvent.click(screen.getByText('Set as Default'));
- expect(updateHomepageMock).toHaveBeenCalledWith(
- '/organizations/org-slug/discover/homepage/',
- expect.objectContaining({
- data: expect.objectContaining({fields: ['test'], range: '14d'}),
- })
- );
- });
- describe('Add to Dashboard modal', () => {
- it('opens a modal with the correct params for Top 5 chart', async function () {
- const featuredOrganization = TestStubs.Organization({
- features: ['dashboards-edit'],
- });
- wrapper = mountWithTheme(
- <QueryList
- organization={featuredOrganization}
- savedQueries={[
- TestStubs.DiscoverSavedQuery({
- display: DisplayModes.TOP5,
- orderby: 'test',
- fields: ['test', 'count()'],
- yAxis: ['count()'],
- }),
- ]}
- pageLinks=""
- onQueryChange={queryChangeMock}
- location={location}
- />
- );
- let card = wrapper.find('QueryCard').last();
- await act(async () => {
- triggerPress(card.find('DropdownTrigger'));
- await tick();
- wrapper.update();
- });
- card = wrapper.find('QueryCard').last();
- const menuItems = card.find('MenuItemWrap');
- expect(menuItems.length).toEqual(3);
- expect(menuItems.at(0).text()).toEqual('Add to Dashboard');
- await act(async () => {
- triggerPress(menuItems.at(0));
- await tick();
- wrapper.update();
- });
- expect(openAddToDashboardModal).toHaveBeenCalledWith(
- expect.objectContaining({
- widget: {
- title: 'Saved query #1',
- displayType: DisplayType.AREA,
- limit: 5,
- queries: [
- {
- aggregates: ['count()'],
- columns: ['test'],
- conditions: '',
- fields: ['test', 'count()', 'count()'],
- name: '',
- orderby: 'test',
- },
- ],
- },
- widgetAsQueryParams: expect.objectContaining({
- defaultTableColumns: ['test', 'count()'],
- defaultTitle: 'Saved query #1',
- defaultWidgetQuery:
- 'name=&aggregates=count()&columns=test&fields=test%2Ccount()%2Ccount()&conditions=&orderby=test',
- displayType: DisplayType.AREA,
- source: DashboardWidgetSource.DISCOVERV2,
- }),
- })
- );
- });
- it('opens a modal with the correct params for other chart', async function () {
- const featuredOrganization = TestStubs.Organization({
- features: ['dashboards-edit'],
- });
- wrapper = mountWithTheme(
- <QueryList
- organization={featuredOrganization}
- savedQueries={[
- TestStubs.DiscoverSavedQuery({
- display: DisplayModes.DEFAULT,
- orderby: 'count()',
- fields: ['test', 'count()'],
- yAxis: ['count()'],
- }),
- ]}
- pageLinks=""
- onQueryChange={queryChangeMock}
- location={location}
- />
- );
- let card = wrapper.find('QueryCard').last();
- await act(async () => {
- triggerPress(card.find('DropdownTrigger'));
- await tick();
- wrapper.update();
- });
- card = wrapper.find('QueryCard').last();
- const menuItems = card.find('MenuItemWrap');
- expect(menuItems.length).toEqual(3);
- expect(menuItems.at(0).text()).toEqual('Add to Dashboard');
- await act(async () => {
- triggerPress(menuItems.at(0));
- await tick();
- wrapper.update();
- });
- expect(openAddToDashboardModal).toHaveBeenCalledWith(
- expect.objectContaining({
- widget: {
- title: 'Saved query #1',
- displayType: DisplayType.LINE,
- queries: [
- {
- aggregates: ['count()'],
- columns: [],
- conditions: '',
- fields: ['count()'],
- name: '',
- // Orderby gets dropped because ordering only applies to
- // Top-N and tables
- orderby: '',
- },
- ],
- },
- widgetAsQueryParams: expect.objectContaining({
- defaultTableColumns: ['test', 'count()'],
- defaultTitle: 'Saved query #1',
- defaultWidgetQuery:
- 'name=&aggregates=count()&columns=&fields=count()&conditions=&orderby=',
- displayType: DisplayType.LINE,
- source: DashboardWidgetSource.DISCOVERV2,
- }),
- })
- );
- });
- });
- });
|