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

fix: calculate positions for elements inside iframes correctly #29

Conversation

istateside
Copy link
Contributor

Fixes #28

When cy.realClick() or cy.realHover() are called on elements that are inside of an iframe within the Cypress app's own iframe, the position calculated for the element doesn't account for the possible offset position of its containing iframe.

}

return {
x: finalX,
Copy link
Owner

Choose a reason for hiding this comment

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

Also it is required to calculate the real size of the iframe (if it was scaled). Just like we are doing already for the upper iframe

@dmtrKovalenko
Copy link
Owner

I cannot merge PRs without tests. If you want this to be merged please add some tests or wait – I will add some tests myself

@istateside
Copy link
Contributor Author

istateside commented Feb 16, 2021

I have an update with tests I'll push up here soon, just gotta polish it up a bit.

I don't think my changes cover elements that are being transformed themselves (transform applied to the target element or one of its containers, as opposed to a transform on the <iframe> itself), but I don't think the library covers that case before this PR anyway. I'd prefer to leave that out of this PR and report it as a separate issue

@istateside istateside force-pushed the fix/element-positions-inside-iframes branch from 5d6b028 to 3b71e78 Compare February 18, 2021 17:07
@istateside
Copy link
Contributor Author

Just pushed up a commit fixing the failing test and rebasing on develop.

Sorry about that, I recently changed some git defaults to not index untracked files by default. I typically work in a very large repo and that change speeds up all my git commands. Still haven't acclimated to it yet, so I keep forgetting to manually add untracked files to my commits.

Let me know what you think of the approach I went with (or take the PR over if you'd prefer), i added some HTML files to test the iframe behavior against.

@istateside
Copy link
Contributor Author

I'm still getting a failure on the swipe test, for the toTop test. It only fails when run in CI mode, it passes fine with cypress open. @dmtrKovalenko would you be able to look into that for me?

const iframes = [];

let currentWindow: Window | null = element.ownerDocument.defaultView;
while (currentWindow && currentWindow.frameElement && currentWindow !== window) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just a note regarding .frameElement - it should return null for a cross-origin frame which could be a problem when running with --disable-web-security but I've checked that and it seems that this flag makes .frameElement return the correct element from the parent.

}

if (currentWindow) {
iframes.unshift(window.parent.document.querySelector('iframe')); // The Cypress app frame
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm wondering - couldn't this algorithm be simplified to process the whole thing in a single pass when traversing elements up? This potentially would also allow dropping this Cypress-specific~ line.

@istateside
Copy link
Contributor Author

Hey, just checking in here. I haven't had time to come back to this, but I'm hoping to put some more time in this upcoming weekend to see if I can figure out why the build is failing (and to respond to the outstanding comments)

@dmtrKovalenko dmtrKovalenko merged commit 3c8f01a into dmtrKovalenko:develop Mar 5, 2021
dmtrKovalenko added a commit that referenced this pull request Mar 5, 2021
* feat: add option changing scrolling behavior (#30)

* feat: allow changing scrolling behavior for realClick and realHover

* feat: Fallback to Cypress.config('scrollBehavior')

* feat: Add specs for scrollBehavior to click and hover

* fix: ignore TS errors or Cypress <6.1.0

* fix: remove false option for scrollBehavior

* fix: bump dev dependency for cypress to 6.1 for compilation error

* [] Move scrollBehavior specs directly into click.spec and hover.spec

* [] Fix failing swipe tests by passing scrollBehavior

* Reduce renames

* Remove unused option

Co-authored-by: Dmitriy Kovalenko <[email protected]>

* Add support for radius options in realTouch (#31)

* test: add test for radius options in realTouch (#32)

* fix(realTouch): accept 0 for position x/y values (#33)

* feat: Transpile files to cjs (#34)

* fix: calculate positions for elements inside iframes correctly (#29)

* fix: calculate positions for elements inside iframes correctly

* Handle iframes with scale transforms

* [] Refactor getCypressElementCoordinates to better handle scaled frames

* [] Add tests for click and hover in iframes

* [] Add HTML files to fixtures folder

* Remove unnecessary @ts-expect-error

* Change logic of get cypress element

* Make swipe tests retryable

Co-authored-by: Dmitriy Kovalenko <[email protected]>

* Fix touch radius test

Co-authored-by: Kevin Fleischman <[email protected]>
Co-authored-by: Mateusz Burzyński <[email protected]>
Co-authored-by: Izhaki <[email protected]>
Co-authored-by: Kevin Fleischman <[email protected]>
@dmtrKovalenko
Copy link
Owner

🎉 This PR is included in version 1.3.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

// for cross origin domains .frameElement returns null so query using parentWindow
// but when running using --disable-web-security it will return the frame element
(currentWindow.frameElement as HTMLElement) ??
currentWindow.parent.document.querySelector("iframe")
Copy link
Collaborator

Choose a reason for hiding this comment

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

out of curiosity - is there any situation in which this fallback would actually kick in? note that if it does it might not return the correct iframe as there might be multiple iframes on the page and this doesn't account for that

Copy link
Owner

Choose a reason for hiding this comment

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

Yep when running with disable-web-security it follows the original .frameElement.

I didn’t get the last part. This prop returns the frame where window is embedded. It means that it returns the upper frame which is the only that contains this window.

If think this way it may be really possible to remove this branching, but what exact problem do you see here?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yep when running with disable-web-security it follows the original .frameElement.

I was the one who has checked how this behaves with disable-web-security and to my slight surprise, it just has returned the "correct" .frameElement despite .frameElement having to return null for cross-origin iframes. So it is as web-security is also responsible for guarding access to .frameElement - so it returns null normally and if we disable it starts to return the correct element.

So using disable-web-security (according to my tests) doesn't influence the logic anyhow - and from what I understand we shouldn't be even able to select cross-origin element in Cypress (when not using disable-web-security) as it's running in the real browser's context so it would just not allow us to do that.

I didn’t get the last part. This prop returns the frame where window is embedded. It means that it returns the upper frame which is the only that contains this window.

I was referring to the fallback logic (currentWindow.parent.document.querySelector("iframe")) - it can just queries the first iframe but the currentWindow.parent.document might contain more than one and thus we can select incorrect one using this.

If think this way it may be really possible to remove this branching, but what exact problem do you see here?

I just usually try to avoid dead branches of the code and was really curious if this is dead or not (the ?? part). I might very well just miss something here. And, as mentioned, even if it's not dead I believe that it might lead to incorrect results at times.

Copy link
Owner

Choose a reason for hiding this comment

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

Makes sense. So it needs to be processed by looking for iframe which content window is equal to current frame, yeah it looks correct.

Feel free to open PR, I am on vacation right now so won’t code — but I can review PR and merge if everything is fine

Copy link
Collaborator

Choose a reason for hiding this comment

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

The question is - how to write a test for this? Under what circumstances are we able to "fail" reading the currentWindow.frameElement?

Copy link
Owner

Choose a reason for hiding this comment

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

In any case except cypress is running over chrome with disabled web security I think

Copy link
Collaborator

Choose a reason for hiding this comment

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

In a regular scenario (without disabled web security) - we can't even get access to cross-origin frames. I've just re-tested this using this repo:

Uncaught DOMException: Blocked a frame with origin "https://example.cypress.io" from accessing a cross-origin frame.

So I think (but not entirely sure) that it's not possible to get access to an element from some inner cross-origin so this entire logic just can't be executed on such an element (no cypress command can).

However, I see that a regular relation between embedding context and an embedded iframe is somehow hacked for the AUT in Cypress. How do you even achieve that? 🤔 I have never actually thought about it as our tests are running against localhost.

And note - a cross-origin AUT has .frameElement === null. So this logic is actually not dead 👍 As it handles the last iframe on the stack (the AUT) and it just happens that the AUT is the first one (at least for now 😉 ).

If I have made any mistake in my whole reasoning - please let me know.

Copy link
Owner

@dmtrKovalenko dmtrKovalenko Mar 7, 2021

Choose a reason for hiding this comment

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

Cypress proxies response of your website for testing so the origin will always be the same. The whole cypress is build over making iframe same origin.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Cool, that's good to know! Now when you have said that I think I've seen your injection code when debugging - just didn't connect the dots.

Either way - would you agree then that this fallback logic is currently only executed when looking for the frameElement of the AUT? Or are there any other cases as well that come to your mind?

Copy link
Owner

Choose a reason for hiding this comment

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

Yes it looks like it exists for aut or the edge case, but you are right it’s mainly for the cypress aut

@istateside
Copy link
Contributor Author

Just checked in on this and saw it was merged - thanks for taking this over, gonna upgrade in our app today 😃

dmtrKovalenko added a commit that referenced this pull request May 31, 2021
* 1.3.0 (#35)

* feat: add option changing scrolling behavior (#30)

* feat: allow changing scrolling behavior for realClick and realHover

* feat: Fallback to Cypress.config('scrollBehavior')

* feat: Add specs for scrollBehavior to click and hover

* fix: ignore TS errors or Cypress <6.1.0

* fix: remove false option for scrollBehavior

* fix: bump dev dependency for cypress to 6.1 for compilation error

* [] Move scrollBehavior specs directly into click.spec and hover.spec

* [] Fix failing swipe tests by passing scrollBehavior

* Reduce renames

* Remove unused option

Co-authored-by: Dmitriy Kovalenko <[email protected]>

* Add support for radius options in realTouch (#31)

* test: add test for radius options in realTouch (#32)

* fix(realTouch): accept 0 for position x/y values (#33)

* feat: Transpile files to cjs (#34)

* fix: calculate positions for elements inside iframes correctly (#29)

* fix: calculate positions for elements inside iframes correctly

* Handle iframes with scale transforms

* [] Refactor getCypressElementCoordinates to better handle scaled frames

* [] Add tests for click and hover in iframes

* [] Add HTML files to fixtures folder

* Remove unnecessary @ts-expect-error

* Change logic of get cypress element

* Make swipe tests retryable

Co-authored-by: Dmitriy Kovalenko <[email protected]>

* Fix touch radius test

Co-authored-by: Kevin Fleischman <[email protected]>
Co-authored-by: Mateusz Burzyński <[email protected]>
Co-authored-by: Izhaki <[email protected]>
Co-authored-by: Kevin Fleischman <[email protected]>

* Revert "1.3.0 (#35)"

This reverts commit db00220.

* chore(readme): Add badge and fix typo

Co-authored-by: Kevin Fleischman <[email protected]>
Co-authored-by: Mateusz Burzyński <[email protected]>
Co-authored-by: Izhaki <[email protected]>
Co-authored-by: Kevin Fleischman <[email protected]>
dmtrKovalenko added a commit that referenced this pull request Jul 26, 2021
* 1.3.0 (#35)

* feat: add option changing scrolling behavior (#30)

* feat: allow changing scrolling behavior for realClick and realHover

* feat: Fallback to Cypress.config('scrollBehavior')

* feat: Add specs for scrollBehavior to click and hover

* fix: ignore TS errors or Cypress <6.1.0

* fix: remove false option for scrollBehavior

* fix: bump dev dependency for cypress to 6.1 for compilation error

* [] Move scrollBehavior specs directly into click.spec and hover.spec

* [] Fix failing swipe tests by passing scrollBehavior

* Reduce renames

* Remove unused option

Co-authored-by: Dmitriy Kovalenko <[email protected]>

* Add support for radius options in realTouch (#31)

* test: add test for radius options in realTouch (#32)

* fix(realTouch): accept 0 for position x/y values (#33)

* feat: Transpile files to cjs (#34)

* fix: calculate positions for elements inside iframes correctly (#29)

* fix: calculate positions for elements inside iframes correctly

* Handle iframes with scale transforms

* [] Refactor getCypressElementCoordinates to better handle scaled frames

* [] Add tests for click and hover in iframes

* [] Add HTML files to fixtures folder

* Remove unnecessary @ts-expect-error

* Change logic of get cypress element

* Make swipe tests retryable

Co-authored-by: Dmitriy Kovalenko <[email protected]>

* Fix touch radius test

Co-authored-by: Kevin Fleischman <[email protected]>
Co-authored-by: Mateusz Burzyński <[email protected]>
Co-authored-by: Izhaki <[email protected]>
Co-authored-by: Kevin Fleischman <[email protected]>

* Revert "1.3.0 (#35)"

This reverts commit db00220.

* chore(readme): Add badge and fix typo

* Update cypress to v8

Co-authored-by: Kevin Fleischman <[email protected]>
Co-authored-by: Mateusz Burzyński <[email protected]>
Co-authored-by: Izhaki <[email protected]>
Co-authored-by: Kevin Fleischman <[email protected]>
dmtrKovalenko added a commit that referenced this pull request Jul 26, 2021
* chore: backport changes (#90)

* 1.3.0 (#35)

* feat: add option changing scrolling behavior (#30)

* feat: allow changing scrolling behavior for realClick and realHover

* feat: Fallback to Cypress.config('scrollBehavior')

* feat: Add specs for scrollBehavior to click and hover

* fix: ignore TS errors or Cypress <6.1.0

* fix: remove false option for scrollBehavior

* fix: bump dev dependency for cypress to 6.1 for compilation error

* [] Move scrollBehavior specs directly into click.spec and hover.spec

* [] Fix failing swipe tests by passing scrollBehavior

* Reduce renames

* Remove unused option

Co-authored-by: Dmitriy Kovalenko <[email protected]>

* Add support for radius options in realTouch (#31)

* test: add test for radius options in realTouch (#32)

* fix(realTouch): accept 0 for position x/y values (#33)

* feat: Transpile files to cjs (#34)

* fix: calculate positions for elements inside iframes correctly (#29)

* fix: calculate positions for elements inside iframes correctly

* Handle iframes with scale transforms

* [] Refactor getCypressElementCoordinates to better handle scaled frames

* [] Add tests for click and hover in iframes

* [] Add HTML files to fixtures folder

* Remove unnecessary @ts-expect-error

* Change logic of get cypress element

* Make swipe tests retryable

Co-authored-by: Dmitriy Kovalenko <[email protected]>

* Fix touch radius test

Co-authored-by: Kevin Fleischman <[email protected]>
Co-authored-by: Mateusz Burzyński <[email protected]>
Co-authored-by: Izhaki <[email protected]>
Co-authored-by: Kevin Fleischman <[email protected]>

* Revert "1.3.0 (#35)"

This reverts commit db00220.

* chore(readme): Add badge and fix typo

Co-authored-by: Kevin Fleischman <[email protected]>
Co-authored-by: Mateusz Burzyński <[email protected]>
Co-authored-by: Izhaki <[email protected]>
Co-authored-by: Kevin Fleischman <[email protected]>

* chore(deps-dev): bump @typescript-eslint/parser from 4.24.0 to 4.26.0 (#92)

Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 4.24.0 to 4.26.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.26.0/packages/parser)

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump @typescript-eslint/eslint-plugin (#91)

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 4.25.0 to 4.26.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.26.0/packages/eslint-plugin)

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(Read

* chore(deps-dev): bump cypress from 7.4.0 to 7.6.0 (#111)

Bumps [cypress](https://github.com/cypress-io/cypress) from 7.4.0 to 7.6.0.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Changelog](https://github.com/cypress-io/cypress/blob/develop/.releaserc.base.js)
- [Commits](cypress-io/cypress@v7.4.0...v7.6.0)

---
updated-dependencies:
- dependency-name: cypress
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore: Remove validation of cypress iframe using id name (#124)

* chore(deps-dev): bump @typescript-eslint/eslint-plugin (#122)

Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 4.26.0 to 4.28.3.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.28.3/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps-dev): bump cypress from 7.6.0 to 7.7.0 (#120)

Bumps [cypress](https://github.com/cypress-io/cypress) from 7.6.0 to 7.7.0.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Changelog](https://github.com/cypress-io/cypress/blob/develop/.releaserc.base.js)
- [Commits](cypress-io/cypress@v7.6.0...v7.7.0)

---
updated-dependencies:
- dependency-name: cypress
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): Cypress v8 (#131)

* 1.3.0 (#35)

* feat: add option changing scrolling behavior (#30)

* feat: allow changing scrolling behavior for realClick and realHover

* feat: Fallback to Cypress.config('scrollBehavior')

* feat: Add specs for scrollBehavior to click and hover

* fix: ignore TS errors or Cypress <6.1.0

* fix: remove false option for scrollBehavior

* fix: bump dev dependency for cypress to 6.1 for compilation error

* [] Move scrollBehavior specs directly into click.spec and hover.spec

* [] Fix failing swipe tests by passing scrollBehavior

* Reduce renames

* Remove unused option

Co-authored-by: Dmitriy Kovalenko <[email protected]>

* Add support for radius options in realTouch (#31)

* test: add test for radius options in realTouch (#32)

* fix(realTouch): accept 0 for position x/y values (#33)

* feat: Transpile files to cjs (#34)

* fix: calculate positions for elements inside iframes correctly (#29)

* fix: calculate positions for elements inside iframes correctly

* Handle iframes with scale transforms

* [] Refactor getCypressElementCoordinates to better handle scaled frames

* [] Add tests for click and hover in iframes

* [] Add HTML files to fixtures folder

* Remove unnecessary @ts-expect-error

* Change logic of get cypress element

* Make swipe tests retryable

Co-authored-by: Dmitriy Kovalenko <[email protected]>

* Fix touch radius test

Co-authored-by: Kevin Fleischman <[email protected]>
Co-authored-by: Mateusz Burzyński <[email protected]>
Co-authored-by: Izhaki <[email protected]>
Co-authored-by: Kevin Fleischman <[email protected]>

* Revert "1.3.0 (#35)"

This reverts commit db00220.

* chore(readme): Add badge and fix typo

* Update cypress to v8

Co-authored-by: Kevin Fleischman <[email protected]>
Co-authored-by: Mateusz Burzyński <[email protected]>
Co-authored-by: Izhaki <[email protected]>
Co-authored-by: Kevin Fleischman <[email protected]>

* chore(deps): Support cypress v8

* fix: Enter doesn't fire trust click event (#132)

* fix: Enter doesn't fire trust click event

* Commit fixture

Co-authored-by: Kevin Fleischman <[email protected]>
Co-authored-by: Mateusz Burzyński <[email protected]>
Co-authored-by: Izhaki <[email protected]>
Co-authored-by: Kevin Fleischman <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Triggering events on elements inside iframes calculate position incorrectly
3 participants