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'; const mockUseNavigate = jest.fn(); jest.mock('sentry/utils/useNavigate', () => ({ useNavigate: () => mockUseNavigate, })); jest.mock('sentry/utils/analytics'); 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(); }); 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, }, }, }) ); }); // Location should update expect(mockUseNavigate).toHaveBeenCalledWith( expect.objectContaining({query: {streamline: '1'}}) ); 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, }, }, }) ); }); // Location should update again expect(mockUseNavigate).toHaveBeenCalledWith( expect.objectContaining({query: {streamline: '0'}}) ); expect(trackAnalytics).toHaveBeenCalledTimes(2); }); });