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
Iframe support #136
Comments
commenting that I care because the docs said I should and we need this functionality for full test coverage. |
We also would need this functionality to be able to really use Cypress. Our app relies on rendering into an iframe for a significant part of it‘s functionality (it’s an editor, and the iframe is used to sandbox the thing being edited), and being able to target elements in that iframe is pretty essential to our testing. |
Is the We can pretty easily add same domain iframe support. Cross domain will take a lot more work. The difference will likely be days of work vs 1-2 weeks. |
Same domain. The iframe is really just a sandboxed canvas that we render into, rather than a 3rd party resource that we are loading into the app. (And thanks for the quick reply!) |
same domain iframe would allow us to test emails via e.g. mailinator.com |
Cypress actually injects to forcibly enable it to access same domain This is coming up on our radar and it will introduce a few more API's to enable switching in and out of As a workaround today you can actually still target these elements and potentially perform actions on them by you cannot return them or use them in cypress commands. So this actually works: cy.get("iframe").then(function($iframe){
// query into the iframe
var b = $iframe.contents().find("body")
// you can work with this element here but it cannot
// be returned
var evt = new Event(...)
b.dispatchEvent(evt)
return null
}) |
I would need that feature too. To really test all use cases of our credit card from which is implemented by using braintree hosted fields api. They inject iframes into div and do the complete validation. However to test that our visuals and the submission to the server works I would need to be able to access those iframes. |
@harz87 the If that's the case you'll need to disable web security before being able to access them. After you do that you can at least manually interact with them and force their values to be set - although you won't be able to use Cypress API's until we add support for switching to and from iframes. |
This is something that'd be pretty important for my company. We've currently got a working ruby+selenium testing setup, however not all of our company is able to take advantage of those tools as we have some PHP and Go codebases, each of which is rapidly accumulating more and more JS heavy interfaces we'd like to be able to test. We're looking at cypress as a possible candidate to standardise on, but iframe support is currently a blocker. The specific test case we're evaluating is our payments flow, which loads a modal containing an iframe on the same domain with all of the controls for inputting payment details and submitting requests to pay to the server. Here's a screenshot to give you a better idea: All of the content you can see is actually embedded in an iframe. Our tests go through the various payment methods we offer, filling in details like credit card information, billing address, etc. before clicking pay and then asserting that an appropriate message is displayed such as "Payment successful" or an appropriate error message. Unfortunately we can't just test the content within the iframe directly as the payment modal is designed to be embedded into a page, and it communicates necessary information between the page containing the iframe and the page within the iframe. We can use the workaround posted above, however as we're aiming to replace an already functional test system it makes it harder to justify using the workaround when it greatly reduces the benefits of using cypress. Let me know if there's anymore information you need. |
We would like to have this feature in cypress, because we are using CKEditor for wysiwyg input in our application, and it uses an iframe. |
+1 We are also integrating external (cross-domain) payment methods and would like to test. |
+1 We are also integrating external (cross-domain) payment methods |
People writing about payment methods, so do i. I'm trying to pass Stripe checkout iframe
cypress.json
{
"chromeWebSecurity": false
} .get('iframe.stripe_checkout_app').should('exist')
.then(function ($iframe) {
const iframe = $iframe.contents()
const cardNumInput = iframe.find('input:eq(0)')
const cardValidInput = iframe.find('input:eq(1)')
const cvcInput = iframe.find('input:eq(2)')
cardNumInput.val('4242424242424242')
cardValidInput.val('1222')
cvcInput.val('123')
setTimeout(() => {
iframe.find('button').click()
}, 1000)
return null
}) Anyone knows how to resolve this? |
EDITED: to show using proper Cypress commands. .get('iframe.stripe_checkout_app')
.then(function ($iframe) {
const $body = $iframe.contents().find('body')
cy
.wrap($body)
.find('input:eq(0)')
.type('4242424242424242')
cy
.wrap($body)
.find('input:eq(1)')
.type('1222')
cy
.wrap($body)
.find('input:eq(2)')
.type('123')
}) |
We use Iframe to insert user made forms into a webpage. We have to look at whats entered in the fields. The forms don't even show up in the cypress browser. They are just replaced with "<iframe> placeholder for". It hows up fine in a plain chrome browser though. |
Are you still planning to add support for this later? |
We don't show content in iframes when reverting to a snapshot (nor will we ever do that). However we will eventually support targeting DOM elements inside of iframes. |
This would be great for us too, we are using CKeditor quite a bit (in an iFrame) |
I'm also very interested in the ability to target elements in an iframe (same domain). This means that the root frame is only responsible for starting the inner frame application This works great for our unit and integration testing using karma. |
We are much closer to having this work. Here in We'll still need to build in API's that enable you to switch the document context to the iframe, so you can use the querying methods of Cypress the same as you do on the outer document. Also things like verifying actionability still need work - notice I need to pass Nevertheless its a big step forward because you can at least now fill out forms and interact with iframe elements, which prior to |
So this does work, but I find I have to add a |
No, this is all part of the complexity of support iframes. Essentially all of the same safeguards we've added to the main frame have to be replicated on iframes. We do a ton of work to ensure The additional complexity is that we can't add those listeners until you've told us you want to "switch" into those frames. |
You'd likely need to write a custom command that takes this into account. It checks |
ok that was the direction I was headed 👍 |
This is an option typing in an input field situated in the iframe: cy.get(iframe_selector).then($iframe => {
const iframe = $iframe.contents();
const myInput = iframe.find("your input selector like #myElement");
cy.wrap(myInput).type("example");
//you don't need to trigger events like keyup or change
}); |
This is what I ended up doing. Seems to work rather well. You can alias the Cypress.Commands.add('iframe', { prevSubject: 'element' }, $iframe => {
return new Cypress.Promise(resolve => {
$iframe.on('load', () => {
resolve($iframe.contents().find('body'));
});
});
}); // for <iframe id="foo" src="bar.html"></iframe>
cy.get('#foo').iframe().find('.bar').should('contain', 'Success!'); |
This is what's working for me (the second find() was timing out without an extra wait):
I hope it helps. Reference: https://www.udemy.com/course/cypress-tutorial/ |
Hi everybody This is added in the commands.js-file:
To interact with the elements:
The command iframeOnload() is only used when the iframe is reloaded/slow, or when iframeDirect() fails for some reason (otherwise the workaround is to use iframeDirect() with wait() which makes the tests very unstable). The only way to use cypress selector-button on the elements in the iframe is to navigate to the iframe-src/address but that makes everything harder :) At the moment I use the Inspector to find the element-name. Hope this helps someone. And if anyone knows how to merge both commands into one, please share your solution! Edit: when testing iframes, if you put the mouse-pointer on cypress command log, cypress wont be able to show the flow, it shows an almost blank page (at least in my case). |
@acusti I have the same issue where my editor is in an iframe. For now, I created a Cypress command: Cypress.Commands.add('getEditor', () => {
return cy.get('#editor-iframe')
.its('0.contentDocument.body').should('not.be.empty')
.then(cy.wrap);
}); |
This works when running the tests on my PC but when I run them in a Tekton-pipeline in OCP4 the iframeOnload() is running forever (because it's waiting forever, no other code is running). |
Hi all I have closed my previous ticket that was linked to cypress crashing as I feel its related to iFrames. Automation team is currently using : "cypress-iframe": "^1.0.1", npm plugin We seem to be able to automate loading of site and querying the iFrame contents, the problem happens soon as the script has finished the checks within the iFrame and the iFrame closes - this is when Cypress crashes, its been happening for last few months with various versions - we patiently waiting but we need some feedback/words on the matter. No matter the content of the site, we observed in number of occations if a iFrame is used in the form of a popup then closed or a redirect happens, cypress will crash, I'm not able to provide any specific debug info as there really is none, to replicate someone from cypress just needs to set up some mocks around iFrames. Is this happening to anyone else or anyone has a temp solution - even the most basic support to stop crashing would help. Thank you |
Does it crash even when running on some other PC? |
Correct, all team members experiance the crash, mix of machines, MacOS and Windows - so this is not related to machine itself. The cypress runner just stops and then all is seen is the script selection screen to re-run script. I guess it may not be classified as a "full crash" where the app completely closes and terminates. |
I'm just coming here to add that we are experiencing this exact problem as well. It would be great to hear if there is any potential workaround for this, or if it is even being worked on. This issue has been open for 7 years... |
Thanks for responding Elli, Im glad we are not only ones with this issue, so far we found no workaround, once again we hope cypress team responds - Im not sure what options with have if we do not get some feedback on the matter. Do not wish to sound like a broken record. |
Worked for me in CY 12.10.1version . |
Unfortunately our problem is with a submit button that dynamically creates a form inside of a new iframe and then redirects the user from that iframe. So I don't need to see anything in the iframe itself, I just need to redirect after the button is clicked, but Cypress crashes and there doesn't seem to be any way to intercept the request to work around it. |
Don't get me wrong, I like Cypress, but when it comes to frames, Playwright can handle them. |
I've been using cypress for years and they still haven't solved this problem |
@brian-mann Hi, can you update community please on where we stand on iFrames, least some estimate perhaps. Thank you |
@T-Auto-1 you are the greatest for that solution! |
Hello Everyone,
Correct me if i missed any thing here. Could cypress team gives any expected timeline if this feature is going to be available or any current update would be very helpful. Thanks, |
I found a solution that works without the need to set chromeWebSecurity to false. I created this custom command:
In the beforeEach of the test, I use:
And in the test code, I use:
It's a simple solution and didn't cause any issues using chromeWebSecurity set to true, but I'm still in favor of Cypress helping us address this problem; it will greatly assist us. |
Thanks @MarcosPereira1 for the input. Let me try that, did you tested above code against cross-origin iframe? in test: But this will not work for cross-origin iframes. Only work for same origin frames. |
I did tried other workaround to establish communication flow between parent document and iframe document. Please find below sample code to understand more: Button clicked successfully!
<script>
const messageDiv = document.getElementById("message");
document.getElementById("send-message-btn").addEventListener("click", () => {
const message = { type: "dataUpdate", data: "Hello from iframe!" };
parent.postMessage(message, "http://127.0.0.1:3000/index.html");
Index.html: <script> // Listen for messages from the iframe window.addEventListener("message", (event) => { // Make sure the message is from a trusted source if (event.origin !== "http://127.0.0.1:3002/IframeTest/iframe-content.html") return;
XHR in iframe<iframe src="iframe-content.html" data-cy="the-frame"></iframe>Cypress Test: Steps to do that:
This is just a example and depends on how we are embedding cross-origin iframe. This looks safe way to deal with iframe but it may increase complexity in frontend as we need to main these logics on both segment of documents. In case if embedded iframe(iframe-content.html in our case) don't support(which most of the case won't as long it's not open source or same team managing) then it become show stopper for cypress users. |
Updated Feb 9, 2021 - see note below or #136 (comment)
Currently the Test Runner does not support selecting or accessing elements from within an iframe.
What users want
Users of Cypress need to access elements in an
<iframe>
and additionally access an API to "switch into" and switch back out of different iframes. Currently the Test Runner thinks the element has been detached from the DOM (because itsparent
document is not the expected one).What we need to do
Add new
cy
commands to switch into iframes and then also switch back to the "main" frame.Cypress must inject itself into iframes so things like XHR's work just like the main frame. This will ideally use something like
Mutation Observers
to be notified when new iframes are being pushed into the DOM.Add API to navigate between frames
Update the Driver to take into account element document references to known frames
Things to consider
<iframe>
.{ chromeWebSecurity: false }
(Chromium-based browsers only).Examples of how we could do this
Workaround
It's possible to run
cy.*
commands on iframe elements like below:Updates as of Feb 9, 2021
Pasting some snippets from our technical brief on iframe support that we are currently planning. As always, things can change as we move forward with implementation, but this is what we are currently planning.
If there's any feedback/criticism on these specific proposed APIs, we'd be happy to hear it.
.switchToFrame([...args], callback)
Switches into an iframe and evals callback in the iframe. Doesn’t matter whether the iframe is same-origin or cross-origin.
Stripe payment example
Same-origin iframe
Example where a site uses a same-domain iframe as a date-picker widget
We also intend to support snapshots of iframes.
The text was updated successfully, but these errors were encountered: