jQuery, as we all know, is a JavaScript library which has simplified the web development process by providing multi-browser support for the HTML document traversing, event handling, DOM traversing and manipulation. For all the UI automation frameworks, accessing and manipulating the DOM elements is one of the significant tasks, and jQuery can help in achieving these tasks by writing very minimal code. Cypress has also based all its methods on jQuery functions, even cypress bundles the jQuery as one of the tools and exposes all the jQuery functions on the Cypress class. In this article, we will be covering the following topics to understand the relation of Cypress with jQuery:
- How Cypress queries DOM elements?
- What are the similarities between Cypress and jQuery while querying DOM elements?
- What are the dissimilarities between Cypress and jQuery while querying DOM elements?
- How to use jQuery functions in Cypress for accessing DOM elements?
- How to access DOM elements using Cypress.$?
- Similarly, how to access DOM elements using cy.$$?
- Difference between Cypress.$ and cy.$$?
How Cypress queries DOM elements?
As discussed, Cypress uses jQuery’s powerful selector engine to search and identify the DOM elements. All the Cypress methods to traverse the DOM elements are wrappers over the jQuery methods. As the baseline of Cypress is the same as jQuery, many of its attributes are the same as that of jQuery, but it also differs from jQuery in certain aspects. Let's discuss in the following sections, these similarities and dissimilarities between Cypress and jQuery for accessing the DOM elements:
What are the similarities between Cypress and jQuery while querying DOM elements?
As we know that Cypress uses the get() method to search for a web element in DOM and jQuery uses the $() method to search for web elements in DOM. The syntax of both of these elements is almost similar, as both of these accept the selector/locator of the web-element, which need to search in the DOM.
The web-elements can be queried in Cypress using the following syntax:
// Cypress querying an element
cy.get('selector_of_web-element');
As we have seen in the article, "get and find commands," the get command returns an object of a chainable jQuery object, which can invoke further methods
And, the web-elements can be queried in jQuery using the following syntax:
// jQuery querying an element
$('selector_of_web-element');
Similar to the Cypress's get method, the jQuery $() method also returns a jQuery object "JQuery<HTMLObjectElement>
", which can be used to invoke further jQuery functions.
What are the dissimilarities between Cypress and jQuery while querying DOM elements?
Apart from the mentioned similarities, there are certain dissimilarities between Cypress and jQuery, specifically around the execution nature(synchronous vs. asynchronous) and the results when one can not find an element while querying the DOM elements. Let's understand these differences in detail in the following sections:
jQuery's synchronous vs. Cypress's asynchronous execution:
The jQuery queries the UI elements synchronously, i.e., it returns the result of the search query instantly. Let's consider the following snippet:
// Search element and assign to a constant
const element = $('selector_of_web-element');
It will work perfectly fine, as the jQuery's $() function will return the query's result synchronously.
On the other hand, when we query the DOM elements using Cypress, as shown below:
// Cypress querying an element and assigning to constant will not work
const element = cy.get('selector_of_web-element');
It will not work as the Cypress's get() method will not return anything synchronously. As we have already covered in the chapter, "Cypress commands are asynchronous", all the Cypress commands return a promise, and we can never assign a promise to any constant variable.
Cypress vs. jQuery when the queried elements are not traceable:
Cypress and jQuery also differentiate in the behavior when the queried elements are not traceable. For a jQuery query, if it is not able to find the DOM element, it returns an empty jQuery collection. So, we need to handle such scenarios in case of jQuery explicitly. To understand it further, consider the following code snippet:
// $() returns synchronously with an empty collection if the element is not found.
const element = $('element_selector')
// Explicit handling with if condition
if (element.length) {
doSomething(element);
}
So, to avoid any kind of runtime exceptions, the developer needs to explicitly validate the length of the collection returned by the $(), so that at the runtime if the DOM element is not traceable, the not needed code will not be executed.
But, in the case of Cypress, no explicit handling of the search result need to be done. Cypress automatically retires the query until either it has not found the element or it times out while querying the element. Consider the following code to understand the same:
cy.get('element_selector')
.then((element) => { // this code will never execute if the element is not found
doSomething(element)
})
As we know, the get() method returns a promise, and the promise will resolve only when one finds the element. If the promise will reject, it will never execute the code under the then() method and makes the code much more readable.
Even though Cypress's methods are self-sufficient for automating a web application, but still Cypress has bundled and exposed the core jQuery functions on both the Cypress and cy objects. Let's understand the details and usage of both of these types in the following sections:
How to use jQuery functions in Cypress for accessing DOM elements?
As discussed, cypress bundles the jQuery functions, and these functions can be called anywhere in the test where you want to perform some synchronous query or action on the DOM elements. Cypress provides two ways to access these jQuery functions. Let's understand the details of both of these types in the following sections:
How to access DOM elements using Cypress.$?
One of the ways cypress has exposed the jQuery functions is using the "Cypress.$" object. Its syntax looks like below:
Cypress.$(element_selector)
Let's understand the usage of the same with the help of the following code:
// type definitions for Cypress object "cy"
/// <reference types="Cypress" />
describe('JQuery and Cypress Test Case', function () {
it('Performing JQuery Operation', function () {
cy.visit("https://demoqa.com/");
cy.request("/")
.its('body')
.then(html => {
const $titleHomePage = Cypress.$(html).find('.entry-title').text();
cy.log('Title of Page is: ' + $titleHomePage);
})
})
})
Save the test as CypressTest.js under the "integration/examples" folder and run it by double-clicking in the Cypress window. It will show the output as follows:
As we can see in the above test, we explicitly surrounded the Cypress.$() inside the .then clause, as the Cypress.$() is a synchronous call and all other methods of cypress are asynchronous, so, to wait for the cypress method, such as cy.visit() to complete their execution and the pass on context to Cypress.$() method.
Another use case of the jQuery methods using Cypress.$ can be on the browser console to debug the DOM elements while running the test cases. The Cypress.$ will automatically get the context of the page on the browser's console when the cypress test is running. You can validate the same using the following steps:
- When you are running the above test case, right-click on the browser window and click on the inspect option as shown below:
- Now on this console, if you directly search the title of the page using the locator, it will show the result as below:
So, before using any of the DOM elements in the cypress test cases, we can validate them directly on the console using the Cypress.$() method.
How to access DOM elements using cy.$$?
Another way to access the jQuery functions in Cypress is by using the cy.$$() function. Its syntax looks like below:
cy.$$(element_selector)
Let's modify the above code snippet, to use the cy.$$ instead of cypress.$:
// type definitions for Cypress object "cy"
/// <reference types="Cypress" />
describe('JQuery and Cypress Test Case', function () {
it('Performing JQuery Operation', function () {
cy.visit("https://demoqa.com/");
// const $titleHomePage = cy.$$('.entry-title').text();
cy.request("/")
.its('body')
.then(html => {
const $titleHomePage = cy.$$(html).find('.entry-title').text();
cy.log('Title of Page is: ' + $titleHomePage);
})
})
})
Save the test as CypressTest1.js under the "integration/examples" folder and run it by double-clicking in the Cypress window. It will show the same output as follows:
As we can see from the above screenshot that the output of the test using both Cypress.$ and cy.$$ is the same.
So, what is the difference between these two? Let's understand the same in the following section:
Difference between Cypress.$ and cy.$$?
As we have seen in the above sections that we can use both the Cypress.$ and cy.$$ to query DOM elements. The Cypress.$ is the replica of the jQuery functions, and you can do everything using Cypress.$ that you can do using the jQuery functions.
For Example, consider the following code snippets:
$.each([1, 2, 3], (arrayIndex, arrayValue) => {
expect(arrayIndex).to.eq(arrayValue)
})
The same can be achieved in Cypress using the following:
Cypress.$.each([1, 2, 3], (arrayIndex, arrayValue) => {
expect(arrayIndex).to.eq(arrayValue)
})
But, if we try to use cy.$$, instead of Cypress.$, as shown below:
cy.$$.each([1, 2, 3], (arrayIndex, arrayValue) => {
expect(arrayIndex).to.eq(arrayValue)
}) // This will lead to error
The above code-snippet will raise an error, as cy.$$ is a wrapper of the jQuery.fn.init and can only query the DOM elements and can't perform any other jQuery functions.
Key Takeaways
- Cypress exposes all the jQuery functions on the Cypress.$ and cy.$$ functions.
- Both of these jQuery functions are synchronous.
- Cypress.$ is a replica of jQuery functions, and you can perform all the jQuery operations using this.
- cy.$$ can be used only for querying the DOM elements using jQuery functions.
Let's move to the next article to understand the details of how we can handle the "child windows and frames" using Cypress?
If you want to learn more you can look at this video series: ++Cypress video series++