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

Properly load rrweb-snapshot on AMD-based web pages #210

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

andrewortwein
Copy link
Contributor

@andrewortwein andrewortwein commented Nov 20, 2024

Issue: #AP-5218

What Changed

Any tests using @chromatic-com/playwright error if the page being tested loads modules using the AMD API (requirejs) and is running in Chrome. This change detects AMD and properly loads our fork of rrweb-snapshot so that we can take a snapshot of the page.

As part of this PR, I first added a new AMD-based page and then created a Playwright test to take a snapshot of that page. Before implementing the fix, the test failed in exactly the same way that the customer's tests are failing.

Background

We currently use rrweb-snapshot v2.0.0-alpha.17. They made some big changes from v2.0.0-alpha.14 and v2.0.0-alpha.15. Among those changes was how modules were being exported. Something about the older way they did this worked fine, but the newer version does not. This issue might be related: rrweb-io/rrweb#1592.

How to test

  1. Run the tests
  2. Extra credit: Create a new Playwright project with a test that points to http://cookbook.tools.bbc.co.uk/ and verify that it is captured correctly

@andrewortwein andrewortwein changed the title Andrew/ap-5218-tweak-version-of-rrweb-used-by-chromatic-by-default Properly load rrweb-snapshot on AMD-based web pages Nov 20, 2024
Copy link

codacy-production bot commented Nov 20, 2024

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
+0.00% (target: -1.00%) (target: 80.00%)
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (a2a8f09) 308 294 95.45%
Head commit (f78e3ce) 308 (+0) 294 (+0) 95.45% (+0.00%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#210) 0 0 ∅ (not applicable)

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

Codacy stopped sending the deprecated coverage status on June 5th, 2024. Learn more

Copy link
Member

@skitterm skitterm left a comment

Choose a reason for hiding this comment

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

A couple small things, otherwise looks good. Nice work sleuthing on this, turns out it was on our side, and nice fix as well!

@@ -35,7 +35,15 @@ async function takeSnapshot(
// Serialize and capture the DOM
const domSnapshot: elementNode = await page.evaluate(dedent`
${rrweb};
rrwebSnapshot.snapshot(document);
if (typeof define === "function" && define.amd) {
new Promise((resolve) => {
Copy link
Member

Choose a reason for hiding this comment

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

One small thing -- is there a reason we're wrapping this in a Promise here? Since we're not awaiting the results of the promise.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't quite understand why, but this doesn't work if I remove the Promise

Copy link
Member

Choose a reason for hiding this comment

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

Maybe playwright is waiting on the promise somehow? Maybe we should return new Promise... just to make that 100% clear.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The return is implicit. See https://playwright.dev/docs/api/class-page#page-evaluate. I find it a bit confusing, but that seems to be how it functions. Just to be sure, I tried adding return in front of new Promise and it errored with Error: page.evaluate: SyntaxError: Illegal return statement.

Copy link
Member

@tmeasday tmeasday Nov 25, 2024

Choose a reason for hiding this comment

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

I don't see how if (x) { y } else { z } evaluates to anything, but clearly it does somehow (I assume we use the return value domSnapshot still right?).

Maybe there is some way to wrap this in a function (so you can return) to make it less confusing? Otherwise I'd be in favour of a ternary (x ? y : z) to make it less weird.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added additional comments to hopefully point out the odd behavior that page.evaluate displays, along with a link to Playwright doc. I'd like to avoid using a ternary since it's possible we might have other scenarios to account for in the future.

packages/playwright/src/takeSnapshot.ts Show resolved Hide resolved
@@ -35,7 +35,15 @@ async function takeSnapshot(
// Serialize and capture the DOM
const domSnapshot: elementNode = await page.evaluate(dedent`
${rrweb};
rrwebSnapshot.snapshot(document);
if (typeof define === "function" && define.amd) {
new Promise((resolve) => {
Copy link
Member

@tmeasday tmeasday Nov 25, 2024

Choose a reason for hiding this comment

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

I don't see how if (x) { y } else { z } evaluates to anything, but clearly it does somehow (I assume we use the return value domSnapshot still right?).

Maybe there is some way to wrap this in a function (so you can return) to make it less confusing? Otherwise I'd be in favour of a ternary (x ? y : z) to make it less weird.

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

Successfully merging this pull request may close these issues.

3 participants