Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Playwright-MSW Fails when a request that has been cloned is passed to fetch #64

Open
jcannon98188 opened this issue Mar 29, 2023 · 4 comments

Comments

@jcannon98188
Copy link

Ran into this issue where playwright-msw will fail when a Request object that has been cloned is passed to fetch.

I ran into this issue when using playwright-msw alongside the rtk-query library, which creates a Request object, then clones it, and then passes the original request object to fetch. Example of that happening in their source code here

Both in my actual application, as well as the minimum reproduction that I have linked below, these requests are handled just fine by msw when ran on its own. The issue only appears when using playwright-msw to run the msw.

From my investigation into this issue, I suspect the issue is occuring as part of the handler.ts file in playwright-msw source link. When I was investigating this as part of my actual application I am working on, I found that request.postData was returning null.

Minimum reproduction of this issue can be found at a repo here

Relevant files are:

src/App.tsx
src/mocks/handlers.ts
tests/example.spec.ts

@jcannon98188
Copy link
Author

Not directly related to this issue, but in case anyone comes across this issue before it is fixed, and uses RTK-Query here is the workaround that allowed me to get the libraries to play nice with eachother

const playwrightMSWCompatibleFetch = async (input: RequestInfo, _init: RequestInit) => {
    if (typeof input === 'string') return await fetch(input);
    const request = input as Request;
    let body: string;
    if (request.body !== null) {
        body = await request.text();
    }
    let requestOptions: RequestInit = {
        method: request.method,
        headers: request.headers,
        credentials: request.credentials,
    };
    if (body !== undefined) {
        requestOptions.body = body;
    }
    return await fetch(request.url, requestOptions);
};

export const emptySplitApi = createApi({
    baseQuery: fetchBaseQuery({
            baseUrl: '/',
            fetchFn: playwrightMSWCompatibleFetch,
        }),
    endpoints: () => ({}),
});

@samanthaandrews
Copy link

I am experiencing this issue as well. playwright-msw is not intercepting requests if they have already been handled by the base handlers. I am trying to overwrite mocked requests in specific tests to throw errors, and those requests are not being handled by playwright-msw.

@jcannon98188
Copy link
Author

I'm not sure if that is the same issue @samanthaandrews however I have experienced similar things as well. Usually it's caused by your playwright test being finished before the network call actually finishing. If you post your test that's failing up I can see if I can figure it out for you, but no guarantees.

@Toxiapo
Copy link

Toxiapo commented Jun 20, 2023

Hi @jcannon98188 ,
@samanthaandrews and I are both working on the same bug, I can help with providing the failed test that showcases the problem.

This is the test that's failing.

  test.only("Returning book fails", async ({ page, worker }) => {
    await worker.use(
      rest.get(ALMOST_MIDNIGHT_REVOKE_URL, async (_req, res, _ctx) => {
        return res(
          problemDocument(500, "Something went wrong", "Error message")
        );
      })
    );

    await page.goto(ALMOST_MIDNIGHT_DETTAIL_PAGE_URL);

    const downloadButton = await page.getByRole("button", { name: "Download" });
    await expect(downloadButton).toBeVisible();

    await downloadButton.click();

    // shows the progress bar
    await expect(page.getByText("Downloading")).toBeVisible();

    const returnButton = await page.getByRole("button", { name: "Return" });
    const readButton = await page.getByRole("button", {
      name: "Read",
      exact: true
    });

    await expect(returnButton).toBeVisible();
    await expect(readButton).toBeVisible();

    await returnButton.click();

    const confirmBtn = await page.getByRole("button", { name: "Return" });
    await expect(confirmBtn).toBeVisible();
// After this action, the request should fail, but looking at the console,
// it's returning the good response set in the base handler file
    await confirmBtn.click();

    const alertBox = await page.locator(".alert-wrapper");
    await expect(alertBox).toHaveCount(1);
  });

This is the base handler.

  rest.get(ALMOST_MIDNIGHT_REVOKE_URL, (_req, res, ctx) => {
    return res(ctx.xml(bookAlmostMidnightInvoked));
  }),

await confirmBtn.click(); should execute the request and fail, but it returned a good response from the base.

Please let me know if you need more information. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants