123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422 |
- import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
- import {
- DraggableTabBar,
- type Tab,
- } from 'sentry/views/issueList/groupSearchViewTabs/draggableTabBar';
- describe('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 defaultNewTab: Tab = {
- key: 'new-view',
- label: 'New View',
- content: <div>This is a New View</div>,
- };
- const tempTab: Tab = {
- key: 'temporary-tab',
- label: 'Unsaved',
- content: <div>This is the Temporary view</div>,
- };
- const tabs: Tab[] = [
- {
- key: '1',
- label: 'Prioritized',
- queryCount: 20,
- hasUnsavedChanges: true,
- content: <div>Tab 1 Content</div>,
- },
- {key: '2', label: 'For Review', queryCount: 1001, content: <div>Tab 2 Content</div>},
- {key: '3', label: 'Regressed', content: <div>Tab 3 Content</div>},
- ];
- describe('Tabs render as expected', () => {
- it('should render tabs from props', () => {
- render(
- <DraggableTabBar
- tabs={tabs}
- setTabs={jest.fn()}
- onTabRenamed={mockOnTabRenamed}
- showTempTab={false}
- tempTab={tempTab}
- defaultNewTab={defaultNewTab}
- />
- );
- 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();
- expect(screen.getByRole('tabpanel')).toHaveTextContent('Tab 1 Content');
- });
- it('should render temp tab if showTempTab = true', () => {
- render(
- <DraggableTabBar
- tabs={tabs}
- setTabs={jest.fn()}
- onTabRenamed={mockOnTabRenamed}
- showTempTab
- tempTab={tempTab}
- defaultNewTab={defaultNewTab}
- />
- );
- expect(screen.getByRole('tab', {name: 'Unsaved'})).toBeInTheDocument();
- });
- });
- // Skipping this and next tests due to excessive unexplainable flakiness
- // biome-ignore lint/suspicious/noSkippedTests: <explanation>
- describe.skip('Tab menu options', () => {
- it('should render the correct set of actions for changed tabs', async () => {
- render(
- <DraggableTabBar
- tabs={tabs}
- setTabs={jest.fn()}
- onTabRenamed={mockOnTabRenamed}
- showTempTab
- tempTab={tempTab}
- defaultNewTab={defaultNewTab}
- />
- );
- 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(
- <DraggableTabBar
- tabs={tabs}
- setTabs={jest.fn()}
- onTabRenamed={mockOnTabRenamed}
- showTempTab
- tempTab={tempTab}
- defaultNewTab={defaultNewTab}
- />
- );
- // 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(
- <DraggableTabBar
- tabs={[tabs[1]]}
- setTabs={jest.fn()}
- onTabRenamed={mockOnTabRenamed}
- showTempTab
- tempTab={tempTab}
- defaultNewTab={defaultNewTab}
- />
- );
- 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(
- <DraggableTabBar
- tabs={tabs}
- setTabs={jest.fn()}
- onTabRenamed={mockOnTabRenamed}
- showTempTab
- tempTab={tempTab}
- defaultNewTab={defaultNewTab}
- />
- );
- // 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: <explanation>
- describe.skip('Tab actions', () => {
- it('should allow renaming a tab', async () => {
- render(
- <DraggableTabBar
- tabs={tabs}
- setTabs={jest.fn()}
- onTabRenamed={mockOnTabRenamed}
- showTempTab
- tempTab={tempTab}
- defaultNewTab={defaultNewTab}
- />
- );
- 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(
- <DraggableTabBar
- tabs={tabs}
- setTabs={jest.fn()}
- onTabRenamed={mockOnTabRenamed}
- showTempTab
- tempTab={tempTab}
- defaultNewTab={defaultNewTab}
- />
- );
- 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(
- <DraggableTabBar
- tabs={tabs}
- setTabs={jest.fn()}
- onTabRenamed={mockOnTabRenamed}
- showTempTab
- tempTab={tempTab}
- defaultNewTab={defaultNewTab}
- />
- );
- 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(
- <DraggableTabBar
- tabs={tabs}
- setTabs={jest.fn()}
- onSave={mockOnSave}
- showTempTab
- tempTab={tempTab}
- defaultNewTab={defaultNewTab}
- />
- );
- 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(
- <DraggableTabBar
- tabs={tabs}
- setTabs={jest.fn()}
- onDiscard={mockOnDiscard}
- showTempTab
- tempTab={tempTab}
- defaultNewTab={defaultNewTab}
- />
- );
- 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(
- <DraggableTabBar
- tabs={tabs}
- setTabs={jest.fn()}
- onDelete={mockOnDelete}
- showTempTab
- tempTab={tempTab}
- defaultNewTab={defaultNewTab}
- />
- );
- 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(
- <DraggableTabBar
- tabs={tabs}
- setTabs={jest.fn()}
- onDuplicate={mockOnDuplicate}
- showTempTab
- tempTab={tempTab}
- defaultNewTab={defaultNewTab}
- />
- );
- 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(
- <DraggableTabBar
- tabs={tabs}
- setTabs={jest.fn()}
- onDiscardTempView={mockOnDiscardTempView}
- showTempTab
- tempTab={tempTab}
- defaultNewTab={defaultNewTab}
- />
- );
- 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(
- <DraggableTabBar
- tabs={tabs}
- setTabs={jest.fn()}
- onSaveTempView={mockOnSaveTempView}
- showTempTab
- tempTab={tempTab}
- defaultNewTab={defaultNewTab}
- />
- );
- 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(
- <DraggableTabBar
- tabs={tabs}
- setTabs={jest.fn()}
- onAddView={mockOnAddView}
- showTempTab
- tempTab={tempTab}
- defaultNewTab={defaultNewTab}
- />
- );
- await userEvent.click(screen.getByRole('button', {name: 'Add View'}));
- expect(mockOnAddView).toHaveBeenCalled();
- });
- });
- });
|