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

[Feature] Mocking API requests for MSW #23277

Closed
lisaweilguni opened this issue May 25, 2023 · 6 comments
Closed

[Feature] Mocking API requests for MSW #23277

lisaweilguni opened this issue May 25, 2023 · 6 comments

Comments

@lisaweilguni
Copy link

lisaweilguni commented May 25, 2023

Context

Playwright Version: 1.33.0
Operating System: OS X
Node.js version: 16.20.0
MSW version: 1.2.1

We are currently migrating the E2E test suite of a React Native app from Cypress to Playwright. Both Playwright and msw work perfectly for us. We use MSW also in combination with our Jest test suite, as well as for local manual testing. We would like to intercept and mock network requests that are performed by browsers during Playwright tests. In Cypress we managed to achieve it like this:

    cy.window().then((window) => {
      const {worker, rest} = window.msw;
      worker.use(
        rest.post(`*${api.customName}`, (_, res, ctx) => {
          const response = cloneDeep(responses.customName);
          response.days = 5;

          return res(ctx.status(200), ctx.json(response));
        }),
      );
    });

Problem

We tried to achieve the same behavior in Playwright tests, but have not been successful yet.

What we tried

  1. Use build-in modification of API responses (then realized that this build-in feature might not work for msw)
    await page.route(`*/api/${api.statistics}`, async (route) => {
      const response = await route.fetch();
      const json = await response.json();
      json.days = 5;

      await route.fulfill({response, json});
    });
  1. Add option serviceWorkers: allow in config
  2. Try using Experimental Service Worker Network Events (unsuccessful)
  3. Try msw-playwright package, but the requests do not seem to get intercepted. The browser returns the original response that is defined in our msw environment (handlers.ts).

What could be the cause of the problem? What's the best way to intercept API requests in Playwright tests using MSW? Thanks in advance for your help!

@weyert
Copy link

weyert commented May 26, 2023

Did you try all browsers? I know Chromium has issues with intercepting things. Works better in Firefox. I have a subset of tests that run in this browser I can check some analytics events are getting send to PostHog

maybe related to #6479?

@mxschmitt
Copy link
Member

What's the best way to intercept API requests in Playwright tests

We usually recommend using Playwright's network mocking rather than relying on a third-party library.
https://playwright.dev/docs/network

And then you can do route.fulfill which is able to mock network requests from the page, we also recommend blocking service workers for it.

Why would that not work in your use-case?

@sand4rt
Copy link
Collaborator

sand4rt commented May 30, 2023

I ran into this as well.

I think the downside of the current HTTP mocking solution is that the Playwright mocks are not reusable for both local development and testing.

With MSW it is possible to develop the frontend against the mock server without relying on a backend. In addition, it is also possible to reuse the MSW mocks in a shared NPM package.

@lisaweilguni
Copy link
Author

lisaweilguni commented May 31, 2023

Thanks for taking the time to look into this and your suggestions @weyert @sand4rt @mxschmitt!

We use MSW also in combination with our Jest test suite, as well as for local manual testing. That's why using the native Playwright intercepts is not suitable for us as we would need to duplicate our entire mock server. We are currently running all our tests for our mock server (MSW) and would prefer to continue to do so.

We tested all browsers, but the request coming from MSW does not get intercepted in either of them. We would, of course, prefer to use Playwright's network mocking instead of a third-party library. It would be great if there was a way to enable intercepting API requests coming from MSW (just as in Cypress).

test('Correct number of days gets displayed', async ({page}) => {
    const response = cloneDeep(responses.statistics);
    response.days = 5;

    await page.route(`*/api/${api.statistics}`, (route) =>
      route.fulfill({
        status: 200,
        body: JSON.stringify(response),
      }),
    );

    await page.goto('/dashboard');

    await expect(page.getByText('5')).toBeVisible();
  });

@mxschmitt
Copy link
Member

The Playwright team is unfortunately not familiar with this package, so I think its better to ask for help in their bug tracker: https://github.com/valendres/playwright-msw

Closing it by that, thanks for your understanding!

@weblancaster
Copy link

@mxschmitt it seems this was discussed previously and even some work was done to accommodate MSW but still not a straightforward solution. It's unfortunate that the use of such popular lib like MSW is not documented in Playwright.

That said, for anyone else landing here, there are a few issues (mswjs/msw#1322, #1090) people are discussing possible solutions. Would be nice to have it documented in PW because many people are using MSW as the mocking strategy for local development and testing.

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

5 participants