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

[BUG] position of elements inside Chromium cross origin iframe seems wrong #3170

Closed
joost2076 opened this issue Jul 26, 2020 · 3 comments
Closed

Comments

@joost2076
Copy link

Context:

  • Playwright Version: 1.2.1
  • Operating System: ubuntu 20.04
  • Node version: 10.19
  • Browser: Chromium

Code Snippet

<!-- running at localhost:8000 -->
<body>
    <div style="position:fixed;top:300px;left:300px;width:400px;height:400px;">
        <iframe src="https://en.wikipedia.org/"  width="100%" height="100%" > </iframe>    
    </div>
</body>
const playwright = require('playwright');

(async () => {
  const browser = await playwright.chromium.launch({headless:false });
  const context = await browser.newContext({viewport:{width:1920, height:1080}}); 
  const page = await context.newPage();

  await page.goto('http://localhost:8000');
  const frame = page.frames()[1]
  const button = await frame.$('#pt-login')
  await button.click()

  await browser.close();
})();

The bug
Chromium does not succeed in clicking the login button.
The position of elements inside a cross-origin iframe seem to be calculated without taking the offset of the iframe into account.
The offset of the iframe is set to top-left 300,300. Playwright tries to click 275.74, 37.18

checking that element receives pointer events at (275.74,37.18)

Serving some other content from localhost inside the iframe in chromium does take the offset into account and works as expected.
(Firefox works fine. Have not tried webkit)

rwoll added a commit to rwoll/playwright that referenced this issue Jul 27, 2020
This changeset adds two tests aimed at repoducing microsoft#3170 where a link
in a cross-domain iframe fails to get clicked even though the element is
found.

In addition to the cross-domain test, we add a `srcdoc` test to baseline
the source of failing behavior.

In the matrix of {Firefox, Chomium, Webkit } X { srcdoc, cross-domain} X
{ Headfull, Headless }, only the Chromium Headfull test with
cross-domain iframe fails.

Notably, it fails while logging the same message as reported in the
original issue:

```
pw:api retrying click action [] +0ms
pw:api   waiting for element to be visible, enabled and not moving [] +0ms
pw:api   element is visible, enabled and does not move [] +25ms
pw:api   scrolling into view if needed [] +0ms
pw:api   done scrolling [] +1ms
pw:api   checking that element receives pointer events at (35.32,17) [] +1ms
pw:api   element does not receive pointer events []
…
```
rwoll added a commit to rwoll/playwright that referenced this issue Jul 27, 2020
This changeset adds two tests aimed at reproducing microsoft#3170 where a link
in a cross-domain iframe fails to get clicked even though the element is
found.

In addition to the cross-domain test, we add a `srcdoc` test to baseline
the source of failing behavior.

In the matrix of {Firefox, Chromium, Webkit } X { srcdoc, cross-domain } X
{ Headfull, Headless }, only the Chromium Headfull test with
cross-domain iframe fails.

Notably, it fails while logging the same message as reported in the
original issue:

```
pw:api retrying click action [] +0ms
pw:api   waiting for element to be visible, enabled and not moving [] +0ms
pw:api   element is visible, enabled and does not move [] +25ms
pw:api   scrolling into view if needed [] +0ms
pw:api   done scrolling [] +1ms
pw:api   checking that element receives pointer events at (35.32,17) [] +1ms
pw:api   element does not receive pointer events []
…
```
rwoll added a commit to rwoll/playwright that referenced this issue Jul 27, 2020
This changeset adds two tests aimed at reproducing microsoft#3170 where a link
in a cross-domain iframe fails to get clicked even though the element is
found.

In addition to the cross-domain test, we add a `srcdoc` test to baseline
the source of failing behavior.

In the matrix of {Firefox, Chromium, Webkit } X { srcdoc, cross-domain } X
{ Headfull, Headless }, only the Chromium Headfull test with
cross-domain iframe fails.

Notably, it fails while logging the same message as reported in the
original issue:

```
pw:api retrying click action [] +0ms
pw:api   waiting for element to be visible, enabled and not moving [] +0ms
pw:api   element is visible, enabled and does not move [] +25ms
pw:api   scrolling into view if needed [] +0ms
pw:api   done scrolling [] +1ms
pw:api   checking that element receives pointer events at (35.32,17) [] +1ms
pw:api   element does not receive pointer events []
…
```
@rwoll
Copy link
Member

rwoll commented Jul 27, 2020

I added #3172 thinking it would cover the case reported here. However, while I get the same error message, the failure matrix doesn't match the failure matrix for the exact scenario from @joost2076 which I've repro'd (and then further tested across all browsers with the attached script). Firefox (headless and headfull) is the only browser where the click works and navigates to the login page. Chromium headfull fails in the exact way @joost2076 reported (i.e. while awaiting the click). The other combinations report a successful click (i.e. we get past the await) but don't actually navigate to the log in page.

If you remove the style from the div, the results remain unchanged except you get a headfull chrome click (but still no navigation).

Aside: If you perform this test manually in the production version of Firefox (78.0.2), the navigation to the Wikipedia login page will be blocked due to X-Frame-Options: DENY. The iframe will load on localhost, but clicking login will get you a notice.


Raw Test Output:

CHROMIUM [HEADLESS=true]
----------------
✅: Login button found
✅: Click completed—as reported by Playwright
❌: Page navigated to the actual login page
📸: Screenshot take chromium-true.png

CHROMIUM [HEADLESS=false]
----------------
✅: Login button found
❌: Click completed—as reported by Playwright
❌: Page navigated to the actual login page
📸: Screenshot take chromium-false.png

WEBKIT [HEADLESS=true]
----------------
✅: Login button found
✅: Click completed—as reported by Playwright
❌: Page navigated to the actual login page
📸: Screenshot take webkit-true.png

WEBKIT [HEADLESS=false]
----------------
✅: Login button found
✅: Click completed—as reported by Playwright
❌: Page navigated to the actual login page
📸: Screenshot take webkit-false.png

FIREFOX [HEADLESS=true]
----------------
✅: Login button found
✅: Click completed—as reported by Playwright
✅: Page navigated to the actual login page
📸: Screenshot take firefox-true.png

FIREFOX [HEADLESS=false]
----------------
✅: Login button found
✅: Click completed—as reported by Playwright
✅: Page navigated to the actual login page
📸: Screenshot take firefox-false.png

Script to generate it:

const playwright = require("playwright"); // playwright-1.2.1
const http = require("http");
const server = http.createServer((req, res) => {
  res.setHeader("Cache-Control", "no-store");
  res.end(`
    <body>
        <div style="position:fixed;top:300px;left:300px;width:400px;height:400px;">
            <iframe src="https://en.wikipedia.org/"  width="100%" height="100%" > </iframe>
        </div>
    </body>
  `);
});

const tests = async () => {
  const results = [];
  for (const b of [
    playwright.chromium,
    playwright.webkit,
    playwright.firefox,
  ]) {
    for (const headless of [true, false]) {
      const result = {
        browser: b.name(),
        headless,
        foundLoginButton: false,
        clickCompleted: false,
        pageNavigated: false,
        screenshot: null,
        error: null,
      };
      results.push(result);
      const browser = await b.launch({ headless });
      const context = await browser.newContext({
        viewport: { width: 1920, height: 1080 },
      });
      const page = await context.newPage();
      await page.goto("http://localhost:8000");
      try {
        const frame = page.frames()[1];
        // Check for an actual navigation to the login page
        const loggedInPage = new Promise((fulfill, reject) => {
          const t = setTimeout(() => reject("~10 seconds ellapsed"), 10_000);
          page.on("framenavigated", (f) => {
            if (
              f.url() ===
              "https://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Main+Page"
            ) {
              clearTimeout(t);
              fulfill();
            }
          });
        });

        const button = await frame.$("#pt-login");
        result.foundLoginButton = true;
        await button.click({ timeout: 5_000 });
        result.clickCompleted = true;
        await loggedInPage;
        result.pageNavigated = true;
      } catch (error) {
        result.error = error;
      } finally {
        const path = `${b.name()}-${headless}.png`;
        await page.screenshot({ path });
        result.screenshot = path;
      }

      await browser.close();
    }
  }
  return results;
};

server.listen(8000);
tests()
  .then((results) => {
    console.log("Tests complete.");
    for (const result of results) {
      console.log(
        `${result.browser.toUpperCase()} [HEADLESS=${result.headless}]`
      );
      console.log(`----------------`);
      console.log(
        `${result.foundLoginButton ? "✅" : "❌"}: Login button found`
      );
      console.log(
        `${
          result.clickCompleted ? "✅" : "❌"
        }: Click completed—as reported by Playwright`
      );
      console.log(
        `${
          result.pageNavigated ? "✅" : "❌"
        }: Page navigated to the actual login page`
      );
      console.log(`📸: Screenshot take ${result.screenshot}`);
      console.log();
    }
  })
  .catch((error) => console.error("Tests errored", error))
  .finally(() => {
    console.log("Closing down test server");
    server.close();
  });

rwoll added a commit to rwoll/playwright that referenced this issue Jul 27, 2020
This changeset adds tests the more closely match the reported scenario
in microsoft#3170. Firefox, both headless and headfull pass completetly in all
cases. The other browsers (both headless and headfull) report a
successful click (i.e. they get past the await `button.click()`) but
fail to pass the navigation check, except for Chromium HeadFULL with a
fixed div which fails to even do the click.

NB: If you perform this test manually in the production version of
Firefox (78.0.2), the navigation to the Wikipedia login page will be
blocked due to X-Frame-Options: DENY. The iframe will load on
localhost, but clicking login will get you a an error about
X-Frame-Options. So, in some ways, even though this test is "passing"
for FFOX, in a traditional user environment we'd expect it to fail.
rwoll added a commit to rwoll/playwright that referenced this issue Jul 27, 2020
This changeset adds tests the more closely match the reported scenario
in microsoft#3170. Firefox, both headless and headfull pass completetly in all
cases. The other browsers (both headless and headfull) report a
successful click (i.e. they get past the await `button.click()`) but
fail to pass the navigation check, except for Chromium HeadFULL with a
fixed div which fails to even do the click.

NB: If you perform this test manually in the production version of
Firefox (78.0.2), the navigation to the Wikipedia login page will be
blocked due to X-Frame-Options: DENY. The iframe will load on
localhost, but clicking login will get you a an error about
X-Frame-Options. So, in some ways, even though this test is "passing"
for FFOX, in a traditional user environment we'd expect it to fail.
@rwoll
Copy link
Member

rwoll commented Jul 27, 2020

I've updated #3172 with additional tests that more closely simulate the reported issue. It seems there's two issues:

  1. Clicking on a link within a an iframe within a fixed position div fails for headFULL Chromium: https://github.com/microsoft/playwright/pull/3172/files#diff-436ef033c677ecf2016948e353dd7af2R365
  2. After a successful click on an iframe, a navigation to a frame with X-Frame-Options: DENY is handled inconsistently across the Plawywright browsers (as compared with each other and the consumer facing browsers): https://github.com/microsoft/playwright/pull/3172/files#diff-436ef033c677ecf2016948e353dd7af2R473-R480

/cc @aslushnikov since he looked into #3166 which feels similar (at least for the clicking part), but differs in what's fixed and visible.

rwoll added a commit to rwoll/playwright that referenced this issue Jul 27, 2020
This changeset adds two tests aimed at reproducing microsoft#3170 where a link
in a cross-domain iframe fails to get clicked even though the element is
found.

In addition to the cross-domain test, we add a `srcdoc` test to baseline
the source of failing behavior.

In the matrix of {Firefox, Chromium, Webkit } X { srcdoc, cross-domain } X
{ Headfull, Headless }, only the Chromium Headfull test with
cross-domain iframe fails.

Notably, it fails while logging the same message as reported in the
original issue:

```
pw:api retrying click action [] +0ms
pw:api   waiting for element to be visible, enabled and not moving [] +0ms
pw:api   element is visible, enabled and does not move [] +25ms
pw:api   scrolling into view if needed [] +0ms
pw:api   done scrolling [] +1ms
pw:api   checking that element receives pointer events at (35.32,17) [] +1ms
pw:api   element does not receive pointer events []
…
```
rwoll added a commit to rwoll/playwright that referenced this issue Jul 27, 2020
This changeset adds tests the more closely match the reported scenario
in microsoft#3170. Firefox, both headless and headfull pass completetly in all
cases. The other browsers (both headless and headfull) report a
successful click (i.e. they get past the await `button.click()`) but
fail to pass the navigation check, except for Chromium HeadFULL with a
fixed div which fails to even do the click.

NB: If you perform this test manually in the production version of
Firefox (78.0.2), the navigation to the Wikipedia login page will be
blocked due to X-Frame-Options: DENY. The iframe will load on
localhost, but clicking login will get you a an error about
X-Frame-Options. So, in some ways, even though this test is "passing"
for FFOX, in a traditional user environment we'd expect it to fail.
rwoll added a commit to rwoll/playwright that referenced this issue Jul 28, 2020
This changeset adds two tests aimed at reproducing microsoft#3170 where a link
in a cross-domain iframe fails to get clicked even though the element is
found.

In addition to the cross-domain test, we add a `srcdoc` test to baseline
the source of failing behavior.

In the matrix of {Firefox, Chromium, Webkit } X { srcdoc, cross-domain } X
{ Headfull, Headless }, only the Chromium Headfull test with
cross-domain iframe fails.

Notably, it fails while logging the same message as reported in the
original issue:

```
pw:api retrying click action [] +0ms
pw:api   waiting for element to be visible, enabled and not moving [] +0ms
pw:api   element is visible, enabled and does not move [] +25ms
pw:api   scrolling into view if needed [] +0ms
pw:api   done scrolling [] +1ms
pw:api   checking that element receives pointer events at (35.32,17) [] +1ms
pw:api   element does not receive pointer events []
…
```
rwoll added a commit to rwoll/playwright that referenced this issue Jul 28, 2020
This changeset adds tests the more closely match the reported scenario
in microsoft#3170. Firefox, both headless and headfull pass completetly in all
cases. The other browsers (both headless and headfull) report a
successful click (i.e. they get past the await `button.click()`) but
fail to pass the navigation check, except for Chromium HeadFULL with a
fixed div which fails to even do the click.

NB: If you perform this test manually in the production version of
Firefox (78.0.2), the navigation to the Wikipedia login page will be
blocked due to X-Frame-Options: DENY. The iframe will load on
localhost, but clicking login will get you a an error about
X-Frame-Options. So, in some ways, even though this test is "passing"
for FFOX, in a traditional user environment we'd expect it to fail.
@dgozman
Copy link
Contributor

dgozman commented Jul 29, 2020

I think with #3201 and #3217 this can be closed. Playwright should now click correctly, and we'll follow up with X-Frame-Options: DENY issue in Firefox.

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

No branches or pull requests

3 participants