chromaui / chromatic-e2e

Archive end-to-end tests to be replayed in Storybook and Chromatic
MIT License
21 stars 4 forks source link

Cypress uses Chrome Devtools Protocol #53

Closed skitterm closed 9 months ago

skitterm commented 9 months ago

What Changed

Cypress now uses Chrome Devtools Protocol (CDP) to archive the requested resources! This enables us to share most of the network-watching code (95%) between Playwright and Cypress.

Previously we were using the client-side cy.intercept(), which plays well with Cypress but would have required us to duplicate our network-watching code (and we'd have to remember to keep bugfixes and features up-to-date in both places).

The approach

Like Playwright, we use the Watcher class to listen to network requests/responses via CDP, and store those on the watcher.archive object. However, we use one watcher instance for the entire test run, instead of one instance per test (we still write the archives to disk at the end of each test). This is because Cypress doesn't give us a way to share the watcher between the "beforeEach" and "afterEach" on the server.

We still take the DOM snapshot on the client, and pass that to the server (where we add the watcher archive and send things off to be written to disk).

The API

Users will now need to add a second command to their cypress.config.js|ts file, as well as the on('before:browser:launch') lifecycle method. In practice, that will look like:

import { defineConfig } from 'cypress';
import { setupNetworkListener, onBeforeBrowserLaunch, saveArchives } from '../src/cypress-api';

export default defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      // implement node event listeners here
      on('task', {
        setupNetworkListener,
        saveArchives,
      });
      on('before:browser:launch', async (browser, launchOptions) => {
        await onBeforeBrowserLaunch(browser, launchOptions);

        return launchOptions;
      });
    },
  },
});

This is in addition to the user importing our client-side before/after hooks in their support.ts file (which they had to do before as well).

Tradeoffs/limitations

How to test

  1. See that the UI tests for Playwright still look the same
  2. Run yarn test:playwright locally and confirm that the tests aren't waiting for the global 10s timeout to finish (making sure they're still using the network-idle-checking)
  3. Observe the UI Tests for Cypress, and make sure they're the same as they were in previous builds when Cypress was using the client-side cy.intercept() for network-watching.

Change Type

📦 Published PR as canary version: 0.0.54--canary.53.8d7bcec.0
:sparkles: Test out this PR locally via: ```bash npm install @chromaui/test-archiver@0.0.54--canary.53.8d7bcec.0 # or yarn add @chromaui/test-archiver@0.0.54--canary.53.8d7bcec.0 ```
skitterm commented 9 months ago

Does that mean each test will take the full 10 seconds to run?

@tevanoff yes, it does. I'm working on a follow-on PR to use network idleness.

skitterm commented 9 months ago

Looks good!

@tevanoff thanks!

Are you planning on holding off on merging this until the network idle PR is ready to go as well?

I'm not planning on waiting to merge for the idle stuff -- since we haven't onboarded people onto Cypress yet, I figure we're free to make changes at will still.

skitterm commented 9 months ago

@tmeasday re-requesting your review as I've updated the on('before:browser:launch)' syntax and wanted to get your thoughts on always using the env variable or not. Seems we could wait on the latter change in a follow-up PR if needed.

thafryer commented 9 months ago

:rocket: PR was released in v0.0.54 :rocket:

skitterm commented 9 months ago

@tevanoff PR #54 (just submitted) gets Cypress tests faster again (instead of waiting the global 10 seconds after each test).