Imagine your application loads in stages and shows several loading elements. There are two loading elements visible to the user right away (above the fold), and one more loading element below the fold. Here is a sample page showing this situation:
1 | <body> |
The #page1
and #page2
sections are marked with different colors. Each is 1000x1000 pixels and if we zoom out look like this:
Tip: I set the viewport width and height as 1000 pixels in the cypress.json
file. To show the two sections at once, I modified the viewport height using per-test configuration:
1 | it('loads', { viewportHeight: 2000 }, () => { |
🎁 You can find the source code and the tests shown in this bog post in the repo bahmutov/loading-elements.
Video: I have recorded a short video showing how to check the loading elements in the current viewport. You can watch the video below
The application "loads" and removes the first two loading elements.
1 | const [loading1, loading2] = document.querySelectorAll('#page1 .loading') |
If we want to check if the loading elements above the fold disappear, we cannot just check the visibility - because it will include the third loading element that is still visible, even if the user cannot see it without scrolling.
1 | it('the loading element below the fold never goes away', () => { |
How do we check if the loading elements inside the current viewport are no longer visible? By using the bounding rectangle of the elements before checking them! See the documentation for the Element.getBoundingClientRect which returns the rectangle in the current viewport. I took this chart from the documentation page:
If the bottom of the element is less than zero, then the element is above the current viewport. If the top of the element is larger than the viewport height, then the element is still below the current viewport. Similarly, we can check the Let me write a custom command to repeatedly check the DOM until the elements in the current viewport become hidden.
1 | /// <reference types="cypress" /> |
Let's make our application even more complicated. We will hide / remove all loading elements one by one after 2, 3 and 4.5 seconds.
1 | const [loading1, loading2] = document.querySelectorAll('#page1 .loading') |
Our test will wait for the above the folder loading elements to disappear before scrolling to the bottom of the page and verifying the last loading element is also gone from the view.
1 | it('checks if the loading element is visible within the current viewport', () => { |
The above test works beautifully.
Happy Testing!