123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- import {initializeOrg} from 'sentry-test/initializeOrg';
- import {
- render,
- renderGlobalModal,
- screen,
- userEvent,
- waitFor,
- within,
- } from 'sentry-test/reactTestingLibrary';
- import DashboardList from 'sentry/views/dashboards/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()],
- });
- const {router, routerContext} = initializeOrg();
- beforeEach(function () {
- MockApiClient.clearMockResponses();
- 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'},
- widgetPreview: [],
- }),
- TestStubs.Dashboard(widgets, {
- id: '2',
- title: 'Dashboard 2',
- dateCreated: '2021-04-19T13:13:23.962105Z',
- createdBy: {id: '1'},
- widgetPreview: [
- {
- displayType: 'line',
- layout: {},
- },
- {
- displayType: 'table',
- layout: {},
- },
- ],
- }),
- ];
- 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();
- });
- it('renders an empty list', function () {
- render(
- <DashboardList
- organization={organization}
- dashboards={[]}
- pageLinks=""
- location={router.location}
- />
- );
- expect(screen.getByTestId('empty-state')).toBeInTheDocument();
- });
- it('renders dashboard list', function () {
- render(
- <DashboardList
- organization={organization}
- dashboards={dashboards}
- pageLinks=""
- location={router.location}
- />
- );
- expect(screen.getByText('Dashboard 1')).toBeInTheDocument();
- expect(screen.getByText('Dashboard 2')).toBeInTheDocument();
- });
- it('returns landing page url for dashboards', function () {
- render(
- <DashboardList
- organization={organization}
- dashboards={dashboards}
- pageLinks=""
- location={router.location}
- />,
- {context: routerContext}
- );
- expect(screen.getByRole('link', {name: 'Dashboard 1'})).toHaveAttribute(
- 'href',
- '/organizations/org-slug/dashboard/1/?'
- );
- expect(screen.getByRole('link', {name: 'Dashboard 2'})).toHaveAttribute(
- 'href',
- '/organizations/org-slug/dashboard/2/?'
- );
- });
- it('persists global selection headers', function () {
- render(
- <DashboardList
- organization={organization}
- dashboards={dashboards}
- pageLinks=""
- location={{query: {statsPeriod: '7d'}}}
- />,
- {context: routerContext}
- );
- expect(screen.getByRole('link', {name: 'Dashboard 1'})).toHaveAttribute(
- 'href',
- '/organizations/org-slug/dashboard/1/?statsPeriod=7d'
- );
- });
- it('can delete dashboards', async function () {
- render(
- <DashboardList
- organization={organization}
- dashboards={dashboards}
- pageLinks=""
- location={{query: {}}}
- onDashboardsChange={dashboardUpdateMock}
- />,
- {context: routerContext}
- );
- renderGlobalModal();
- await userEvent.click(screen.getAllByRole('button', {name: /dashboard actions/i})[1]);
- await userEvent.click(screen.getByTestId('dashboard-delete'));
- expect(deleteMock).not.toHaveBeenCalled();
- await userEvent.click(
- within(screen.getByRole('dialog')).getByRole('button', {name: /confirm/i})
- );
- await waitFor(() => {
- 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'},
- widgetPreview: [],
- }),
- ];
- render(
- <DashboardList
- organization={organization}
- dashboards={singleDashboard}
- pageLinks=""
- location={{query: {}}}
- onDashboardsChange={dashboardUpdateMock}
- />
- );
- await userEvent.click(screen.getByRole('button', {name: /dashboard actions/i}));
- expect(screen.getByTestId('dashboard-delete')).toHaveAttribute(
- 'aria-disabled',
- 'true'
- );
- });
- it('can duplicate dashboards', async function () {
- render(
- <DashboardList
- organization={organization}
- dashboards={dashboards}
- pageLinks=""
- location={{query: {}}}
- onDashboardsChange={dashboardUpdateMock}
- />
- );
- await userEvent.click(screen.getAllByRole('button', {name: /dashboard actions/i})[1]);
- await userEvent.click(screen.getByTestId('dashboard-duplicate'));
- await waitFor(() => {
- expect(createMock).toHaveBeenCalled();
- expect(dashboardUpdateMock).toHaveBeenCalled();
- });
- });
- it('does not throw an error if the POST fails during duplication', async function () {
- const postMock = MockApiClient.addMockResponse({
- url: '/organizations/org-slug/dashboards/',
- method: 'POST',
- statusCode: 404,
- });
- render(
- <DashboardList
- organization={organization}
- dashboards={dashboards}
- pageLinks=""
- location={{query: {}}}
- onDashboardsChange={dashboardUpdateMock}
- />
- );
- await userEvent.click(screen.getAllByRole('button', {name: /dashboard actions/i})[1]);
- await userEvent.click(screen.getByTestId('dashboard-duplicate'));
- await waitFor(() => {
- expect(postMock).toHaveBeenCalled();
- // Should not update, and not throw error
- expect(dashboardUpdateMock).not.toHaveBeenCalled();
- });
- });
- });
|