import {RouterFixture} from 'sentry-fixture/routerFixture'; import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary'; import { DraggableTabBar, type Tab, } from 'sentry/views/issueList/groupSearchViewTabs/draggableTabBar'; import {IssueSortOptions} from 'sentry/views/issueList/utils'; // biome-ignore lint/suspicious/noSkippedTests: describe.skip('DraggableTabBar', () => { const mockOnTabRenamed = jest.fn(); const mockOnAddView = jest.fn(); const mockOnDelete = jest.fn(); const mockOnDiscard = jest.fn(); const mockOnDuplicate = jest.fn(); const mockOnSave = jest.fn(); const mockOnDiscardTempView = jest.fn(); const mockOnSaveTempView = jest.fn(); const router = RouterFixture({ location: { pathname: 'test', }, }); const tabs: Tab[] = [ { id: '1', key: '1', label: 'Prioritized', queryCount: 20, query: 'priority:high', querySort: IssueSortOptions.DATE, unsavedChanges: ['priority:low', IssueSortOptions.DATE], }, { id: '2', key: '2', label: 'For Review', queryCount: 1001, query: 'is:unassigned', querySort: IssueSortOptions.DATE, }, { id: '3', key: '3', label: 'Regressed', query: 'is:regressed', querySort: IssueSortOptions.DATE, }, ]; describe('Tabs render as expected', () => { it('should render tabs from props', () => { render( ); expect(screen.getAllByRole('tab').length).toBe(tabs.length); // The query count is included in the tab name here expect(screen.getByRole('tab', {name: 'Prioritized 20'})).toBeInTheDocument(); expect(screen.getByRole('tab', {name: 'For Review 1000+'})).toBeInTheDocument(); expect(screen.getByRole('tab', {name: 'Regressed'})).toBeInTheDocument(); }); }); // Skipping this and next tests due to excessive unexplainable flakiness // biome-ignore lint/suspicious/noSkippedTests: describe.skip('Tab menu options', () => { it('should render the correct set of actions for changed tabs', async () => { render( ); await userEvent.click( screen.getByRole('button', {name: 'Prioritized Tab Options'}) ); expect( await screen.findByRole('menuitemradio', {name: 'Save Changes'}) ).toBeInTheDocument(); expect( await screen.findByRole('menuitemradio', {name: 'Discard Changes'}) ).toBeInTheDocument(); expect( await screen.findByRole('menuitemradio', {name: 'Rename'}) ).toBeInTheDocument(); expect( await screen.findByRole('menuitemradio', {name: 'Duplicate'}) ).toBeInTheDocument(); expect( await screen.findByRole('menuitemradio', {name: 'Delete'}) ).toBeInTheDocument(); }); it('should render the correct set of actions for unchanged tabs', async () => { render( ); // We need to explicitly click on the For Review tab since it is not the default (first) tab in props await userEvent.click(screen.getByRole('tab', {name: 'For Review 1000+'})); await userEvent.click( await screen.findByRole('button', {name: 'For Review Tab Options'}) ); expect( await screen.findByRole('menuitemradio', {name: 'Rename'}) ).toBeInTheDocument(); expect( await screen.findByRole('menuitemradio', {name: 'Duplicate'}) ).toBeInTheDocument(); expect( await screen.findByRole('menuitemradio', {name: 'Delete'}) ).toBeInTheDocument(); expect( screen.queryByRole('menuitemradio', {name: 'Save Changes'}) ).not.toBeInTheDocument(); expect( screen.queryByRole('menuitemradio', {name: 'Discard Changes'}) ).not.toBeInTheDocument(); }); it('should render the correct set of actions for a single tab', async () => { render( ); await userEvent.click(screen.getByRole('button', {name: 'For Review Tab Options'})); expect( await screen.findByRole('menuitemradio', {name: 'Rename'}) ).toBeInTheDocument(); expect( await screen.findByRole('menuitemradio', {name: 'Duplicate'}) ).toBeInTheDocument(); // Delete should not be present since there is only one tab expect( screen.queryByRole('menuitemradio', {name: 'Delete'}) ).not.toBeInTheDocument(); }); it('should render the correct set of actions for temporary tabs', async () => { render( ); // We need to explicitly click on the For Review tab since it is not the default (first) tab in props await userEvent.click(screen.getByRole('tab', {name: 'Unsaved'})); await userEvent.click( await screen.findByRole('button', {name: 'Unsaved Tab Options'}) ); expect( await screen.findByRole('menuitemradio', {name: 'Save View'}) ).toBeInTheDocument(); expect( await screen.findByRole('menuitemradio', {name: 'Discard'}) ).toBeInTheDocument(); }); }); // biome-ignore lint/suspicious/noSkippedTests: describe.skip('Tab actions', () => { it('should allow renaming a tab', async () => { render( ); await userEvent.click(screen.getByRole('tab', {name: 'For Review 1000+'})); await userEvent.click( await screen.findByRole('button', {name: 'For Review Tab Options'}) ); await userEvent.click(await screen.findByRole('menuitemradio', {name: 'Rename'})); // Ctrl+A to select all text, then backspace to delete it // (We purposely do not highlight the text when hitting rename) await userEvent.keyboard('{Control>}A{/Control}{Backspace}'); await userEvent.paste('New Name'); await userEvent.keyboard('{enter}'); expect(mockOnTabRenamed).toHaveBeenCalledWith('2', 'New Name'); }); it('should not allow renaming a tab to empty string', async () => { render( ); await userEvent.click(screen.getByRole('tab', {name: 'For Review 1000+'})); await userEvent.click( await screen.findByRole('button', {name: 'For Review Tab Options'}) ); await userEvent.click(await screen.findByRole('menuitemradio', {name: 'Rename'})); await userEvent.keyboard('{Control>}A{/Control}{Backspace}'); await userEvent.keyboard('{enter}'); // Tab name should not have changed expect(screen.getByRole('tab', {name: 'For Review 1000+'})).toBeInTheDocument(); expect(mockOnTabRenamed).not.toHaveBeenCalled(); }); it('should discard changes if esc is pressed while renaming', async () => { render( ); await userEvent.click(screen.getByRole('tab', {name: 'For Review 1000+'})); await userEvent.click( await screen.findByRole('button', {name: 'For Review Tab Options'}) ); await userEvent.click(await screen.findByRole('menuitemradio', {name: 'Rename'})); await userEvent.keyboard('{Control>}A{/Control}{Backspace}'); await userEvent.paste('New Name'); await userEvent.keyboard('{esc}'); expect(mockOnTabRenamed).not.toHaveBeenCalled(); }); it('should fire the onSave callback when save changes is pressed', async () => { render( ); await userEvent.click(screen.getByRole('tab', {name: 'Prioritized 20'})); await userEvent.click( await screen.findByRole('button', {name: 'Prioritized Tab Options'}) ); await userEvent.click( await screen.findByRole('menuitemradio', {name: 'Save Changes'}) ); expect(mockOnSave).toHaveBeenCalledWith('1'); }); it('should fire the onDiscard callback when discard is pressed', async () => { render( ); await userEvent.click(screen.getByRole('tab', {name: 'Prioritized 20'})); await userEvent.click( await screen.findByRole('button', {name: 'Prioritized Tab Options'}) ); await userEvent.click( await screen.findByRole('menuitemradio', {name: 'Discard Changes'}) ); expect(mockOnDiscard).toHaveBeenCalledWith('1'); }); it('should fire the onDelete callback when delete is pressed', async () => { render( ); await userEvent.click(screen.getByRole('tab', {name: 'For Review 1000+'})); await userEvent.click( await screen.findByRole('button', {name: 'For Review Tab Options'}) ); await userEvent.click(await screen.findByRole('menuitemradio', {name: 'Delete'})); expect(mockOnDelete).toHaveBeenCalledWith('2'); }); it('should fire the onDuplicate callback when duplicate is pressed', async () => { render( ); await userEvent.click(screen.getByRole('tab', {name: 'For Review 1000+'})); await userEvent.click( await screen.findByRole('button', {name: 'For Review Tab Options'}) ); await userEvent.click( await screen.findByRole('menuitemradio', {name: 'Duplicate'}) ); expect(mockOnDuplicate).toHaveBeenCalledWith('2'); }); it('should fire the onDiscardTempView callback when the discard button is pressed for a temp view', async () => { render( ); await userEvent.click(screen.getByRole('tab', {name: 'Unsaved'})); await userEvent.click( await screen.findByRole('button', {name: 'Unsaved Tab Options'}) ); await userEvent.click(await screen.findByRole('menuitemradio', {name: 'Discard'})); expect(mockOnDiscardTempView).toHaveBeenCalled(); }); it('should fire the onSaveTempView callback when the discard button is pressed for a temp view', async () => { render( ); await userEvent.click(screen.getByRole('tab', {name: 'Unsaved'})); await userEvent.click( await screen.findByRole('button', {name: 'Unsaved Tab Options'}) ); await userEvent.click( await screen.findByRole('menuitemradio', {name: 'Save View'}) ); expect(mockOnSaveTempView).toHaveBeenCalled(); }); it('should fire the onAddView callback when the add view button is pressed', async () => { render( ); await userEvent.click(screen.getByRole('button', {name: 'Add View'})); expect(mockOnAddView).toHaveBeenCalled(); }); }); });