percy / cli

The Percy CLI is used to interact with, and upload snapshots to, percy.io via the command line.
https://docs.percy.io/docs/cli-overview
70 stars 43 forks source link

Support websites with CSP truested-types #1163

Closed bjarketrux closed 1 year ago

bjarketrux commented 1 year ago

The problem

Running percy against a site that has CSP trusted-types enabled fails.

Environment

Details

The website that the CSP header set (in this case an Angular SPA):

content-security-policy: ... ;require-trusted-types-for 'script';trusted-types angular angular#bundler angular#unsafe-bypass

Workaround is to remove trusted types or use Firefox (as it does not support trusted-types yet.

Debug logs

[percy] Percy has started!
[percy] Running "node simple.js"
[percy] Could not take DOM snapshot "MyTitle"
[percy] Error: page.evaluate: TypeError: Failed to set the 'innerHTML' property on 'Element': This document requires 'TrustedHTML' assignment.
    at serializeCSSOM (eval at evaluate (:197:30), <anonymous>:151:27)
    at Object.serializeDOM (eval at evaluate (:197:30), <anonymous>:307:9)
    at eval (eval at evaluate (:197:30), <anonymous>:3:23)
    at UtilityScript.evaluate (<anonymous>:199:17)
    at UtilityScript.<anonymous> (<anonymous>:1:44)

Code to reproduce issue

const { chromium } = require('playwright');
const percySnapshot = require('@percy/playwright');

(async () => {
  const browser = await chromium.launch({
    headless: false,
  });

  const page = await browser.newPage();
  await page.goto('https://localhost:44440/', { waitUntil: 'networkidle' });
  await percySnapshot(page, 'MyTitle');
  await browser.close();
})();
itsjwala commented 1 year ago

Hey @bjarketrux 👋

@percy/dom package runs on the client's test browser when percySnapshot is called, it requires the server which is serving the document to not send the CSP header for it to able to run.

you can verify it by doing the following

Expand 1. start Percy's local server ```shell npx percy exec:start --debug ``` 2. Runs `@percy/dom` package ```js eval(await (await fetch('http://localhost:5338/percy/dom.js')).text()) PercyDom.serialize() ```

The support for this would need to be built on the user's end by either having a proxy that drops the CSP header or whitelisting for it to run E2E

bjarketrux commented 1 year ago

Okay so the conclusion is wont-fix and with the following options as work around:

You mention whitelisting. Does percy has a trusted type policy name we can use?

itsjwala commented 1 year ago

You mention whitelisting. Does percy has a trusted type policy name we can use?

nothing that I could think of for trusted type, but say for connect-src e.t.c we may use localhost:5338