123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- import {DashboardListItemFixture} from 'sentry-fixture/dashboard';
- import {LocationFixture} from 'sentry-fixture/locationFixture';
- import {OrganizationFixture} from 'sentry-fixture/organization';
- import {UserFixture} from 'sentry-fixture/user';
- import {initializeOrg} from 'sentry-test/initializeOrg';
- import {
- render,
- renderGlobalModal,
- screen,
- userEvent,
- waitFor,
- within,
- } from 'sentry-test/reactTestingLibrary';
- import DashboardTable from 'sentry/views/dashboards/manage/dashboardTable';
- import {type DashboardListItem, DisplayType} from 'sentry/views/dashboards/types';
- describe('Dashboards - DashboardTable', function () {
- let dashboards: DashboardListItem[];
- let deleteMock: jest.Mock;
- let dashboardUpdateMock: jest.Mock;
- let createMock: jest.Mock;
- const organization = OrganizationFixture({
- features: [
- 'global-views',
- 'dashboards-basic',
- 'dashboards-edit',
- 'discover-query',
- 'dashboards-table-view',
- ],
- });
- const {router} = initializeOrg();
- beforeEach(function () {
- MockApiClient.clearMockResponses();
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/projects/',
- body: [],
- });
- dashboards = [
- DashboardListItemFixture({
- id: '1',
- title: 'Dashboard 1',
- dateCreated: '2021-04-19T13:13:23.962105Z',
- createdBy: UserFixture({id: '1'}),
- permissions: {
- isEditableByEveryone: false,
- teamsWithEditAccess: [1],
- },
- }),
- DashboardListItemFixture({
- id: '2',
- title: 'Dashboard 2',
- dateCreated: '2021-04-19T13:13:23.962105Z',
- createdBy: UserFixture({id: '1'}),
- widgetPreview: [
- {
- displayType: DisplayType.LINE,
- layout: null,
- },
- {
- displayType: DisplayType.TABLE,
- layout: null,
- },
- ],
- }),
- ];
- 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', async function () {
- render(
- <DashboardTable
- onDashboardsChange={jest.fn()}
- organization={organization}
- dashboards={[]}
- location={router.location}
- />
- );
- expect(screen.getByTestId('empty-state')).toBeInTheDocument();
- expect(
- await screen.findByText('Sorry, no Dashboards match your filters.')
- ).toBeInTheDocument();
- });
- it('renders dashboard list', function () {
- render(
- <DashboardTable
- onDashboardsChange={jest.fn()}
- organization={organization}
- dashboards={dashboards}
- location={router.location}
- />
- );
- expect(screen.getByText('Dashboard 1')).toBeInTheDocument();
- expect(screen.getByText('Dashboard 2')).toBeInTheDocument();
- });
- it('returns landing page url for dashboards', function () {
- render(
- <DashboardTable
- onDashboardsChange={jest.fn()}
- organization={organization}
- dashboards={dashboards}
- location={router.location}
- />,
- {router}
- );
- 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(
- <DashboardTable
- onDashboardsChange={jest.fn()}
- organization={organization}
- dashboards={dashboards}
- location={{...LocationFixture(), query: {statsPeriod: '7d'}}}
- />,
- {router}
- );
- expect(screen.getByRole('link', {name: 'Dashboard 1'})).toHaveAttribute(
- 'href',
- '/organizations/org-slug/dashboard/1/?statsPeriod=7d'
- );
- });
- it('can delete dashboards', async function () {
- render(
- <DashboardTable
- organization={organization}
- dashboards={dashboards}
- location={{...LocationFixture(), query: {}}}
- onDashboardsChange={dashboardUpdateMock}
- />,
- {router}
- );
- renderGlobalModal();
- await userEvent.click(screen.getAllByTestId('dashboard-delete')[1]);
- 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', function () {
- const singleDashboard = [
- DashboardListItemFixture({
- id: '1',
- title: 'Dashboard 1',
- dateCreated: '2021-04-19T13:13:23.962105Z',
- createdBy: UserFixture({id: '1'}),
- widgetPreview: [],
- }),
- ];
- render(
- <DashboardTable
- organization={organization}
- dashboards={singleDashboard}
- location={LocationFixture()}
- onDashboardsChange={dashboardUpdateMock}
- />
- );
- expect(screen.getAllByTestId('dashboard-delete')[0]).toHaveAttribute(
- 'aria-disabled',
- 'true'
- );
- });
- it('can duplicate dashboards', async function () {
- render(
- <DashboardTable
- organization={organization}
- dashboards={dashboards}
- location={{...LocationFixture(), query: {}}}
- onDashboardsChange={dashboardUpdateMock}
- />
- );
- renderGlobalModal();
- await userEvent.click(screen.getAllByTestId('dashboard-duplicate')[1]);
- expect(createMock).not.toHaveBeenCalled();
- await userEvent.click(
- within(screen.getByRole('dialog')).getByRole('button', {name: /confirm/i})
- );
- 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(
- <DashboardTable
- organization={organization}
- dashboards={dashboards}
- location={{...LocationFixture(), query: {}}}
- onDashboardsChange={dashboardUpdateMock}
- />
- );
- renderGlobalModal();
- await userEvent.click(screen.getAllByTestId('dashboard-duplicate')[1]);
- expect(postMock).not.toHaveBeenCalled();
- await userEvent.click(
- within(screen.getByRole('dialog')).getByRole('button', {name: /confirm/i})
- );
- await waitFor(() => {
- expect(postMock).toHaveBeenCalled();
- // Should not update, and not throw error
- expect(dashboardUpdateMock).not.toHaveBeenCalled();
- });
- });
- it('renders access column', async function () {
- const organizationWithEditAccess = OrganizationFixture({
- features: [
- 'global-views',
- 'dashboards-basic',
- 'dashboards-edit',
- 'discover-query',
- 'dashboards-table-view',
- 'dashboards-edit-access',
- ],
- });
- render(
- <DashboardTable
- onDashboardsChange={jest.fn()}
- organization={organizationWithEditAccess}
- dashboards={dashboards}
- location={router.location}
- />
- );
- expect((await screen.findAllByTestId('grid-head-cell')).length).toBe(5);
- expect(screen.getByText('Access')).toBeInTheDocument();
- await userEvent.click((await screen.findAllByTestId('edit-access-dropdown'))[0]);
- expect(screen.getAllByPlaceholderText('Search Teams')[0]).toBeInTheDocument();
- });
- });
|