test: wrap all user calls in act()

Some user events trigger react dom changes. These need to be wrapped in
act() to avoid a warning printed to the console. To be save, we wrap
all instances.
This commit is contained in:
David Lechner
2023-03-10 18:16:27 -06:00
committed by David Lechner
parent 78290eb927
commit d88ce8998f
42 changed files with 212 additions and 172 deletions
+24 -24
View File
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
// Copyright (c) 2022-2023 The Pybricks Authors
import { cleanup, waitFor } from '@testing-library/react';
import { act, cleanup, waitFor } from '@testing-library/react';
import React from 'react';
import { testRender, uuid } from '../../test';
import { FileMetadata } from '../fileStorage';
@@ -39,7 +39,7 @@ describe('archive button', () => {
const button = explorer.getByTitle('Backup all files');
expect(button).toBeEnabled();
await user.click(button);
await act(() => user.click(button));
expect(dispatch).toHaveBeenCalledWith(explorerArchiveAllFiles());
});
});
@@ -50,7 +50,7 @@ describe('import file button', () => {
const button = explorer.getByTitle('Import a file');
await user.click(button);
await act(() => user.click(button));
expect(dispatch).toHaveBeenCalledWith(explorerImportFiles());
});
});
@@ -61,7 +61,7 @@ describe('new file button', () => {
const button = explorer.getByTitle('Create a new file');
await user.click(button);
await act(() => user.click(button));
expect(dispatch).toHaveBeenCalledWith(explorerCreateNewFile());
});
});
@@ -73,7 +73,7 @@ describe('tree item', () => {
const treeItem = explorer.getByRole('treeitem', { name: 'test.file' });
await user.click(treeItem);
await act(() => user.click(treeItem));
expect(dispatch).toHaveBeenCalledWith(
explorerUserActivateFile('test.file', uuid(0)),
@@ -86,8 +86,8 @@ describe('tree item', () => {
const treeItem = explorer.getByRole('treeitem', { name: 'test.file' });
await user.click(treeItem);
await user.keyboard('{Enter}');
await act(() => user.click(treeItem));
await act(() => user.keyboard('{Enter}'));
expect(dispatch).toHaveBeenCalledWith(
explorerUserActivateFile('test.file', uuid(0)),
@@ -100,14 +100,14 @@ describe('tree item', () => {
const [user, explorer, dispatch] = testRender(<Explorer />);
const treeItem = explorer.getByRole('treeitem', { name: 'test.file' });
await user.hover(treeItem);
await act(() => user.hover(treeItem));
const button = await waitFor(() =>
explorer.getByRole('button', { name: 'Duplicate test.file' }),
);
// user.click() has bad interaction with hover so we use user.pointer() instead
await user.pointer({ keys: '[MouseLeft]', target: button });
await act(() => user.pointer({ keys: '[MouseLeft]', target: button }));
expect(dispatch).toHaveBeenCalledWith(explorerDuplicateFile('test.file'));
@@ -121,8 +121,8 @@ describe('tree item', () => {
const treeItem = explorer.getByRole('treeitem', { name: 'test.file' });
await user.click(treeItem);
await user.keyboard('{Control>}d{/Control}');
await act(() => user.click(treeItem));
await act(() => user.keyboard('{Control>}d{/Control}'));
expect(dispatch).toHaveBeenCalledWith(explorerDuplicateFile('test.file'));
});
@@ -134,14 +134,14 @@ describe('tree item', () => {
const [user, explorer, dispatch] = testRender(<Explorer />);
const treeItem = explorer.getByRole('treeitem', { name: 'test.file' });
await user.hover(treeItem);
await act(() => user.hover(treeItem));
const button = await waitFor(() =>
explorer.getByRole('button', { name: 'Rename test.file' }),
);
// user.click() has bad interaction with hover so we use user.pointer() instead
await user.pointer({ keys: '[MouseLeft]', target: button });
await act(() => user.pointer({ keys: '[MouseLeft]', target: button }));
expect(dispatch).toHaveBeenCalledWith(explorerRenameFile('test.file'));
@@ -155,8 +155,8 @@ describe('tree item', () => {
const treeItem = explorer.getByRole('treeitem', { name: 'test.file' });
await user.click(treeItem);
await user.keyboard('{F2}');
await act(() => user.click(treeItem));
await act(() => user.keyboard('{F2}'));
expect(dispatch).toHaveBeenCalledWith(explorerRenameFile('test.file'));
});
@@ -168,14 +168,14 @@ describe('tree item', () => {
const [user, explorer, dispatch] = testRender(<Explorer />);
const treeItem = explorer.getByRole('treeitem', { name: 'test.file' });
await user.hover(treeItem);
await act(() => user.hover(treeItem));
const button = await waitFor(() =>
explorer.getByRole('button', { name: 'Export test.file' }),
);
// user.click() has bad interaction with hover so we use user.pointer() instead
await user.pointer({ keys: '[MouseLeft]', target: button });
await act(() => user.pointer({ keys: '[MouseLeft]', target: button }));
expect(dispatch).toHaveBeenCalledWith(explorerExportFile('test.file'));
@@ -189,8 +189,8 @@ describe('tree item', () => {
const treeItem = explorer.getByRole('treeitem', { name: 'test.file' });
await user.click(treeItem);
await user.keyboard('{Control>}e{/Control}');
await act(() => user.click(treeItem));
await act(() => user.keyboard('{Control>}e{/Control}'));
expect(dispatch).toHaveBeenCalledWith(explorerExportFile('test.file'));
});
@@ -202,14 +202,14 @@ describe('tree item', () => {
const [user, explorer, dispatch] = testRender(<Explorer />);
const treeItem = explorer.getByRole('treeitem', { name: 'test.file' });
await user.hover(treeItem);
await act(() => user.hover(treeItem));
const button = await waitFor(() =>
explorer.getByRole('button', { name: 'Delete test.file' }),
);
// user.click() has bad interaction with hover so we use user.pointer() instead
await user.pointer({ keys: '[MouseLeft]', target: button });
await act(() => user.pointer({ keys: '[MouseLeft]', target: button }));
expect(dispatch).toHaveBeenCalledWith(
explorerDeleteFile('test.file', uuid(0)),
@@ -225,8 +225,8 @@ describe('tree item', () => {
const treeItem = explorer.getByRole('treeitem', { name: 'test.file' });
await user.click(treeItem);
await user.keyboard('{Delete}');
await act(() => user.click(treeItem));
await act(() => user.keyboard('{Delete}'));
expect(dispatch).toHaveBeenCalledWith(
explorerDeleteFile('test.file', uuid(0)),
+2 -1
View File
@@ -2,6 +2,7 @@
// Copyright (c) 2022-2023 The Pybricks Authors
import { Toast } from '@blueprintjs/core';
import { act } from '@testing-library/react';
import React from 'react';
import { testRender } from '../../../test';
import { fileInUse } from './FileInUseAlert';
@@ -12,7 +13,7 @@ it('should dismiss when close is clicked', async () => {
const [user, message] = testRender(<Toast {...toast} />);
await user.click(message.getByRole('button', { name: /close/i }));
await act(() => user.click(message.getByRole('button', { name: /close/i })));
expect(callback).toHaveBeenCalledWith('dismiss');
});
+2 -1
View File
@@ -2,6 +2,7 @@
// Copyright (c) 2022-2023 The Pybricks Authors
import { Toast } from '@blueprintjs/core';
import { act } from '@testing-library/react';
import React from 'react';
import { testRender } from '../../../test';
import { noFilesToBackup } from './NoFilesToBackup';
@@ -12,7 +13,7 @@ it('should dismiss when close is clicked', async () => {
const [user, message] = testRender(<Toast {...toast} />);
await user.click(message.getByRole('button', { name: /close/i }));
await act(() => user.click(message.getByRole('button', { name: /close/i })));
expect(callback).toHaveBeenCalledWith('dismiss');
});
+2 -1
View File
@@ -2,6 +2,7 @@
// Copyright (c) 2022-2023 The Pybricks Authors
import { Toast } from '@blueprintjs/core';
import { act } from '@testing-library/react';
import React from 'react';
import { testRender } from '../../../test';
import { noPyFiles } from './NoPyFiles';
@@ -12,7 +13,7 @@ it('should dismiss when close is clicked', async () => {
const [user, message] = testRender(<Toast {...toast} />);
await user.click(message.getByRole('button', { name: /close/i }));
await act(() => user.click(message.getByRole('button', { name: /close/i })));
expect(callback).toHaveBeenCalledWith('dismiss');
});
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
// Copyright (c) 2022-2023 The Pybricks Authors
import { cleanup, waitFor } from '@testing-library/react';
import { act, cleanup, waitFor } from '@testing-library/react';
import React from 'react';
import { testRender } from '../../../test';
import DeleteFileAlert from './DeleteFileAlert';
@@ -17,7 +17,7 @@ describe('accept', () => {
explorer: { deleteFileAlert: { fileName: 'test.file', isOpen: true } },
});
await user.click(dialog.getByRole('button', { name: 'Delete' }));
await act(() => user.click(dialog.getByRole('button', { name: 'Delete' })));
expect(dispatch).toHaveBeenCalledWith(deleteFileAlertDidAccept());
});
@@ -29,7 +29,7 @@ describe('accept', () => {
await waitFor(() =>
expect(dialog.getByRole('button', { name: 'Delete' })).toHaveFocus(),
);
await user.keyboard('{Enter}');
await act(() => user.keyboard('{Enter}'));
expect(dispatch).toHaveBeenCalledWith(deleteFileAlertDidAccept());
});
@@ -41,7 +41,7 @@ describe('cancel', () => {
explorer: { deleteFileAlert: { fileName: 'test.file', isOpen: true } },
});
await user.click(dialog.getByRole('button', { name: 'Keep' }));
await act(() => user.click(dialog.getByRole('button', { name: 'Keep' })));
expect(dispatch).toHaveBeenCalledWith(deleteFileAlertDidCancel());
});
@@ -55,7 +55,7 @@ describe('cancel', () => {
expect(dialog.getByRole('button', { name: 'Delete' })).toHaveFocus(),
);
await user.keyboard('{Escape}');
await act(() => user.keyboard('{Escape}'));
expect(dispatch).toHaveBeenCalledWith(deleteFileAlertDidCancel());
});
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
// Copyright (c) 2022-2023 The Pybricks Authors
import { waitFor } from '@testing-library/dom';
import { act } from '@testing-library/react';
import React from 'react';
import { testRender } from '../../../test';
import DuplicateFileDialog from './DuplicateFileDialog';
@@ -20,10 +21,10 @@ describe('duplicate button', () => {
// have to type a new file name before Duplicate button is enabled
const input = dialog.getByRole('textbox', { name: 'File name' });
await waitFor(() => expect(input).toHaveFocus());
await user.type(input, 'new', { skipClick: true });
await act(() => user.type(input, 'new', { skipClick: true }));
await waitFor(() => expect(button).not.toBeDisabled());
await user.click(button);
await act(() => user.click(button));
expect(dispatch).toHaveBeenCalledWith(
duplicateFileDialogDidAccept('source.file', 'new.file'),
);
@@ -39,7 +40,7 @@ describe('duplicate button', () => {
// have to type a new file name before Duplicate button is enabled
const input = dialog.getByRole('textbox', { name: 'File name' });
await waitFor(() => expect(input).toHaveFocus());
await user.type(input, 'new{Enter}', { skipClick: true });
await act(() => user.type(input, 'new{Enter}', { skipClick: true }));
expect(dispatch).toHaveBeenCalledWith(
duplicateFileDialogDidAccept('source.file', 'new.file'),
@@ -57,7 +58,7 @@ describe('duplicate button', () => {
await waitFor(() => expect(button).toBeVisible());
await user.click(button);
await act(() => user.click(button));
expect(dispatch).toHaveBeenCalledWith(duplicateFileDialogDidCancel());
});
@@ -72,7 +73,7 @@ describe('duplicate button', () => {
expect(dialog.getByRole('textbox', { name: 'File name' })).toHaveFocus(),
);
await user.keyboard('{Escape}');
await act(() => user.keyboard('{Escape}'));
expect(dispatch).toHaveBeenCalledWith(duplicateFileDialogDidCancel());
});
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022-2023 The Pybricks Authors
import { cleanup } from '@testing-library/react';
import { act, cleanup } from '@testing-library/react';
import React from 'react';
import { testRender } from '../../../test';
import { FileNameValidationResult } from '../../pybricksMicropython/lib';
@@ -40,7 +40,7 @@ it('should fix file names with spaces', async () => {
/>,
);
await user.click(group.getByRole('button', { name: /fix it/i }));
await act(() => user.click(group.getByRole('button', { name: /fix it/i })));
expect(callback).toHaveBeenCalledWith('test_name');
});
@@ -57,7 +57,7 @@ it('should fix file names with file extension', async () => {
/>,
);
await user.click(group.getByRole('button', { name: /fix it/i }));
await act(() => user.click(group.getByRole('button', { name: /fix it/i })));
expect(callback).toHaveBeenCalledWith('test');
});
@@ -74,7 +74,7 @@ it('should fix file names with invalid characters', async () => {
/>,
);
await user.click(group.getByRole('button', { name: /fix it/i }));
await act(() => user.click(group.getByRole('button', { name: /fix it/i })));
expect(callback).toHaveBeenCalledWith('test_name');
});
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
// Copyright (c) 2022-2023 The Pybricks Authors
import { waitFor } from '@testing-library/dom';
import { cleanup } from '@testing-library/react';
import { act, cleanup } from '@testing-library/react';
import React from 'react';
import { testRender } from '../../../test';
import { Hub } from '../../components/hubPicker';
@@ -22,10 +22,12 @@ describe('accept', () => {
const button = dialog.getByLabelText('Create');
// have to type a file name before Create button is enabled
await user.type(dialog.getByRole('textbox', { name: 'File name' }), 'test');
await act(() =>
user.type(dialog.getByRole('textbox', { name: 'File name' }), 'test'),
);
await waitFor(() => expect(button).not.toBeDisabled());
await user.click(button);
await act(() => user.click(button));
expect(dispatch).toHaveBeenCalledWith(
newFileWizardDidAccept('test', '.py', Hub.Move),
);
@@ -36,9 +38,11 @@ describe('accept', () => {
explorer: { newFileWizard: { isOpen: true } },
});
await user.type(
dialog.getByRole('textbox', { name: 'File name' }),
'test{Enter}',
await act(() =>
user.type(
dialog.getByRole('textbox', { name: 'File name' }),
'test{Enter}',
),
);
expect(dispatch).toHaveBeenCalledWith(
@@ -53,7 +57,7 @@ describe('cancel', () => {
explorer: { newFileWizard: { isOpen: true } },
});
await user.click(dialog.getByRole('button', { name: 'Close' }));
await act(() => user.click(dialog.getByRole('button', { name: 'Close' })));
expect(dispatch).toHaveBeenCalledWith(newFileWizardDidCancel());
});
@@ -67,7 +71,7 @@ describe('cancel', () => {
expect(dialog.getByRole('textbox', { name: 'File name' })).toHaveFocus(),
);
await user.keyboard('{Escape}');
await act(() => user.keyboard('{Escape}'));
expect(dispatch).toHaveBeenCalledWith(newFileWizardDidCancel());
});
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
// Copyright (c) 2022-2023 The Pybricks Authors
import { waitFor } from '@testing-library/dom';
import { act } from '@testing-library/react';
import React from 'react';
import { testRender } from '../../../test';
import RenameFileDialog from './RenameFileDialog';
@@ -18,10 +19,10 @@ describe('rename button', () => {
// have to type a new file name before Rename button is enabled
const input = dialog.getByLabelText('File name');
await waitFor(() => expect(input).toHaveFocus());
await user.type(input, 'new', { skipClick: true });
await act(() => user.type(input, 'new', { skipClick: true }));
await waitFor(() => expect(button).not.toBeDisabled());
await user.click(button);
await act(() => user.click(button));
expect(dispatch).toHaveBeenCalledWith(
renameFileDialogDidAccept('old.file', 'new.file'),
);
@@ -35,7 +36,7 @@ describe('rename button', () => {
// have to type a new file name before Rename button is enabled
const input = dialog.getByLabelText('File name');
await waitFor(() => expect(input).toHaveFocus());
await user.type(input, 'new{Enter}', { skipClick: true });
await act(() => user.type(input, 'new{Enter}', { skipClick: true }));
expect(dispatch).toHaveBeenCalledWith(
renameFileDialogDidAccept('old.file', 'new.file'),
@@ -51,7 +52,7 @@ describe('rename button', () => {
await waitFor(() => expect(button).toBeVisible());
await user.click(button);
await act(() => user.click(button));
expect(dispatch).toHaveBeenCalledWith(renameFileDialogDidCancel());
});
});
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
// Copyright (c) 2022-2023 The Pybricks Authors
import { waitFor } from '@testing-library/dom';
import { act } from '@testing-library/react';
import React from 'react';
import { testRender } from '../../../test';
import RenameImportDialog from './RenameImportDialog';
@@ -18,10 +19,10 @@ describe('rename button', () => {
// have to type a new file name before Rename button is enabled
const input = dialog.getByLabelText('File name');
await waitFor(() => expect(input).toHaveFocus());
await user.type(input, 'new', { skipClick: true });
await act(() => user.type(input, 'new', { skipClick: true }));
await waitFor(() => expect(button).not.toBeDisabled());
await user.click(button);
await act(() => user.click(button));
expect(dispatch).toHaveBeenCalledWith(
renameImportDialogDidAccept('old.file', 'new.file'),
);
@@ -35,7 +36,7 @@ describe('rename button', () => {
// have to type a new file name before Rename button is enabled
const input = dialog.getByLabelText('File name');
await waitFor(() => expect(input).toHaveFocus());
await user.type(input, 'new{Enter}', { skipClick: true });
await act(() => user.type(input, 'new{Enter}', { skipClick: true }));
expect(dispatch).toHaveBeenCalledWith(
renameImportDialogDidAccept('old.file', 'new.file'),
@@ -51,7 +52,7 @@ describe('rename button', () => {
await waitFor(() => expect(button).toBeVisible());
await user.click(button);
await act(() => user.click(button));
expect(dispatch).toHaveBeenCalledWith(renameImportDialogDidCancel());
});
@@ -64,7 +65,7 @@ describe('rename button', () => {
await waitFor(() => expect(button).toBeVisible());
await user.click(button);
await act(() => user.click(button));
expect(dispatch).toHaveBeenCalledWith(renameImportDialogDidCancel());
});
});
@@ -2,6 +2,7 @@
// Copyright (c) 2022-2023 The Pybricks Authors
import { waitFor } from '@testing-library/dom';
import { act } from '@testing-library/react';
import React from 'react';
import { testRender } from '../../../test';
import RenameImportDialog from './ReplaceImportDialog';
@@ -32,11 +33,11 @@ describe('replace button', () => {
const rememberCheckBox = dialog.getByRole('checkbox', {
name: /remember/i,
});
await user.click(rememberCheckBox);
await act(() => user.click(rememberCheckBox));
}
const button = dialog.getByRole('button', { name: buttonName });
await user.click(button);
await act(() => user.click(button));
expect(dispatch).toHaveBeenCalledWith(
replaceImportDialogDidAccept(action, remember),
@@ -53,7 +54,7 @@ describe('replace button', () => {
await waitFor(() => expect(button).toBeVisible());
await user.click(button);
await act(() => user.click(button));
expect(dispatch).toHaveBeenCalledWith(replaceImportDialogDidCancel());
});
});