123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- import {DashboardListItemFixture} from 'sentry-fixture/dashboard';
- import {OrganizationFixture} from 'sentry-fixture/organization';
- import {ProjectFixture} from 'sentry-fixture/project';
- import {RouteComponentPropsFixture} from 'sentry-fixture/routeComponentPropsFixture';
- import {act, render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
- import selectEvent from 'sentry-test/selectEvent';
- import ProjectsStore from 'sentry/stores/projectsStore';
- import localStorage from 'sentry/utils/localStorage';
- import {useNavigate} from 'sentry/utils/useNavigate';
- import ManageDashboards, {LAYOUT_KEY} from 'sentry/views/dashboards/manage';
- import {getPaginationPageLink} from 'sentry/views/organizationStats/utils';
- jest.mock('sentry/utils/localStorage');
- const FEATURES = [
- 'global-views',
- 'dashboards-basic',
- 'dashboards-edit',
- 'discover-query',
- ];
- jest.mock('sentry/utils/useNavigate', () => ({
- useNavigate: jest.fn(),
- }));
- const mockUseNavigate = jest.mocked(useNavigate);
- describe('Dashboards > Detail', function () {
- const mockUnauthorizedOrg = OrganizationFixture({
- features: ['global-views', 'dashboards-basic', 'discover-query'],
- });
- const mockAuthorizedOrg = OrganizationFixture({
- features: FEATURES,
- });
- beforeEach(function () {
- act(() => ProjectsStore.loadInitialData([ProjectFixture()]));
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/projects/',
- body: [],
- });
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/dashboards/',
- body: [],
- });
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/dashboards/?sort=name&per_page=9',
- body: [],
- });
- });
- afterEach(function () {
- MockApiClient.clearMockResponses();
- });
- it('renders', async function () {
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/dashboards/',
- body: [DashboardListItemFixture({title: 'Test Dashboard'})],
- });
- render(<ManageDashboards />, {
- ...RouteComponentPropsFixture(),
- organization: mockAuthorizedOrg,
- });
- expect(await screen.findByText('Dashboards')).toBeInTheDocument();
- expect(await screen.findByText('Test Dashboard')).toBeInTheDocument();
- expect(screen.queryAllByTestId('loading-placeholder')).toHaveLength(0);
- });
- it('shows error message when receiving error', async function () {
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/dashboards/',
- statusCode: 400,
- });
- render(<ManageDashboards />, {
- ...RouteComponentPropsFixture(),
- organization: mockAuthorizedOrg,
- });
- expect(await screen.findByText('Oops! Something went wrong')).toBeInTheDocument();
- });
- it('denies access on missing feature', async function () {
- render(<ManageDashboards />, {
- ...RouteComponentPropsFixture(),
- organization: mockUnauthorizedOrg,
- });
- expect(
- await screen.findByText("You don't have access to this feature")
- ).toBeInTheDocument();
- });
- it('denies access on no projects', async function () {
- act(() => ProjectsStore.loadInitialData([]));
- render(<ManageDashboards />, {
- ...RouteComponentPropsFixture(),
- organization: mockAuthorizedOrg,
- });
- expect(
- await screen.findByText('You need at least one project to use this view')
- ).toBeInTheDocument();
- });
- it('creates new dashboard', async function () {
- const org = OrganizationFixture({features: FEATURES});
- const mockNavigate = jest.fn();
- mockUseNavigate.mockReturnValue(mockNavigate);
- render(<ManageDashboards />, {
- ...RouteComponentPropsFixture(),
- organization: org,
- });
- await userEvent.click(await screen.findByTestId('dashboard-create'));
- expect(mockNavigate).toHaveBeenCalledWith({
- pathname: '/organizations/org-slug/dashboards/new/',
- query: {},
- });
- });
- it('can sort', async function () {
- const org = OrganizationFixture({features: FEATURES});
- const mockNavigate = jest.fn();
- mockUseNavigate.mockReturnValue(mockNavigate);
- render(<ManageDashboards />, {
- ...RouteComponentPropsFixture(),
- organization: org,
- });
- await selectEvent.select(
- await screen.findByRole('button', {name: /sort by/i}),
- 'Dashboard Name (A-Z)'
- );
- expect(mockNavigate).toHaveBeenCalledWith(
- expect.objectContaining({query: {sort: 'title'}})
- );
- });
- it('can search', async function () {
- const org = OrganizationFixture({features: FEATURES});
- const mockNavigate = jest.fn();
- mockUseNavigate.mockReturnValue(mockNavigate);
- render(<ManageDashboards />, {
- ...RouteComponentPropsFixture(),
- organization: org,
- });
- await userEvent.click(await screen.findByPlaceholderText('Search Dashboards'));
- await userEvent.keyboard('dash');
- await userEvent.keyboard('[Enter]');
- expect(mockNavigate).toHaveBeenCalledWith(
- expect.objectContaining({query: {query: 'dash'}})
- );
- });
- it('uses pagination correctly', async function () {
- const mockNavigate = jest.fn();
- mockUseNavigate.mockReturnValue(mockNavigate);
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/dashboards/',
- body: [DashboardListItemFixture({title: 'Test Dashboard 1'})],
- headers: {Link: getPaginationPageLink({numRows: 15, pageSize: 9, offset: 0})},
- });
- render(<ManageDashboards />, {
- ...RouteComponentPropsFixture(),
- organization: mockAuthorizedOrg,
- });
- expect(await screen.findByText('Test Dashboard 1')).toBeInTheDocument();
- await userEvent.click(await screen.findByLabelText('Next'));
- expect(mockNavigate).toHaveBeenCalledWith(
- expect.objectContaining({
- query: {
- cursor: '0:9:0',
- },
- })
- );
- });
- it('disables pagination correctly', async function () {
- const mockNavigate = jest.fn();
- mockUseNavigate.mockReturnValue(mockNavigate);
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/dashboards/',
- body: [DashboardListItemFixture({title: 'Test Dashboard 1'})],
- headers: {Link: getPaginationPageLink({numRows: 15, pageSize: 9, offset: 0})},
- });
- render(<ManageDashboards />, {
- ...RouteComponentPropsFixture(),
- organization: mockAuthorizedOrg,
- });
- expect(await screen.findByText('Test Dashboard 1')).toBeInTheDocument();
- await userEvent.click(await screen.findByLabelText('Previous'));
- expect(mockNavigate).not.toHaveBeenCalled();
- });
- it('toggles between grid and list view', async function () {
- MockApiClient.addMockResponse({
- url: '/organizations/org-slug/dashboards/',
- body: [DashboardListItemFixture({title: 'Test Dashboard 1'})],
- headers: {Link: getPaginationPageLink({numRows: 15, pageSize: 9, offset: 0})},
- });
- render(<ManageDashboards />, {
- ...RouteComponentPropsFixture(),
- organization: {
- ...mockAuthorizedOrg,
- features: [...FEATURES, 'dashboards-table-view'],
- },
- });
- expect(await screen.findByTestId('list')).toBeInTheDocument();
- await userEvent.click(await screen.findByTestId('list'));
- expect(localStorage.setItem).toHaveBeenCalledWith(LAYOUT_KEY, '"list"');
- expect(await screen.findByTestId('grid-editable')).toBeInTheDocument();
- expect(await screen.findByTestId('grid')).toBeInTheDocument();
- await userEvent.click(await screen.findByTestId('grid'));
- expect(localStorage.setItem).toHaveBeenCalledWith(LAYOUT_KEY, '"grid"');
- expect(await screen.findByTestId('dashboard-grid')).toBeInTheDocument();
- });
- });
|