0

Every similar question I've looked at doesn't seem to be able to provide the right combination to make the test execution happy. Hoping someone can see what I am missing...

The test code

it('2 checkmarks are checked after clicking on them and unchecked when clicked a 2nd time', async () => {
  const userViewer = userEvent.setup();
  const testComponent = render(<TestContainer />);

  // open accordion item
  const expandAccordionItemControl = testComponent.getByRole('button', { name: /Add groups/i });
  await userViewer.click(expandAccordionItemControl);

  // click on 2 row checkboxes
  let checkedRows = testComponent.queryAllByRole('checkbox', { checked: true });
  expect(checkedRows.length).toBe(0);
  const uncheckedRows = testComponent.getAllByRole('checkbox', { checked: false });
  const checkboxTwo = uncheckedRows[1];
  const checkboxFour = uncheckedRows[3];
  await userViewer.click(checkboxTwo);
  await userViewer.click(checkboxFour);

  // two row checkboxes are checked
  checkedRows = testComponent.queryAllByRole('checkbox', { checked: true });
  expect(checkedRows.length).toBe(2);

  // uncheck checked rows
  // await Promise.all(checkedRows.map((cb) => userViewer.click(cb))); <-------- returns error
  await act(async () => {
    await Promise.all(checkedRows.map((cb) => userViewer.click(cb))); // <--------- tried this but still same error
  });

  // confirm all rows are unchecked
  checkedRows = testComponent.queryAllByRole('checkbox', { checked: true });
  expect(checkedRows.length).toBe(0);
});

enter image description here

For now, my solution is to just hardcode both uncheck clicks...

const checkedBoxTwo = checkedRows[0];
const checkedBoxFour = checkedRows[1];
await userViewer.click(checkedBoxTwo);
await userViewer.click(checkedBoxFour);

but I was really hoping to just let a loop handle this. Anyone have any ideas?

Fiddle Freak
  • 1,923
  • 5
  • 43
  • 83

1 Answers1

1

Since you can't perform these actions in parallel you need to iterate through your checkboxes and wait for each one to be checked before proceeding to the next one.

To be honest it makes sense not to be able to do this in parallel since this is not a real-world scenario and does not simulate a real user and i guess that's the reason your are getting the overlapping act error.

I haven't really tested it but this should work:

  // uncheck checked rows
  for (const checkedRow of checkedRows) {
    await userViewer.click(checkedRow)
  }
fgkolf
  • 910
  • 3
  • 15
  • it works, it's just our linting rules complain about those two lines `// eslint-disable-next-line no-restricted-syntax` and `// eslint-disable-next-line no-await-in-loop`. – Fiddle Freak Nov 16 '22 at 14:20
  • 1
    On a side note, it's interesteing it passes with a `for` loop and not a `.forEach` loop. – Fiddle Freak Nov 16 '22 at 14:26
  • 1
    Indeed, you can read [this answer](https://stackoverflow.com/a/37576787/13168083) along with it's very interesting comments on this matter. – fgkolf Nov 16 '22 at 14:45