import {LocationFixture} from 'sentry-fixture/locationFixture'; import {OrganizationFixture} from 'sentry-fixture/organization'; import {UserFixture} from 'sentry-fixture/user'; import {act, render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary'; import ConfigStore from 'sentry/stores/configStore'; import {trackAnalytics} from 'sentry/utils/analytics'; import {NewIssueExperienceButton} from 'sentry/views/issueDetails/actions/newIssueExperienceButton'; jest.mock('sentry/utils/analytics'); const mockFeedbackForm = jest.fn(); jest.mock('sentry/utils/useFeedbackForm', () => ({ useFeedbackForm: () => mockFeedbackForm(), })); describe('NewIssueExperienceButton', function () { const organization = OrganizationFixture({features: ['issue-details-streamline']}); const user = UserFixture(); user.options.prefersIssueDetailsStreamlinedUI = true; const location = LocationFixture({query: {streamline: '1'}}); beforeEach(() => { ConfigStore.init(); jest.clearAllMocks(); }); it('does not appear by default', function () { render(
); expect(screen.getByTestId('test-id')).toBeEmptyDOMElement(); }); it('appears when organization has flag', function () { render(
, {organization} ); expect(screen.getByTestId('test-id')).not.toBeEmptyDOMElement(); }); it('does not appear even if user prefers this UI', function () { act(() => ConfigStore.set('user', user)); render(
); expect(screen.getByTestId('test-id')).toBeEmptyDOMElement(); }); it('does not appear when query param is set', function () { render(
, {router: {location}} ); expect(screen.getByTestId('test-id')).toBeEmptyDOMElement(); }); it('triggers changes to the user config and location', async function () { const mockChangeUserSettings = MockApiClient.addMockResponse({ url: '/users/me/', method: 'PUT', }); render(, {organization}); const button = screen.getByRole('button', { name: 'Switch to the new issue experience', }); await userEvent.click(button); // Text should change immediately expect( screen.getByRole('button', {name: 'Switch to the old issue experience'}) ).toBeInTheDocument(); // User option should be saved await waitFor(() => { expect(mockChangeUserSettings).toHaveBeenCalledWith( '/users/me/', expect.objectContaining({ data: { options: { prefersIssueDetailsStreamlinedUI: true, }, }, }) ); }); expect(trackAnalytics).toHaveBeenCalledTimes(1); // Clicking again toggles it off await userEvent.click(button); // Old text should be back expect( screen.getByRole('button', {name: 'Switch to the new issue experience'}) ).toBeInTheDocument(); // And save the option as false await waitFor(() => { expect(mockChangeUserSettings).toHaveBeenCalledWith( '/users/me/', expect.objectContaining({ data: { options: { prefersIssueDetailsStreamlinedUI: false, }, }, }) ); }); expect(trackAnalytics).toHaveBeenCalledTimes(2); }); it('can switch back to the old UI via dropdown', async function () { const mockFormCallback = jest.fn(); mockFeedbackForm.mockReturnValue(mockFormCallback); const mockChangeUserSettings = MockApiClient.addMockResponse({ url: '/users/me/', method: 'PUT', }); render(, {organization}); await userEvent.click( screen.getByRole('button', { name: 'Switch to the new issue experience', }) ); expect( screen.getByRole('button', { name: 'Switch issue experience', }) ).toBeInTheDocument(); const dropdownButton = screen.getByRole('button', { name: 'Switch issue experience', }); await userEvent.click(dropdownButton); await userEvent.click( await screen.findByRole('menuitemradio', {name: 'Give feedback on new UI'}) ); expect(mockFeedbackForm).toHaveBeenCalled(); await userEvent.click(dropdownButton); await userEvent.click( screen.getByRole('menuitemradio', { name: 'Switch to the old issue experience', }) ); expect(mockChangeUserSettings).toHaveBeenCalledTimes(2); }); });