go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/milo/ui/src/generic_libs/components/routed_tabs/routed_tabs.test.tsx (about)

     1  // Copyright 2023 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  import { act, cleanup, render, screen } from '@testing-library/react';
    16  import { Link, RouterProvider, createMemoryRouter } from 'react-router-dom';
    17  
    18  import { useTabId } from './context';
    19  import { RoutedTab } from './routed_tab';
    20  import { RoutedTabs } from './routed_tabs';
    21  
    22  function TabA() {
    23    useTabId('tab-a');
    24    return <>tab A content</>;
    25  }
    26  
    27  function TabB() {
    28    useTabId('tab-b');
    29    return <>tab B content</>;
    30  }
    31  
    32  describe('RoutedTabs', () => {
    33    afterEach(() => {
    34      cleanup();
    35    });
    36  
    37    it('should mark the active tab correctly', () => {
    38      const router = createMemoryRouter(
    39        [
    40          {
    41            path: 'path/prefix',
    42            element: (
    43              <RoutedTabs>
    44                <RoutedTab label="tab A label" value="tab-a" to="tab-a" />
    45                <RoutedTab label="tab B label" value="tab-b" to="tab-b" />
    46              </RoutedTabs>
    47            ),
    48            children: [
    49              { path: 'tab-a', element: <TabA /> },
    50              { path: 'tab-b', element: <TabB /> },
    51            ],
    52          },
    53        ],
    54        { initialEntries: ['/path/prefix/tab-a'] },
    55      );
    56      render(<RouterProvider router={router} />);
    57  
    58      expect(screen.getByText('tab A label')).toHaveAttribute(
    59        'aria-selected',
    60        'true',
    61      );
    62      expect(screen.queryByText('tab A content')).toBeInTheDocument();
    63  
    64      expect(screen.getByText('tab B label')).not.toHaveAttribute(
    65        'aria-selected',
    66        'true',
    67      );
    68      expect(screen.queryByText('tab B content')).not.toBeInTheDocument();
    69  
    70      act(() => screen.getByText('tab B label').click());
    71  
    72      expect(screen.getByText('tab A label')).not.toHaveAttribute(
    73        'aria-selected',
    74        'true',
    75      );
    76      expect(screen.queryByText('tab A content')).not.toBeInTheDocument();
    77  
    78      expect(screen.getByText('tab B label')).toHaveAttribute(
    79        'aria-selected',
    80        'true',
    81      );
    82      expect(screen.queryByText('tab B content')).toBeInTheDocument();
    83    });
    84  
    85    it('hideWhenInactive should work correctly', () => {
    86      const router = createMemoryRouter(
    87        [
    88          {
    89            path: 'path/prefix',
    90            element: (
    91              <>
    92                <Link to="tab-b">direct link to tab B</Link>
    93                <RoutedTabs>
    94                  <RoutedTab label="tab A label" value="tab-a" to="tab-a" />
    95                  <RoutedTab
    96                    label="tab B label"
    97                    value="tab-b"
    98                    to="tab-b"
    99                    hideWhenInactive
   100                  />
   101                </RoutedTabs>
   102              </>
   103            ),
   104            children: [
   105              { path: 'tab-a', element: <TabA /> },
   106              { path: 'tab-b', element: <TabB /> },
   107            ],
   108          },
   109        ],
   110        { initialEntries: ['/path/prefix/tab-a'] },
   111      );
   112      render(<RouterProvider router={router} />);
   113  
   114      expect(screen.getByText('tab B label')).toHaveStyleRule('display', 'none');
   115  
   116      act(() => screen.getByText('direct link to tab B').click());
   117      expect(screen.getByText('tab B label')).not.toHaveStyleRule(
   118        'display',
   119        'none',
   120      );
   121    });
   122  });