How to assert element before request returns?

92 Views Asked by At

Using Angular and Playwright

I have 2 buttons... delete mode button and refresh button. When the user refreshes the button, I have the delete mode button disabled. When the request comes back, I re enable the delete mode button.

How can I write a test to where I hit the refresh button, I can assert the delete mode button is disabled before the request (which is mocked) is returned?

I have the below but the assertion always passes even if I add a .not to try and fail it (false positive).

it('should disable delete button during refresh', async ({ page }) => {
  const deleteBtn = page.getByRole('button', {name: 'enter delete mode'}).first();
  page.on('request', () => { expect(deleteBtn).toBeDisabled() }) // false positive
  await page.getByText('REFRESH', { exact: true}).click();
});
1

There are 1 best solutions below

0
On BEST ANSWER

You can intercept the network request and mock its response, ensuring that there is a guaranteed window to catch the button in the state where it's supposed to be disabled. Mocking also helps connect the assertion happening in the callback with the main line promise chain in the test case so that the test doesn't end before the assertion has a chance to run.

Here's a minimal, complete and verifiable example:

import {expect, test} from "@playwright/test"; // ^1.39.0

const html = `<!DOCTYPE html>
<html>
<body>
<button>enter delete mode</button>
<button>REFRESH</button>
<script>
const [deleteModeBtn, refreshBtn] = document.querySelectorAll("button");
refreshBtn.addEventListener("click", e => {
  deleteModeBtn.setAttribute("disabled", true);
  fetch("https://jsonplaceholder.typicode.com/users")
    .finally(() => {
      deleteModeBtn.removeAttribute("disabled");
    });
});
</script>
</body>
</html>`;

test("button is disabled during the request", async ({page}) => {
  await page.setContent(html);
  const btn = page.getByRole("button", {name: "enter delete mode"});
  await page.route("*/**/users", async route => {
    await expect(btn).toBeDisabled();
    await route.fulfill({});
  });
  await expect(btn).toBeEnabled();
  await page.getByText("REFRESH", {exact: true}).click();
  await expect(btn).toBeEnabled();
});

To ensure this test actually validates the button being disabled when the request is in flight, comment out btn.setAttribute("disabled", true) or btn.removeAttribute("disabled") and the test will fail.