Skip to content

Commit

Permalink
fix(ci): try to avoid flaky tests (#443)
Browse files Browse the repository at this point in the history
* increase jest timeout
* refactor some tests
  • Loading branch information
renaudAmsellem authored Apr 8, 2024
1 parent 7b17f3f commit 8b6820b
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 80 deletions.
2 changes: 1 addition & 1 deletion apps/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"start": "vite",
"build": "vite build",
"test": "jest",
"test:ci": "jest --maxWorkers=2",
"test:ci": "jest",
"test:commit": "jest --maxWorkers=50% --onlyChanged",
"lint": "eslint src/",
"gen_types": "apollo codegen:generate ./src/_gqlTypes --target=typescript --no-addTypename --outputFlat --passthroughCustomScalars --excludes='**/*.test.*' && cd ../../ && yarn prettier --write apps/admin/src/_gqlTypes",
Expand Down
2 changes: 1 addition & 1 deletion libs/ui/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ module.exports = {
},
transformIgnorePatterns: ['node_modules'],
testRegex: '.test.(ts|tsx)$',
testTimeout: 30000,
testTimeout: 60000,
moduleNameMapper: require('../../jestModuleNameMapper')
};
56 changes: 24 additions & 32 deletions libs/ui/src/components/AttributePicker/AttributePicker.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,11 @@ describe('AttributePicker', () => {

test('Display attributes', async () => {
const mockHandleSubmit = jest.fn();
render(<AttributePicker onClose={jest.fn()} onSubmit={mockHandleSubmit} open />, {mocks: baseMocks});

await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());
render(<AttributePicker onClose={jest.fn()} onSubmit={mockHandleSubmit} open />, {
mocks: baseMocks
});

expect(screen.getByText('attributeA')).toBeInTheDocument();
await waitFor(() => expect(screen.getByText('attributeA')).toBeInTheDocument());
expect(screen.getByText('attributeB')).toBeInTheDocument();
expect(screen.getByText('attributeC')).toBeInTheDocument();
});
Expand Down Expand Up @@ -119,9 +119,7 @@ describe('AttributePicker', () => {
const mockHandleSubmit = jest.fn();
render(<AttributePicker onClose={jest.fn()} onSubmit={mockHandleSubmit} open />, {mocks: mocksWithFilters});

await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());

expect(screen.getByText('attributeA')).toBeInTheDocument();
await waitFor(() => expect(screen.getByText('attributeA')).toBeInTheDocument());
expect(screen.getByText('attributeB')).toBeInTheDocument();
expect(screen.getByText('attributeC')).toBeInTheDocument();

Expand Down Expand Up @@ -171,8 +169,7 @@ describe('AttributePicker', () => {
const mockHandleSubmit = jest.fn();
render(<AttributePicker onClose={jest.fn()} onSubmit={mockHandleSubmit} open />, {mocks: mocksWithSort});

await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());

await waitFor(() => expect(screen.getByText('attributeA')).toBeInTheDocument());
const rows = screen.getAllByRole('row');
expect(rows[0]).toHaveTextContent('attributeA');
expect(rows[1]).toHaveTextContent('attributeB');
Expand All @@ -189,34 +186,31 @@ describe('AttributePicker', () => {
const mockHandleSubmit = jest.fn();
render(<AttributePicker onClose={jest.fn()} onSubmit={mockHandleSubmit} open />, {mocks: baseMocks});

await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());

userEvent.click(screen.getByText('attributeA'));
await waitFor(() => expect(screen.getByText('attributeA')).toBeInTheDocument());
await userEvent.click(screen.getByText('attributeA'));
const rows = screen.getAllByRole('row');
const rowAttributeA = rows[0];
const rowAttributeB = rows[1];
const rowAttributeC = rows[2];

// Select 'attributeA'
const checkboxAttributeA = within(rowAttributeA).getByRole('checkbox'); // First checkbox is for the table header
await waitFor(() => expect(checkboxAttributeA).toBeChecked());
expect(checkboxAttributeA).toBeChecked();

// Unselect 'attributeA'
userEvent.click(checkboxAttributeA);
await waitFor(() => expect(checkboxAttributeA).not.toBeChecked());
await userEvent.click(checkboxAttributeA);
expect(checkboxAttributeA).not.toBeChecked();

// Select "libB" and "libC"
const checkboxAttributeB = within(rowAttributeB).getByRole('checkbox'); // First checkbox is for the table header
userEvent.click(checkboxAttributeB);
await userEvent.click(checkboxAttributeB);

const checkboxAttributeC = within(rowAttributeC).getByRole('checkbox'); // First checkbox is for the table header
userEvent.click(checkboxAttributeC);
await userEvent.click(checkboxAttributeC);

userEvent.click(screen.getByRole('button', {name: /submit/i}));
await userEvent.click(screen.getByRole('button', {name: /submit/i}));

await waitFor(() => expect(mockHandleSubmit).toHaveBeenCalledWith(['attributeB', 'attributeC']), {
timeout: 10000
});
expect(mockHandleSubmit).toHaveBeenCalledWith(['attributeB', 'attributeC']);
});

test('If not multiple, only one element can be selected', async () => {
Expand All @@ -225,24 +219,23 @@ describe('AttributePicker', () => {
mocks: baseMocks
});

await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());
await waitFor(() => expect(screen.getByText('attributeA')).toBeInTheDocument());

userEvent.click(screen.getByText('attributeA'));
await userEvent.click(screen.getByText('attributeA'));
const radioBtnAttributeA = within(screen.getByRole('row', {name: /attributeA/i})).getByRole('radio');
const radioBtnAttributeB = within(screen.getByRole('row', {name: /attributeA/i})).getByRole('radio');
await waitFor(() => expect(radioBtnAttributeA).toBeChecked());
const radioBtnAttributeB = within(screen.getByRole('row', {name: /attributeB/i})).getByRole('radio');
expect(radioBtnAttributeA).toBeChecked();

userEvent.click(screen.getByText('attributeB'));
await waitFor(() => expect(radioBtnAttributeB).toBeChecked());
await waitFor(() => expect(radioBtnAttributeA).not.toBeChecked());
await userEvent.click(screen.getByText('attributeB'));
expect(radioBtnAttributeB).toBeChecked();
expect(radioBtnAttributeA).not.toBeChecked();
});

test('Can create new attribute', async () => {
const mockHandleSubmit = jest.fn();
render(<AttributePicker onClose={jest.fn()} onSubmit={mockHandleSubmit} open />, {mocks: baseMocks});

await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());

await waitFor(() => expect(screen.getByText('attributeA')).toBeInTheDocument());
const newAttributeButton = screen.queryByRole('button', {name: /new_attribute/i});
expect(newAttributeButton).toBeInTheDocument();

Expand Down Expand Up @@ -279,8 +272,7 @@ describe('AttributePicker', () => {
mocks: mocksNotAllowed
});

await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());

await waitFor(() => expect(screen.getByText('attributeA')).toBeInTheDocument());
expect(screen.queryByRole('button', {name: /new_attribute/i})).not.toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -77,22 +77,20 @@ describe('EditLibraryAttributes', () => {

render(<EditLibraryAttributes library={mockLibrary} />);

expect(await screen.findByText('Attribut A')).toBeInTheDocument();
await waitFor(() => expect(screen.getByText('Attribut A')).toBeInTheDocument());
expect(screen.getByText('Attribut B')).toBeInTheDocument();

// Delete attribute A
await user.click(screen.getAllByRole('button', {name: /delete/i})[0]);
user.click(screen.getByRole('button', {name: /submit/i})); // Confirm
await user.click(screen.getByRole('button', {name: /submit/i})); // Confirm

await waitFor(() => {
expect(mockSaveLibraryMutation).toBeCalledWith({
variables: {
library: {
id: mockLibrary.id,
attributes: ['attributeB']
}
expect(mockSaveLibraryMutation).toBeCalledWith({
variables: {
library: {
id: mockLibrary.id,
attributes: ['attributeB']
}
});
}
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,12 @@ describe('EditPreviewsSettingsModal', () => {
});

test('Can add/delete sizes', async () => {
const mockHandleSubmit = jest.fn();

render(
<EditPreviewsSettingsModal
previewsSetting={{...mockLibraryWithPreviewsSettings.previewsSettings[0], system: false}}
open
onClose={jest.fn()}
onSubmit={mockHandleSubmit}
onSubmit={jest.fn()}
/>
);

Expand All @@ -53,18 +51,17 @@ describe('EditPreviewsSettingsModal', () => {

await userEvent.click(screen.getAllByRole('button', {name: /delete/i})[0]);
await userEvent.click(screen.getByRole('button', {name: /confirm/i}));

expect(screen.getAllByRole('textbox', {name: /size_name/i})).toHaveLength(2);
});

test('If readonly, everything is disabled', async () => {
const mockHandleSubmit = jest.fn();

render(
<EditPreviewsSettingsModal
previewsSetting={{...mockLibraryWithPreviewsSettings.previewsSettings[0], system: true}}
open
onClose={jest.fn()}
onSubmit={mockHandleSubmit}
onSubmit={jest.fn()}
/>
);

Expand Down
22 changes: 10 additions & 12 deletions libs/ui/src/components/LibraryPicker/LibraryPicker.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ describe('LibraryPicker', () => {
const mockHandleSubmit = jest.fn();
render(<LibraryPicker onClose={jest.fn()} onSubmit={mockHandleSubmit} open />, {mocks});

await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());
await waitFor(() => expect(screen.getByText('libA')).toBeInTheDocument());

expect(screen.getByText('libA')).toBeInTheDocument();
expect(screen.getByText('libB')).toBeInTheDocument();
Expand All @@ -91,7 +91,7 @@ describe('LibraryPicker', () => {
const mockHandleSubmit = jest.fn();
render(<LibraryPicker onClose={jest.fn()} onSubmit={mockHandleSubmit} open />, {mocks});

await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());
await waitFor(() => expect(screen.getByText('libA')).toBeInTheDocument());

expect(screen.getByText('libA')).toBeInTheDocument();
expect(screen.getByText('libB')).toBeInTheDocument();
Expand All @@ -109,7 +109,7 @@ describe('LibraryPicker', () => {
const mockHandleSubmit = jest.fn();
render(<LibraryPicker onClose={jest.fn()} onSubmit={mockHandleSubmit} open />, {mocks});

await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());
await waitFor(() => expect(screen.getByText('libA')).toBeInTheDocument());

await userEvent.click(screen.getByText('libA'));

Expand All @@ -120,11 +120,11 @@ describe('LibraryPicker', () => {
const rowLibC = rows[2];

const checkboxLibA = within(rowLibA).getByRole('checkbox');
await waitFor(() => expect(checkboxLibA).toBeChecked());
expect(checkboxLibA).toBeChecked();

// Unselect 'libA'
await userEvent.click(checkboxLibA);
await waitFor(() => expect(checkboxLibA).not.toBeChecked());
expect(checkboxLibA).not.toBeChecked();

// Select "libB" and "libC"
const checkboxLibB = within(rowLibB).getByRole('checkbox');
Expand All @@ -135,16 +135,14 @@ describe('LibraryPicker', () => {

await userEvent.click(screen.getByRole('button', {name: /submit/i}));

await waitFor(() => expect(mockHandleSubmit).toHaveBeenCalledWith([mockLibB, mockLibC]), {
timeout: 10_000
});
expect(mockHandleSubmit).toHaveBeenCalledWith([mockLibB, mockLibC]);
});

test('If not multiple, only one element can be selected', async () => {
const mockHandleSubmit = jest.fn();
render(<LibraryPicker onClose={jest.fn()} onSubmit={mockHandleSubmit} open multiple={false} />, {mocks});

await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());
await waitFor(() => expect(screen.getByText('libA')).toBeInTheDocument());

await userEvent.click(screen.getByText('libA'));
const radioBtnLibA = within(screen.getByRole('row', {name: /libA/i})).getByRole('radio');
Expand All @@ -160,13 +158,13 @@ describe('LibraryPicker', () => {
const mockHandleSubmit = jest.fn();
render(<LibraryPicker onClose={jest.fn()} onSubmit={mockHandleSubmit} open />, {mocks});

await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());
await waitFor(() => expect(screen.getByText('libA')).toBeInTheDocument());

const newLibButton = screen.queryByRole('button', {name: /new_library/i});
expect(newLibButton).toBeInTheDocument();

await userEvent.click(newLibButton);
expect(await screen.findByText('EditLibrary')).toBeInTheDocument();
expect(screen.getByText('EditLibrary')).toBeInTheDocument();
});

test('If not allowed, cannot create new library', async () => {
Expand Down Expand Up @@ -196,7 +194,7 @@ describe('LibraryPicker', () => {
const mockHandleSubmit = jest.fn();
render(<LibraryPicker onClose={jest.fn()} onSubmit={mockHandleSubmit} open />, {mocks: mocksNotAllowed});

await waitFor(() => expect(screen.getByRole('table')).toBeInTheDocument());
await waitFor(() => expect(screen.getByText('libA')).toBeInTheDocument());

expect(screen.queryByRole('button', {name: /new_library/i})).not.toBeInTheDocument();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,11 @@ describe('TreeField', () => {
expect(deleteAllButton).toBeInTheDocument();

// Click on the parent, because of the issue on Tooltip. See DeleteAllValuesBtn component file
userEvent.click(deleteAllButton.parentElement);
await userEvent.click(deleteAllButton.parentElement);

userEvent.click(await screen.findByRole('button', {name: /confirm/}));
await userEvent.click(screen.getByRole('button', {name: /confirm/}));

await waitFor(() => {
expect(baseProps.onDeleteMultipleValues).toBeCalled();
});
expect(baseProps.onDeleteMultipleValues).toBeCalled();
});

test('Can edit linked node', async () => {
Expand All @@ -192,11 +190,9 @@ describe('TreeField', () => {
const valueDetailsButtons = screen.getAllByRole('button', {name: /info/, hidden: true});
expect(valueDetailsButtons).toHaveLength(3); // 1 per value + 1 for the attribute

userEvent.click(valueDetailsButtons[0]);
await userEvent.click(valueDetailsButtons[0]);

await waitFor(() => {
expect(mockEditRecordDispatch).toBeCalled();
});
expect(mockEditRecordDispatch).toBeCalled();
expect(mockEditRecordDispatch.mock.calls[0][0].type).toBe(EditRecordReducerActionsTypes.SET_ACTIVE_VALUE);
});

Expand Down Expand Up @@ -231,19 +227,15 @@ describe('TreeField', () => {

const addValueBtn = screen.getByRole('button', {name: /add/});

userEvent.click(addValueBtn);
await userEvent.click(addValueBtn);

const valuesAddBlock = within(await screen.findByTestId('values-add'));
const valuesAddBlock = within(screen.getByTestId('values-add'));

const elementInList = await waitFor(() => valuesAddBlock.getByText(mockRecordFromList.whoAmI.label));
const elementInList = valuesAddBlock.getByText(mockRecordFromList.whoAmI.label);
expect(elementInList).toBeInTheDocument();

await act(async () => {
userEvent.click(elementInList);
});
await userEvent.click(elementInList);

await waitFor(() => {
expect(mockHandleSubmit).toBeCalled();
});
expect(mockHandleSubmit).toBeCalled();
});
});

0 comments on commit 8b6820b

Please sign in to comment.