go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/milo/ui/src/build/legacy/build_page/change_config_dialog.test.tsx (about)

     1  // Copyright 2022 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 {
    16    act,
    17    cleanup,
    18    fireEvent,
    19    render,
    20    screen,
    21  } from '@testing-library/react';
    22  import { destroy, Instance, protect, unprotect } from 'mobx-state-tree';
    23  
    24  import { Store, StoreProvider } from '@/common/store';
    25  
    26  import { ChangeConfigDialog } from './change_config_dialog';
    27  
    28  describe('ChangeConfigDialog', () => {
    29    let store: Instance<typeof Store>;
    30    let setDefaultTabSpy: jest.SpiedFunction<(tab: string) => void>;
    31    beforeEach(() => {
    32      jest.useFakeTimers();
    33      store = Store.create();
    34      unprotect(store);
    35      setDefaultTabSpy = jest.spyOn(store.userConfig.build, 'setDefaultTab');
    36      protect(store);
    37    });
    38  
    39    afterEach(() => {
    40      cleanup();
    41      destroy(store);
    42      jest.useRealTimers();
    43    });
    44  
    45    it('should sync local state when opening the dialog', async () => {
    46      store.userConfig.build.setDefaultTab('test-results');
    47      const { rerender } = render(
    48        <StoreProvider value={store}>
    49          <ChangeConfigDialog open />
    50        </StoreProvider>,
    51      );
    52  
    53      const tabSwitch = screen.getByRole('combobox');
    54  
    55      expect(tabSwitch).toHaveTextContent('Test Results');
    56  
    57      act(() => store.userConfig.build.setDefaultTab('timeline'));
    58      await act(() => jest.runOnlyPendingTimersAsync());
    59  
    60      // Updating the config while the dialog is still open has no effect.
    61      expect(tabSwitch).toHaveTextContent('Test Results');
    62  
    63      rerender(
    64        <StoreProvider value={store}>
    65          <ChangeConfigDialog open={false} />
    66        </StoreProvider>,
    67      );
    68  
    69      expect(tabSwitch).toHaveTextContent('Test Results');
    70    });
    71  
    72    it('should update global config when confirmed', async () => {
    73      store.userConfig.build.setDefaultTab('test-results');
    74      const onCloseSpy = jest.fn();
    75  
    76      render(
    77        <StoreProvider value={store}>
    78          <ChangeConfigDialog open onClose={onCloseSpy} />
    79        </StoreProvider>,
    80      );
    81  
    82      const tabSwitch = screen.getByRole('combobox');
    83  
    84      expect(tabSwitch).toHaveTextContent('Test Results');
    85      fireEvent.mouseDown(tabSwitch);
    86  
    87      await act(() => jest.runOnlyPendingTimersAsync());
    88      fireEvent.click(screen.getByText('Timeline'));
    89      await act(() => jest.runOnlyPendingTimersAsync());
    90  
    91      expect(tabSwitch).toHaveTextContent('Timeline');
    92  
    93      expect(onCloseSpy.mock.calls.length).toStrictEqual(0);
    94      expect(setDefaultTabSpy.mock.calls.length).toStrictEqual(1);
    95  
    96      fireEvent.click(screen.getByRole('button', { name: 'Confirm' }));
    97      await act(() => jest.runOnlyPendingTimersAsync());
    98  
    99      expect(onCloseSpy.mock.calls.length).toStrictEqual(1);
   100      expect(setDefaultTabSpy.mock.calls.length).toStrictEqual(2);
   101      expect(store.userConfig.build.defaultTab).toStrictEqual('timeline');
   102    });
   103  
   104    it('should not update global config when dismissed', async () => {
   105      store.userConfig.build.setDefaultTab('test-results');
   106      const onCloseSpy = jest.fn();
   107  
   108      render(
   109        <StoreProvider value={store}>
   110          <ChangeConfigDialog open onClose={onCloseSpy} />
   111        </StoreProvider>,
   112      );
   113  
   114      const tabSwitch = screen.getByRole('combobox');
   115      expect(tabSwitch).toHaveTextContent('Test Results');
   116  
   117      fireEvent.mouseDown(tabSwitch);
   118      await act(() => jest.runOnlyPendingTimersAsync());
   119      fireEvent.click(screen.getByText('Timeline'));
   120      await act(() => jest.runOnlyPendingTimersAsync());
   121  
   122      expect(tabSwitch).toHaveTextContent('Timeline');
   123  
   124      expect(onCloseSpy.mock.calls.length).toStrictEqual(0);
   125      expect(setDefaultTabSpy.mock.calls.length).toStrictEqual(1);
   126  
   127      fireEvent.click(screen.getByRole('button', { name: 'Dismiss' }));
   128      await act(() => jest.runOnlyPendingTimersAsync());
   129  
   130      expect(onCloseSpy.mock.calls.length).toStrictEqual(1);
   131      expect(setDefaultTabSpy.mock.calls.length).toStrictEqual(1);
   132      expect(store.userConfig.build.defaultTab).toStrictEqual('test-results');
   133    });
   134  });