Adding a Global Function to Cypress for a Date {num} Months Ago
I’m working on a COVID-19 booster shot registration form. On this form I ask the user when they received their last COVID-19 vaccine shot. This is three simple fields (the month values are 01, 02, 03, etc.):
Each vaccine brand (Pfizer, Moderna, J&J) has different eligibility criteria as it relates to the time since the individual received their original vaccine series. Pfizer, for example, is 6 months. My form needs to reject a user who says they received Pfizer less than 6 months ago.
Using Cypress I wanted some test coverage of this functionality. Original I had hard-coded a date value of 5 months ago:
1 2 3 |
cy.get('select[name="datelastvax_month"]').select('08'); cy.get('select[name="datelastvax_day"]').select('01'); cy.get('select[name="datelastvax_year"]').select('2021'); |
As you can imagine this would work well for a while. Fast-forward a few months from now… the time ago will eventually be more than 6 months ago. I don’t want to have to keep updating this code with a recent date. The obvious solution is to dynamically choose the dates based on the current date. A global helper function would be ideal as I need to use this in many tests. Here’s a simple solution:
Step 1: Define the Function in index.js
TheĀ support/index.js file is loaded before each Cypress run. Creating a global function here is a quick way to introduce a reusable piece of code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/** * Returns a simple object for {num} months ago, containing YYYY, MM, DD. * * @param {number} num * Number of months to subtract from current date. * * @return object * Object containing three properties (year:YYYY, month:MM, day:DD) */ cy.getDateMonthsAgo = (num) => { const dateObj = new Date( new Date().getFullYear(), new Date().getMonth() - num, new Date().getDate() ); return { year: dateObj.getFullYear().toString(), month: ('0' + (dateObj.getMonth() + 1)).slice(-2), day: ('0' + dateObj.getDate()).slice(-2), } } |
There are many solutions to handle getting a date from {num} months ago. If you start looking around for “What is a month, really?” you will find many different opinions. The code I’m using above responds like most humans do: give the same day of the month from {num} months ago. With a {num} of 5 (five months ago), on October 25, 2021 the result would be May 25, 2021.
WARNING: Please note the following:
1 2 3 4 5 |
new Date(2021, 1, 28) ==> February 28, 2021 new Date(2021, 1, 29) ==> March 1, 2021 new Date(2021, 1, 30) ==> March 2, 2021 new Date(2021, 1, 31) ==> March 3, 2021 new Date(2021, 1, 32) ==> March 4, 2021 |
Step 2: Use the Function
1 2 3 4 |
const fiveMonthsAgo = cy.getDateMonthsAgo(5); cy.get('select[name="datelastvax_month"]').select(fiveMonthsAgo.month); cy.get('select[name="datelastvax_day"]').select(fiveMonthsAgo.day); cy.get('select[name="datelastvax_year"]').select(fiveMonthsAgo.year); |