A user sent me a good question about this Cypress test: can it be simplified and can we compare the number of "empty" days computed in the first test with the number computed in the second test?
Let's do it!
🎁 You can find the full source code for this blog post in the repo bahmutov/calendar-example.
Block ads
It is painful to load this site, since there are so many ads. The network requests to fetch the ads completely block the Command Log.
The first thing we can do is to block the ad domains using blocklist
option in the cypress.config.js
. We can also move the base URL there and allow for larger viewport
1 | const { defineConfig } = require('cypress') |
Much better.
Wait for the page to load
Let's now figure out what the second test is querying on the page. If we hover over the get td[class="day old"]
command, we notice a curious thing: the entire page is still loading.
If we click on the GET
command, we pin the DOM snapshot and can inspect it in the DevTools. Seems like the .months-container
is still loading and has opacity
less than 1.
Let's wait for the opacity to become 1.
1 | it('Count and print how many empty fields there are for entire year', () => { |
If we hover or pin the GET
command, it clearly shows the empty cells at the start of each month (the "old" days from the previous month)
Empty days for the year
Let's simplify the second test
1 | it('Count and print how many empty fields there are for entire year', () => { |
We are getting all table cells with class "day" and the class "new", and then get all table cells with the class "day" and the class "new". Then we add the number of these cells together. Here is an equivalent test:
1 | it('Count and print how many empty fields there are for entire year', () => { |
Count the empty cells in each month
Now let's look at the first test
1 | it('Find and print how many empty fields there are for each month', () => { |
We are iterating over every month table and count the number of cells with a DIV
inside. Then we subtract it from the total number of cells, computing the number of empty cells. We also print month title. Let's start with just printing the month title. Once we get the month tables, we can iterate over every table, which is a jQuery object.
1 | describe('test calendar', () => { |
The 12 tables are selected
Now we want to find the title for each month. If we inspect the markup, the month's title is in the header cell th.month-title
If you have a jQuery object, you can find the element with a CSS selector directly using the jQuery method $.find
.
1 | cy.get('table.month').each(($table) => { |
What about empty cells? To answer this question, search https://glebbahmutov.com/cypress-examples/ for "empty elements"
This leads you to the page with my Empty elements recipe.
So we can use the CSS selector :empty
to find elements without children elements. Will this work? Let's try it out
1 | cy.get('table.month').each(($table) => { |
Nice
Compare the two numbers
Now let's compare the two numbers: the number of empty table cells with the total number of .day.new, .day.old
cells. We can use a local variable total
to sum the empty cells. All we need to do is to use cy.then(callback)
to use its value. Any time we get something from the web application, we must use cy.then
to use its value.
1 | describe('test calendar', () => { |
And how does our code compare to the initial one?
Any time you are "fighting" the Cypress syntax, take a step back. Maybe you are fighting against the tool and its declarative syntax. If you know what to expect, the test should read naturally. Tip: you can always find Cypress examples and larger recipes by searching https://glebbahmutov.com/cypress-examples/ or cypress.tips/search.