Miraculous — using Cypress to test nested iframes in scalable vector graphics (SVG) interfaces

Maryna Nalbandian
Modern Mainframe
Published in
5 min readFeb 25, 2021

--

You want to use Cypress to test your application but it has iframes embedded in it — don’t panic, let’s dig into this topic.

First, let’s understand the terms of iframes, Cypress.io, and SVG.

Iframe. An iframe (inline frame) is an HTML element that allows an external webpage to be embedded in an HTML document. Unlike traditional frames, which were used to create the structure of a webpage, developers mainly use the iframe tag to embed another HTML document within the current one.

Cypress.io. Cypress is a free and open-source, MIT-licensed, testing tool written in JavaScript. Cypress makes E2E quality assurance, integration, and unit tests easy (well it is easy to understand, but it has its own limitations, and one of them is iframes) to write and debug. Aside from the script runner, Cypress provides a visual interface to indicate which tests and which commands are running.

I hope that Cypress will fix (or improve) these iframe issues . This article is based on , using Cypress version 5.3.0.

Scalable Vector Graphics (SVG) is an Extensible Markup Language (XML) — based vector image format for two-dimensional graphics with support for interactivity and animation.

For testing purposes, I will use Cobol Control Flow, a Visual Studio Code extension that provides a graphical visualization of program flow for programs written in the Cobol language. The extension allows Cobol developers to quickly comprehend and visualize COBOL programs. Especially valuable when learning an unfamiliar application.. Also, we need a web-browser based editor (open-source Theia) lease note that Webviews (used by the control flow extension) work only for secure content (eg: https or localhost, not over http), so Theia should be configured in the secure content).

A quick example of how to generate a Cobol control flow from Cobol source

OK, let’s stop being boring and start the actual fun 😈
Working with iframes and SVG is possible in Cypress.io, but it will take some time for workarounds and additional code.

I used ready to import the cypress-iframe package, however, I needed to add a few things. So here are the steps:

  1. Add the package to your project, using

npm install -D cypress-iframe OR yarn add cypress-iframe --dev

2. Once the plugin is installed we can use builtin functions, like frameLoaded(), iframe() , etc.
Add the following import or require statement in your cypress/support/commands.js or cypress/support/commands.tsfile.

To load the iframe, you need to use the cy.frameLoaded() method and pass the iframe selector. This method will first verify if the iframe is loaded on the page. Then you just need to call cy.iframe() and chain the commands that you want to execute.

3. Great! Now let’s load our iframe:

cy.frameLoaded(‘iframe.webview');

Getting deeper into the project we can see that needed elements are inside another iframe iframe#active-frame . In order to load nested iframes, I used this custom command:

And finally, nested iframes can be loaded:

cy.frameLoaded(‘iframe.webview’).iframeCustom().find(‘iframe#active-frame’).iframeCustom();
How the extension looks like

As the result:

The Cross-origin frame is blocked

This error means that your application navigated to a superdomain that Cypress was not bound to. Initially when you cy.visit(), Cypress changes the browser’s URL to match the url passed to cy.visit(). This enables Cypress to communicate with your application to bypass all same-origin security policies among other things. When your application navigates to a superdomain outside of the current origin-policy, Cypress is unable to communicate with it, and thus fails.

Solution:

We need to tell the browser that it’s safe to access them and this can be done by setting chromeWebSecurityto false in cypress.json file.

4. Try again. Hooray 🎉

5. Now we need to be sure that we have our tooltip with selected class. Use a well-known “traditional” technique for looking for an element within DOM, we can not easily use Cypress features. For example, this will not work inside even loaded iframe:

cy.get(‘.node-foreign-object-div-nodeInfo-name .selected’);

SVG elements are captured using XPath created from HTML attributes.

e.g. //*[local-name()='svg'] or //*[local-name()='g'].
Unfortunately, XPath is not the best solution for finding elements, and here is why:

  • Speed. Nothing wrong with considering XPath locators but in long run, it will affect the speed of execution. Searching element by id, CSS is faster.
  • Using absolute XPath could be a problem as if site structure changes then absolute XPath will not work. Relative paths are better.

This cheatsheet can be handy. Also, I recommend using extensions for browsers to find XPath. Here are 10 Chrome extensions you can be interested in. I would give it a try with selectorshub.

6. Finally we can create our XPath:

But before that, I recommend using cypress-xpath.

cy.loadFlowIframe().xpath(`//*[name()=”g”]//div[@class=”node-foreign-object-div-nodeInfo-name selected”][text()=”${paragraph}”]`);

In the end, we finally caught the needed class in SVG within nested iframes:

In conclusion, I must say it is not super easy or obvious how to deal with this (a bit) extreme case. But I really hope that this article will help you and…

--

--