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

Working with elements inside an iframe

Open BurovnikovEvgeniy opened this issue 1 year ago • 2 comments

Product

axe-core

Question

Hello, I'm trying to check the element(s) that are inside the iframe, but I don't understand how to do it normally. I keep catching the error no such element: element not found (Session info: chrome=127.0.6533.120).

What is there? There is a page where the DOM tree looks something like this:

<div id="pmntWzrdCtr"....>
<iframe class="modal-new_payment-frame" ....>
#document(...)
   <head></ head>
   <body>
      <div id="hook_Block_SendBlock" class="hookBlock">...</div>
   </ body>
</iframe>
</div>

This is a rough outline of the page code, I tried to omit all the details, but left the structure

I tried to work with an iframe like this:

WebDriver driver = getWebDriver().switchTo().frame(getWebDriver().findElement(By.cssSelector("#pmntWzrdCtr iframe")));
getA11Y().testA11Y(driver, $(By.cssSelector("#hook_Block_SendBlock")));

In getA11Y I configure the operation of axe

axeBuilder = new AxeBuilder().setLegacyMode();
axeBuilder.withTags(Arrays.asList("wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "best-practice", "cat.structure", "review-item"));
axeBuilder.disableRules(Arrays.asList(...));

And in the testA11Y function, I run the analysis

Results axeResults = axeBuilder.analyze(driver, selenideElement);
List<Rule> rules = axeResults.getViolations();

I tried to run the analysis in various ways, including using include, but it didn't help https://dequeuniversity.com/rules/axe/4.9/frame-tested?application=axeAPI https://github.com/dequelabs/axe-core-maven-html/blob/develop/playwright/README.md#limit-frame-testing

Unfortunately, all this did not help me achieve the desired goal, in general, there are quite a few (as it seems to me) examples in the documentation, which raises questions

(com.deque.html.axe-core:selenium:4.9.1)

BurovnikovEvgeniy avatar Aug 22 '24 00:08 BurovnikovEvgeniy

Hey @BurovnikovEvgeniy!

We're looking into it and will respond shortly

Zidious avatar Aug 23 '24 16:08 Zidious

The error you're getting: error no such element: element not found appears to be coming from Selenium not axe-core-maven-html-selenium package. Using the fromFrames API (docs) you can limit the testing scope to elements within your iframe. Below I have an example page that has an iframe element and a class attribute (similar to your snippet called modal-new_payment-frame) that loads some content.

main.html -

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Top-level</title>
</head>
<body>
    <h1>Top level page</h1>

    <iframe class="modal-new_payment-frame" src="iframe.html"></iframe>

</body>
</html>

iframe.html -

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My iframe</title>
</head>
<body>
    <h1>My Iframe Page</h1>

    <div id="hook_Block_SendBlock">
        <button></button>
        <img />
    </div>

</body>
</html>

To limit testing to the saidiframe and everything with the div that has an id of hook_Block_SendBlock you can do:

WebDriver webDriver = new ChromeDriver();

webDriver.get("<url>");

// Limit testing to everything with the `hook_Block_SendBlock` div within the `.modal-new_payment-frame` iframe:
AxeBuilder axeBuilder =
    new AxeBuilder().include(new FromFrames(".modal-new_payment-frame", "#hook_Block_SendBlock"));
List<Rule> results = axeBuilder.analyze(webDriver).getViolations();

for (Rule rule : results) {
  System.out.println(rule.getId());
  System.out.println(rule.getDescription());
}

webDriver.quit();

Zidious avatar Aug 23 '24 16:08 Zidious

@Zidious Do I understand correctly that we should just pass the basic element of the frame to axe and it will scan it completely (all elements) according to its own rules? For your example, I call the base element of the frame

BurovnikovEvgeniy avatar Oct 22 '24 11:10 BurovnikovEvgeniy

Yes, if you want to only run within a child element within the iframe then you can use the FromFrames method. You pass in the iframe you want to test against then the child element you want to scope testing to for example: FromFrames(".my-iframe", ".my-child-iframe-div")

Zidious avatar Oct 22 '24 13:10 Zidious

Yes, if you want to only run within a child element within the iframe then you can use the FromFrames method. You pass in the iframe you want to test against then the child element you want to scope testing to for example: FromFrames(".my-iframe", ".my-child-iframe-div")

I understand you! Thank you very much

BurovnikovEvgeniy avatar Oct 22 '24 13:10 BurovnikovEvgeniy