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

chore: use playwright/test for integration tests #1394

Merged
merged 46 commits into from Feb 19, 2023
Merged

Conversation

kettanaito
Copy link
Member

@kettanaito kettanaito commented Sep 7, 2022

Changes

  • Adds and configures @playwright/test for integration tests instead of page-with.
  • Improves the stability of the integration tests.

Roadmap

  • Fix failing src/utils/handleRequest.test.ts:251:30
  • Migrate the rest of the tests
    • rest-api
    • graphql-api
    • msw-api
  • Add .use() support to @open-draft/test-server for runtime middleware
  • Rewrite existing tests to always use HttpServer from test-server
  • Consider if spawning API server per test would be a better idea
  • Adjust the test:integration script to use playwright
  • Fix the failing 9 tests
  • Split the browser and node integration tests (incl. CI)
  • Account for new tests from fix: remove duplicate response logging in the browser console #1418
  • Resolve leaking state in tests
  • Update CONTRIBUTING.md guidelines on how to run --debug mode in PW
  • Fix all test.skip() and test.fixme()
  • Configure CI to upload Playwright test output artifacts for better debugging (although videos and screenshots are of little use, given most of the things happen in Network/Console). It'd be much better to export each failed test's Network into an HAR file and attach that to the failed run.

Resources

  • webpack-http-server. As a part of this change, I'm decoupling the runtime compilation capabilities of page-with into a standalone package.

@kettanaito kettanaito marked this pull request as draft September 7, 2022 16:01
test/playwright.config.ts Outdated Show resolved Hide resolved
@codesandbox-ci
Copy link

codesandbox-ci bot commented Sep 7, 2022

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit a71acf7:

Sandbox Source
MSW React Configuration

async fetch({ page }, use) {
await use(async (url) => {
page.evaluate((url) => fetch(url), url)
return page.waitForResponse(url)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discovery: page.request vs page.evaluate(fetch)

PW comes with a built-in page.request utility but requests it makes bypass the network. I believe that's intentional in order for PW to spy on requests you make. Since we need requests to actually happen to hit the service worker, I'm adding a custom fetch fixture.

test/tsconfig.json Outdated Show resolved Hide resolved
@kettanaito kettanaito added the chore Tasks aimed at internal improvement label Sep 21, 2022
@kettanaito kettanaito self-assigned this Sep 21, 2022
@kettanaito
Copy link
Member Author

@shwarcu, so I've tried spawning the webpack server once but the issue is that the tests need a reference to that server. It's used to perform compilations (server.compile()) and also to modify compilation's behavior on the test's runtime, such as appending new routes, overriding what gets served as the worker script, etc.

There doesn't seem to be a way to create server once and then expose it to tests. Playwright's configs run in a separate process, and I've come to believe that even tests are isolated as I cannot use a singleton pattern—the value of persisted server is always undefined across tests.

I think I can technically split the compilation server and the preview server so that we use a single compilation server to save up resources but spawn a new preview server for each test but that's an overkill given that the compilation server already does a great job at scoping compilations and serving them like a preview (its entire point).

Do you happen to know if we can achieve what I've described above?

@kettanaito
Copy link
Member Author

What I decided to do in the end is to spawn 1 compilation server per 1 worker. I approached it this way: tests are completely isolated within the worker process so there's no way to have a shared state between workers. Within a single worker, however, I will establish a single compilation server to save resources.

I've given this a quick test and can confirm that this setup works. Now testing the flakiness...

@kettanaito
Copy link
Member Author

Sadly, even after rewriting the Worker console logic and ensuring the webpack server is scoped per worker, the tests are still flaky, timing out on the "context" error. Huh.

@shwarcu, what do you think we could look at as the next step?

@shwarcu
Copy link
Contributor

shwarcu commented Feb 7, 2023

Hi @kettanaito 👋 I need more time for 'decompression' after work and I won't be looking at the code today and tomorrow. But I will continue my engagement in this topic and I will get back to you once I have something valuable to say (probably closer to Saturday/Sunday)

@kettanaito
Copy link
Member Author

Absolutely no worries! Please make sure to reset properly. Work can be daunting but a good chunk of rest does wonders. See you around!

@kettanaito
Copy link
Member Author

kettanaito commented Feb 9, 2023

I went and improved a bit on how we handle runtime compilations. I've added the ability to dispose of the compilation once the test settles so they don't take memory anymore:

  • Kill the underlying webpack compiler;
  • Remove any in-memory records of the compilation that webpack-http-server keeps internally.

I don't know if that helped or not but I've got the first CI passing since forever. Will retry it to confirm...

The tests do seem more reliable now. I had 4 runs, 3 succeeded, but the 4th one failed with:

  1) [chromium]  msw-api/setup-worker/scenarios/iframe/iframe.test.ts:40:5  intercepts a request from a deeply nested iframe 
error Command failed with exit code 1.

    Test timeout of 10000ms exceeded.

    frame.waitForSelector: Target closed
    =========================== logs ===========================
    waiting for locator('#first-name') to be visible
    ============================================================

      57 |
      58 |   await deepFrame.evaluate(() => window.request())
    > 59 |   const firstNameElement = await deepFrame.waitForSelector('#first-name')
         |                                            ^
      60 |   const firstName = await firstNameElement.evaluate((node) => node.textContent)
      61 |
      62 |   expect(firstName).toBe('John')

        at /Users/runner/work/msw/msw/test/browser/msw-api/setup-worker/scenarios/iframe/iframe.test.ts:59:44

These iframe tests are dependent on file system, so I suspect there's an issue where two tests try to write to the same directory (although it should be impossible now given the dir name is based on the worker id + directory name).

Well, at least it seems that disposing of webpack instances helped with the other tests.

@kettanaito
Copy link
Member Author

As the next step, I've skipped the iframe tests to verify whether they are the only ones left failing. Will re-run the CI multiple times to confirm that.

@kettanaito
Copy link
Member Author

Alas, the tests are still flaky so I moved on with adding some additional debugging to them. Now each failed test will flush its runtime console state to a log file and upload it as an artifact to the CI. This should help us debug flaky tests since screenshots and videos are pretty much useless given the way we write things in the console primarily.

@kettanaito kettanaito mentioned this pull request Feb 13, 2023
34 tasks
@kettanaito
Copy link
Member Author

So based on https://github.com/mswjs/msw/actions/runs/4148868358, which has failing tests with no logs whatsoever, I suspect the issue is in asynchronicity/servers/etc. Quite a pickle then, I was hoping for some browser-side reporting to help but it looks like I need to dive into why PW/webpack server has trouble doing what it's designed to do.

@kettanaito kettanaito marked this pull request as ready for review February 18, 2023 21:55
@kettanaito kettanaito merged commit 1df33a3 into main Feb 19, 2023
@kettanaito kettanaito deleted the chore/playwright-test branch February 19, 2023 18:43
@kettanaito kettanaito mentioned this pull request Feb 20, 2023
1 task
@kettanaito
Copy link
Member Author

Released: v1.1.0 🎉

This has been released in v1.1.0!

Make sure to always update to the latest version (npm i msw@latest) to get the newest features and bug fixes.


Predictable release automation by @ossjs/release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
chore Tasks aimed at internal improvement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Migrate to "@playwright/test"
2 participants