go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/milo/ui/src/gitiles/components/commit_table/commit_table.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 userEvent from '@testing-library/user-event';
    17  
    18  import { OutputCommit } from '@/gitiles/types';
    19  import { Commit_TreeDiff_ChangeType } from '@/proto/go.chromium.org/luci/common/proto/git/commit.pb';
    20  import { FakeContextProvider } from '@/testing_tools/fakes/fake_context_provider';
    21  
    22  import { CommitTable } from './commit_table';
    23  import { CommitTableBody } from './commit_table_body';
    24  import { CommitTableHead } from './commit_table_head';
    25  import { CommitTableRow } from './commit_table_row';
    26  
    27  const commit: OutputCommit = {
    28    id: '1234567890abcdef',
    29    tree: '1234567890abcdef',
    30    parents: ['1234567890abcdee'],
    31    author: {
    32      name: 'author',
    33      email: 'author@email.com',
    34      time: '2022-02-02T23:22:22Z',
    35    },
    36    committer: {
    37      name: 'committer',
    38      email: 'committer@email.com',
    39      time: '2022-02-02T23:22:22Z',
    40    },
    41    message: 'this is a commit\ndescription\n',
    42    treeDiff: [
    43      {
    44        type: Commit_TreeDiff_ChangeType.MODIFY,
    45        oldId: '1234567890abcdef',
    46        oldMode: 33188,
    47        oldPath: 'ash/style/combobox.cc',
    48        newId: '1234567890abcdef',
    49        newMode: 33188,
    50        newPath: 'ash/style/combobox.cc',
    51      },
    52    ],
    53  };
    54  
    55  describe('CommitTable', () => {
    56    beforeEach(() => {
    57      jest.useFakeTimers();
    58    });
    59  
    60    afterEach(() => {
    61      jest.useRealTimers();
    62      cleanup();
    63    });
    64  
    65    it('should expand/collapse correctly', async () => {
    66      render(
    67        <FakeContextProvider>
    68          <CommitTable repoUrl="https://repo.url">
    69            <CommitTableHead>
    70              <></>
    71            </CommitTableHead>
    72            <CommitTableBody>
    73              <CommitTableRow commit={commit}>
    74                <></>
    75              </CommitTableRow>
    76            </CommitTableBody>
    77          </CommitTable>
    78        </FakeContextProvider>,
    79      );
    80  
    81      const toggleRowButton = screen.getByLabelText('toggle-row');
    82      const toggleAllRowsButton = screen.getByLabelText('toggle-all-rows');
    83      const contentRow = screen.getByTestId('content-row');
    84  
    85      expect(
    86        toggleRowButton.querySelector("[data-testid='ChevronRightIcon']"),
    87      ).toBeInTheDocument();
    88      expect(
    89        toggleRowButton.querySelector("[data-testid='ExpandMoreIcon']"),
    90      ).not.toBeInTheDocument();
    91      expect(contentRow).toHaveStyle({ display: 'none' });
    92  
    93      // Expand by clicking on toggle button.
    94      act(() => toggleRowButton.click());
    95      expect(
    96        toggleRowButton.querySelector("[data-testid='ChevronRightIcon']"),
    97      ).not.toBeInTheDocument();
    98      expect(
    99        toggleRowButton.querySelector("[data-testid='ExpandMoreIcon']"),
   100      ).toBeInTheDocument();
   101      expect(contentRow).not.toHaveStyle({ display: 'none' });
   102  
   103      // Collapse by clicking on toggle button.
   104      act(() => toggleRowButton.click());
   105      expect(
   106        toggleRowButton.querySelector("[data-testid='ChevronRightIcon']"),
   107      ).toBeInTheDocument();
   108      expect(
   109        toggleRowButton.querySelector("[data-testid='ExpandMoreIcon']"),
   110      ).not.toBeInTheDocument();
   111      expect(contentRow).toHaveStyle({ display: 'none' });
   112  
   113      // Expand again by changing the default state.
   114      act(() => toggleAllRowsButton.click());
   115      await act(() => jest.runAllTimersAsync());
   116      expect(
   117        toggleRowButton.querySelector("[data-testid='ChevronRightIcon']"),
   118      ).not.toBeInTheDocument();
   119      expect(
   120        toggleRowButton.querySelector("[data-testid='ExpandMoreIcon']"),
   121      ).toBeInTheDocument();
   122      expect(contentRow).not.toHaveStyle({ display: 'none' });
   123  
   124      // Collapse again by changing the default state.
   125      act(() => toggleAllRowsButton.click());
   126      await act(() => jest.runAllTimersAsync());
   127      expect(
   128        toggleRowButton.querySelector("[data-testid='ChevronRightIcon']"),
   129      ).toBeInTheDocument();
   130      expect(
   131        toggleRowButton.querySelector("[data-testid='ExpandMoreIcon']"),
   132      ).not.toBeInTheDocument();
   133      expect(contentRow).toHaveStyle({ display: 'none' });
   134    });
   135  
   136    it('should expand/collapse correctly with hotkey', async () => {
   137      render(
   138        <FakeContextProvider>
   139          <CommitTable repoUrl="https://repo.url">
   140            <CommitTableHead toggleExpandHotkey="x">
   141              <></>
   142            </CommitTableHead>
   143            <CommitTableBody>
   144              <CommitTableRow commit={commit}>
   145                <></>
   146              </CommitTableRow>
   147            </CommitTableBody>
   148          </CommitTable>
   149        </FakeContextProvider>,
   150      );
   151  
   152      const toggleRowButton = screen.getByLabelText('toggle-row');
   153      const contentRow = screen.getByTestId('content-row');
   154  
   155      expect(
   156        toggleRowButton.querySelector("[data-testid='ChevronRightIcon']"),
   157      ).toBeInTheDocument();
   158      expect(
   159        toggleRowButton.querySelector("[data-testid='ExpandMoreIcon']"),
   160      ).not.toBeInTheDocument();
   161      expect(contentRow).toHaveStyle({ display: 'none' });
   162  
   163      // Expand by clicking on toggle button.
   164      act(() => toggleRowButton.click());
   165      expect(
   166        toggleRowButton.querySelector("[data-testid='ChevronRightIcon']"),
   167      ).not.toBeInTheDocument();
   168      expect(
   169        toggleRowButton.querySelector("[data-testid='ExpandMoreIcon']"),
   170      ).toBeInTheDocument();
   171      expect(contentRow).not.toHaveStyle({ display: 'none' });
   172  
   173      // Collapse by clicking on toggle button.
   174      act(() => toggleRowButton.click());
   175      expect(
   176        toggleRowButton.querySelector("[data-testid='ChevronRightIcon']"),
   177      ).toBeInTheDocument();
   178      expect(
   179        toggleRowButton.querySelector("[data-testid='ExpandMoreIcon']"),
   180      ).not.toBeInTheDocument();
   181      expect(contentRow).toHaveStyle({ display: 'none' });
   182  
   183      // Expand again by changing the default state.
   184      await act(() =>
   185        Promise.all([userEvent.keyboard('x'), jest.runAllTimersAsync()]),
   186      );
   187      expect(
   188        toggleRowButton.querySelector("[data-testid='ChevronRightIcon']"),
   189      ).not.toBeInTheDocument();
   190      expect(
   191        toggleRowButton.querySelector("[data-testid='ExpandMoreIcon']"),
   192      ).toBeInTheDocument();
   193      expect(contentRow).not.toHaveStyle({ display: 'none' });
   194  
   195      // Collapse again by changing the default state.
   196      await act(() =>
   197        Promise.all([userEvent.keyboard('x'), jest.runAllTimersAsync()]),
   198      );
   199      expect(
   200        toggleRowButton.querySelector("[data-testid='ChevronRightIcon']"),
   201      ).toBeInTheDocument();
   202      expect(
   203        toggleRowButton.querySelector("[data-testid='ExpandMoreIcon']"),
   204      ).not.toBeInTheDocument();
   205      expect(contentRow).toHaveStyle({ display: 'none' });
   206    });
   207  
   208    it('should notify default state update correctly', async () => {
   209      const onExpandSpy = jest.fn((_expanded: boolean) => {});
   210      render(
   211        <FakeContextProvider>
   212          <CommitTable
   213            initDefaultExpanded={true}
   214            onDefaultExpandedChanged={onExpandSpy}
   215            repoUrl="https://repo.url"
   216          >
   217            <CommitTableHead>
   218              <></>
   219            </CommitTableHead>
   220            <CommitTableBody>
   221              <></>
   222            </CommitTableBody>
   223          </CommitTable>
   224        </FakeContextProvider>,
   225      );
   226      await act(() => jest.runAllTimersAsync());
   227  
   228      // Don't notify on first render.
   229      expect(onExpandSpy).not.toHaveBeenCalled();
   230  
   231      const toggleButton = screen.getByLabelText('toggle-all-rows');
   232  
   233      // Collapse by clicking on toggle button.
   234      act(() => toggleButton.click());
   235      expect(onExpandSpy).toHaveBeenNthCalledWith(1, false);
   236  
   237      // Expand by clicking on toggle button.
   238      act(() => toggleButton.click());
   239      expect(onExpandSpy).toHaveBeenNthCalledWith(2, true);
   240    });
   241  });