axe-core icon indicating copy to clipboard operation
axe-core copied to clipboard

Testing iframes with Playwright/axe-core

Open zuzanna-maria opened this issue 1 year ago • 5 comments

Product

axe-core

Product Version

No response

Latest Version

  • [X] I have tested the issue with the latest version of the product

Issue Description

Expectation

I am working on accessibility testing with Playwright and @axe-core, following the instructions here. My page contains iframes and I would like to scan and analyze the content inside them.

Actual

When scanning the page object as per the instructions, the incomplete property of the accessibilityScanResults object contains this:

    {
      id: 'frame-tested',
      impact: 'critical',
      tags: [Array],
      description: 'Ensures <iframe> and <frame> elements contain the axe-core script',
      help: 'Frames should be tested with axe-core',
      helpUrl: 'https://dequeuniversity.com/rules/axe/4.9/frame-tested?application=playwright',
      nodes: [Array]
    }

The link provided under the helpUrl property says to "Ensure iframe and frame elements contain the axe-core script" but doesn't provide an example of how to achieve that.

How to Reproduce

When testing a page containing an iframe with code provided in the documentation:

const accessibilityScanResults = await new AxeBuilder({ page }).analyze()

the above issue occurs. it does not occur on pages without iframes. It happens even when trying to explicitly include the iframe as per the documentation:

const accessibilityScanResults = await new AxeBuilder({ page }).include('#sbox-iframe').analyze()

Additional context

Any thing else we should know about the issue?

zuzanna-maria avatar Jul 02 '24 15:07 zuzanna-maria

Thanks for the issue. Unfortunately there are serval reason why an iframe wouldn't be tested. If for some reason axe was prevented from loading into the iframe (for example due to CORS), if the iframe was not fully loaded or even lazy loaded (loading="lazy" and thus not loaded into view when the page loads), or if the iframe threw a JavaScript error during the axe.run execution. Without seeing the actual page it's hard to say what the issue is exactly.

You could try adding a wait to the script just to see if allowing the page more time to load fixes the issue.

import { timeout } from 'node:timers/promises'

await page.goto('https://your-site.com/')
await setTimeout(5000)
const accessibilityScanResults = await new AxeBuilder({ page }).analyze()

straker avatar Jul 02 '24 20:07 straker

Thanks for your reply! I am trying to analyze https://cryptpad.fr/code. It is indeed likely the injection is being blocked by security measures. Could you clarify what kind of injection is being performed by axe-core, as the documentation seems to lack detail on this?

zuzanna-maria avatar Jul 03 '24 11:07 zuzanna-maria

I am getting the same issue for an iFrame in a Salesforce application while using the @axe-core/playwright package. Is there a way to determine if the script isn't being loaded due to CORS?

Billy-Stroud avatar Jul 11 '24 17:07 Billy-Stroud

@Billy-Stroud Unfortunately at the moment there isn't a way to get at this information. We're in discussions to see if we could expose the actual error, but it won't be any time soon.

As a way to see what's going on, I have this custom script I use to inject axe into each frame on the page. You could try running it on the pages in question and hopefully see the same type of error that @axe-core/playwright would be running into.

function inject(doc) {
  const script = doc.createElement('script');
  script.src = 'https://unpkg.com/axe-core@latest';
  doc.body.appendChild(script);

  doc.querySelectorAll('iframe, frame').forEach(frame => {
    frame.contentDocument && inject(frame.contentDocument)
  });
}

inject(document)

straker avatar Jul 12 '24 15:07 straker

@straker Thank you! That allowed me to see the CORS error. It would definitely be helpful to expose these errors in the future.

Billy-Stroud avatar Jul 12 '24 18:07 Billy-Stroud