import React from 'react'; import {initializeOrg} from 'sentry-test/initializeOrg'; import { fireEvent, render, screen, userEvent, within, } from 'sentry-test/reactTestingLibrary'; import GlobalModal from 'sentry/components/globalModal'; import GroupStore from 'sentry/stores/groupStore'; import SelectedGroupStore from 'sentry/stores/selectedGroupStore'; import {IssueListActions} from 'sentry/views/issueList/actions'; describe('IssueListActions', function () { let org, defaultProps; afterEach(() => { jest.restoreAllMocks(); }); beforeEach(() => { const organization = initializeOrg(); org = organization.org; GroupStore.reset(); SelectedGroupStore.reset(); SelectedGroupStore.add(['1', '2', '3']); defaultProps = { api: new MockApiClient(), allResultsVisible: false, query: '', queryCount: 15, organization: org, projectId: 'project-slug', selection: { projects: [1], environments: [], datetime: {start: null, end: null, period: null, utc: true}, }, groupIds: ['1', '2', '3'], onRealtimeChange: jest.fn(), onSelectStatsPeriod: jest.fn(), realtimeActive: false, statsPeriod: '24h', }; }); describe('Bulk', function () { describe('Total results greater than bulk limit', function () { it('after checking "Select all" checkbox, displays bulk select message', function () { render(); userEvent.click(screen.getByRole('checkbox')); expect(screen.getByTestId('issue-list-select-all-notice')).toSnapshot(); }); it('can bulk select', function () { render(); userEvent.click(screen.getByRole('checkbox')); userEvent.click(screen.getByTestId('issue-list-select-all-notice-link')); expect(screen.getByTestId('issue-list-select-all-notice')).toSnapshot(); }); it('bulk resolves', async function () { const apiMock = MockApiClient.addMockResponse({ url: '/organizations/org-slug/issues/', method: 'PUT', }); render( ); userEvent.click(screen.getByRole('checkbox')); userEvent.click(screen.getByTestId('issue-list-select-all-notice-link')); userEvent.click(screen.getByRole('button', {name: 'Resolve'})); await screen.findByRole('dialog'); userEvent.click(screen.getByRole('button', {name: 'Bulk resolve issues'})); expect(apiMock).toHaveBeenCalledWith( expect.anything(), expect.objectContaining({ query: { project: [1], }, data: {status: 'resolved', statusDetails: {}}, }) ); }); }); describe('Total results less than bulk limit', function () { it('after checking "Select all" checkbox, displays bulk select message', function () { render(); userEvent.click(screen.getByRole('checkbox')); expect(screen.getByTestId('issue-list-select-all-notice')).toSnapshot(); }); it('can bulk select', function () { render(); userEvent.click(screen.getByRole('checkbox')); userEvent.click(screen.getByTestId('issue-list-select-all-notice-link')); expect(screen.getByTestId('issue-list-select-all-notice')).toSnapshot(); }); it('bulk resolves', function () { const apiMock = MockApiClient.addMockResponse({ url: '/organizations/org-slug/issues/', method: 'PUT', }); render( ); userEvent.click(screen.getByRole('checkbox')); userEvent.click(screen.getByTestId('issue-list-select-all-notice-link')); userEvent.click(screen.getByRole('button', {name: 'Resolve'})); const modal = screen.getByRole('dialog'); expect(modal).toSnapshot(); userEvent.click(within(modal).getByRole('button', {name: 'Bulk resolve issues'})); expect(apiMock).toHaveBeenCalledWith( expect.anything(), expect.objectContaining({ query: { project: [1], }, data: {status: 'resolved', statusDetails: {}}, }) ); }); }); describe('Selected on page', function () { it('resolves selected items', function () { const apiMock = MockApiClient.addMockResponse({ url: '/organizations/org-slug/issues/', method: 'PUT', }); jest.spyOn(SelectedGroupStore, 'getSelectedIds').mockReturnValue(new Set(['1'])); render( ); const resolveButton = screen.getByRole('button', {name: 'Resolve'}); expect(resolveButton).toBeEnabled(); userEvent.click(resolveButton); expect(apiMock).toHaveBeenCalledWith( expect.anything(), expect.objectContaining({ query: { id: ['1'], project: [1], }, data: {status: 'resolved', statusDetails: {}}, }) ); }); it('can ignore selected items (custom)', async function () { const apiMock = MockApiClient.addMockResponse({ url: '/organizations/org-slug/issues/', method: 'PUT', }); jest.spyOn(SelectedGroupStore, 'getSelectedIds').mockReturnValue(new Set(['1'])); render( ); userEvent.click(screen.getByRole('button', {name: 'Ignore options'})); fireEvent.click(screen.getByText(/Until this affects an additional/)); await screen.findByTestId('until-affect-custom'); userEvent.click(screen.getByTestId('until-affect-custom')); const modal = screen.getByRole('dialog'); userEvent.clear(within(modal).getByLabelText('Number of users')); userEvent.type(within(modal).getByLabelText('Number of users'), '300'); userEvent.click(within(modal).getByRole('textbox')); userEvent.click(within(modal).getByText('per week')); userEvent.click(within(modal).getByRole('button', {name: 'Ignore'})); expect(apiMock).toHaveBeenCalledWith( expect.anything(), expect.objectContaining({ query: { id: ['1'], project: [1], }, data: { status: 'ignored', statusDetails: { ignoreUserCount: 300, ignoreUserWindow: 10080, }, }, }) ); }); }); }); it('can resolve but not merge issues from different projects', function () { jest .spyOn(SelectedGroupStore, 'getSelectedIds') .mockImplementation(() => new Set(['1', '2', '3'])); jest.spyOn(GroupStore, 'get').mockImplementation(id => { switch (id) { case '1': return TestStubs.Group({project: TestStubs.Project({slug: 'project-1'})}); default: return TestStubs.Group({project: TestStubs.Project({slug: 'project-2'})}); } }); render(); // Can resolve but not merge issues from multiple projects expect(screen.getByRole('button', {name: 'Resolve'})).toBeEnabled(); expect(screen.getByRole('button', {name: 'Merge Selected Issues'})).toBeDisabled(); }); describe('mark reviewed', function () { it('acknowledges group', function () { const mockOnMarkReviewed = jest.fn(); jest .spyOn(SelectedGroupStore, 'getSelectedIds') .mockImplementation(() => new Set(['1', '2', '3'])); jest.spyOn(GroupStore, 'get').mockImplementation(id => { return TestStubs.Group({ id, inbox: { date_added: '2020-11-24T13:17:42.248751Z', reason: 0, reason_details: null, }, }); }); render(); const reviewButton = screen.getByRole('button', {name: 'Mark Reviewed'}); expect(reviewButton).toBeEnabled(); userEvent.click(reviewButton); expect(mockOnMarkReviewed).toHaveBeenCalledWith(['1', '2', '3']); }); it('mark reviewed disabled for group that is already reviewed', function () { SelectedGroupStore.add(['1']); SelectedGroupStore.toggleSelectAll(); GroupStore.loadInitialData([TestStubs.Group({id: '1', inbox: null})]); render(); expect(screen.getByRole('button', {name: 'Mark Reviewed'})).toBeDisabled(); }); }); describe('sort', function () { it('calls onSortChange with new sort value', function () { const mockOnSortChange = jest.fn(); render(); userEvent.click(screen.getByRole('button', {name: 'Last Seen'})); userEvent.click(screen.getByText(/Number of events/)); expect(mockOnSortChange).toHaveBeenCalledWith('freq'); }); }); });