123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- import {act} from 'react-dom/test-utils';
- import {selectDropdownMenuItem} from 'sentry-test/dropdownMenu';
- import {mountWithTheme} from 'sentry-test/enzyme';
- import {mountGlobalModal} from 'sentry-test/modal';
- import {triggerPress} from 'sentry-test/utils';
- import DashboardList from 'sentry/views/dashboardsV2/manage/dashboardList';
- describe('Dashboards > DashboardList', function () {
- let dashboards, widgets, deleteMock, dashboardUpdateMock, createMock;
- const organization = TestStubs.Organization({
- features: ['global-views', 'dashboards-basic', 'dashboards-edit', 'discover-query'],
- projects: [TestStubs.Project()],
- });
- beforeEach(function () {
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/projects/',
- body: [],
- });
- widgets = [
- TestStubs.Widget(
- [{name: '', conditions: 'event.type:error', fields: ['count()']}],
- {
- title: 'Errors',
- interval: '1d',
- id: '1',
- }
- ),
- TestStubs.Widget(
- [{name: '', conditions: 'event.type:transaction', fields: ['count()']}],
- {
- title: 'Transactions',
- interval: '1d',
- id: '2',
- }
- ),
- TestStubs.Widget(
- [
- {
- name: '',
- conditions: 'event.type:transaction transaction:/api/cats',
- fields: ['p50()'],
- },
- ],
- {
- title: 'p50 of /api/cats',
- interval: '1d',
- id: '3',
- }
- ),
- ];
- dashboards = [
- TestStubs.Dashboard([], {
- id: '1',
- title: 'Dashboard 1',
- dateCreated: '2021-04-19T13:13:23.962105Z',
- createdBy: {id: '1'},
- widgetDisplay: [],
- }),
- TestStubs.Dashboard(widgets, {
- id: '2',
- title: 'Dashboard 2',
- dateCreated: '2021-04-19T13:13:23.962105Z',
- createdBy: {id: '1'},
- widgetDisplay: ['line', 'table'],
- }),
- ];
- deleteMock = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/dashboards/2/',
- method: 'DELETE',
- statusCode: 200,
- });
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/dashboards/2/',
- method: 'GET',
- statusCode: 200,
- body: {
- id: '2',
- title: 'Dashboard Demo',
- widgets: [
- {
- id: '1',
- title: 'Errors',
- displayType: 'big_number',
- interval: '5m',
- },
- {
- id: '2',
- title: 'Transactions',
- displayType: 'big_number',
- interval: '5m',
- },
- {
- id: '3',
- title: 'p50 of /api/cat',
- displayType: 'big_number',
- interval: '5m',
- },
- ],
- },
- });
- createMock = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/dashboards/',
- method: 'POST',
- statusCode: 200,
- });
- dashboardUpdateMock = jest.fn();
- });
- afterEach(function () {
- MockApiClient.clearMockResponses();
- });
- it('renders an empty list', function () {
- const wrapper = mountWithTheme(
- <DashboardList
- organization={organization}
- dashboards={[]}
- pageLinks=""
- location={{query: {}}}
- />
- );
- const content = wrapper.find('DashboardCard');
- // No dashboards
- expect(content).toHaveLength(0);
- expect(wrapper.find('EmptyStateWarning')).toHaveLength(1);
- });
- it('renders dashboard list', function () {
- const wrapper = mountWithTheme(
- <DashboardList
- organization={organization}
- dashboards={dashboards}
- pageLinks=""
- location={{query: {}}}
- />
- );
- const content = wrapper.find('DashboardCard');
- expect(content).toHaveLength(2);
- });
- it('returns landing page url for dashboards', function () {
- const wrapper = mountWithTheme(
- <DashboardList
- organization={organization}
- dashboards={dashboards}
- pageLinks=""
- location={{query: {}}}
- />
- );
- const card = wrapper.find('DashboardCard').last();
- const link = card.find('Link').last().prop('to');
- expect(link.pathname).toEqual(`/organizations/org-slug/dashboard/2/`);
- });
- it('persists global selection headers', function () {
- const wrapper = mountWithTheme(
- <DashboardList
- organization={organization}
- dashboards={dashboards}
- pageLinks=""
- location={{query: {statsPeriod: '7d'}}}
- />
- );
- const card = wrapper.find('DashboardCard').last();
- const link = card.find('Link').last().prop('to');
- expect(link.pathname).toEqual(`/organizations/org-slug/dashboard/2/`);
- expect(link.query).toEqual({statsPeriod: '7d'});
- });
- it('can delete dashboards', async function () {
- const wrapper = mountWithTheme(
- <DashboardList
- organization={organization}
- dashboards={dashboards}
- pageLinks=""
- location={{query: {}}}
- onDashboardsChange={dashboardUpdateMock}
- />
- );
- const card = wrapper.find('DashboardCard').last();
- expect(card.find('Title').text()).toEqual(dashboards[1].title);
- await selectDropdownMenuItem({
- wrapper,
- specifiers: {prefix: 'DashboardCard', last: true},
- itemKey: 'dashboard-delete',
- });
- expect(deleteMock).not.toHaveBeenCalled();
- // Confirm
- const modal = await mountGlobalModal();
- modal.find('Button').last().simulate('click');
- await tick();
- expect(deleteMock).toHaveBeenCalled();
- expect(dashboardUpdateMock).toHaveBeenCalled();
- });
- it('cannot delete last dashboard', async function () {
- const singleDashboard = [
- TestStubs.Dashboard([], {
- id: '1',
- title: 'Dashboard 1',
- dateCreated: '2021-04-19T13:13:23.962105Z',
- createdBy: {id: '1'},
- widgetDisplay: [],
- }),
- ];
- const wrapper = mountWithTheme(
- <DashboardList
- organization={organization}
- dashboards={singleDashboard}
- pageLinks=""
- location={{query: {}}}
- onDashboardsChange={dashboardUpdateMock}
- />
- );
- let card = wrapper.find('DashboardCard').last();
- expect(card.find('Title').text()).toEqual(singleDashboard[0].title);
- await act(async () => {
- triggerPress(card.find('DropdownTrigger'));
- await tick();
- wrapper.update();
- });
- card = wrapper.find('DashboardCard').last();
- const dashboardDelete = card.find(`MenuItemWrap[data-test-id="dashboard-delete"]`);
- expect(dashboardDelete.prop('aria-disabled')).toBe(true);
- });
- it('can duplicate dashboards', async function () {
- const wrapper = mountWithTheme(
- <DashboardList
- organization={organization}
- dashboards={dashboards}
- pageLinks=""
- location={{query: {}}}
- onDashboardsChange={dashboardUpdateMock}
- />
- );
- const card = wrapper.find('DashboardCard').last();
- expect(card.find('Title').text()).toEqual(dashboards[1].title);
- await selectDropdownMenuItem({
- wrapper,
- specifiers: {prefix: 'DashboardCard', last: true},
- itemKey: 'dashboard-duplicate',
- });
- expect(createMock).toHaveBeenCalled();
- expect(dashboardUpdateMock).toHaveBeenCalled();
- });
- it('does not throw an error if the POST fails during duplication', async function () {
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/dashboards/',
- method: 'POST',
- statusCode: 404,
- });
- const wrapper = mountWithTheme(
- <DashboardList
- organization={organization}
- dashboards={dashboards}
- pageLinks=""
- location={{query: {}}}
- onDashboardsChange={dashboardUpdateMock}
- />
- );
- const card = wrapper.find('DashboardCard').last();
- expect(card.find('Title').text()).toEqual(dashboards[1].title);
- await selectDropdownMenuItem({
- wrapper,
- specifiers: {prefix: 'DashboardCard', last: true},
- itemKey: 'dashboard-duplicate',
- });
- // Should not update, and not throw error
- expect(dashboardUpdateMock).not.toHaveBeenCalled();
- });
- });
|