I want to test a calendar using cypress but it is not possible to select the date I need or any date, the ideal is a dynamic code, where I can enter number of days and it will select the correct number.
I am using this code and I am getting a error saying 'Cannot read property 'includes' of undefined'
let date = new Date()
date.setDate(date.getDate() + 5)
let futureDay = date.getDate()
console.log(futureDay)
let futureMonth = date.toLocaleString('default', { month: 'long' })
cy.get('.flatpickr-current-month')
.invoke('attr', 'flatpickr-monthDropdown-month')
.then(dateAttribute => {
if (!dateAttribute.includes(futureMonth)) {
cy.get('.flatpickr-next-month').click()
} else {
cy.get('.dayContainer')
.contains(futureDay)
.click()
}
})
I am able to add unique attributes in the elements if necessary (I tried and still it did not worked). I was well tried a more simples code as:
cy.get('#inception_date').click()
cy.get('.flatpickr-days > .dayContainer',)
.contains('17')
.click({force: true})
cy.get('#inception_date')
.invoke('prop', 'value')
.should('contain', '2021-07-17')
and in this code I get an error of Timed out retrying after 4000ms: expected '2021-07-27' to include '2021-07-17' because it does not select the any date, it continues to be the date of today.
I am attaching 2 images if the DOM, maybe it can help to figure out what is the issue on my code.
Looking at the examples for flatPickrJS, you want
let date = new Date() // July 28
date.setDate(date.getDate() + 5) // Aug 2
let futureDay = date.getDate() // get 2 (integer)
let futureMonth = date.getMonth() // gets 6 (integer) for July
cy.get('.flatpickr-current-month select') // <select> is nested inside
.invoke('val') // this is the currently selected month
.then(dateAttribute => { // this is "6" for July (months are 0-based)
if (+dateAttribute !== futureMonth) { // +dateAttribute converts string to integer
cy.get('.flatpickr-next-month').click() // change month to Aug
}
cy.get('.dayContainer') // selects Aug 2
.contains(new RegExp(`^${futureDay}$`)) // which is July 28
.click() // plus 5 days
})
cy.get('input.flatpickr')
.invoke('val')
.should('eq', '2021-08-02') // passes
Summary of changes
get the numeric futureMonth not the string month name.
get the value of the current month from the <select>
using .invoke('val')
.
compare current month to futureMonth, if not the same click next-month button.
take the day container click out of } else {
, because you always need to select the day.
NOTE
Thanks to @SyedMuhammadAwais for finding a bug in the day selection code.
Using .contains(futureDay)
does a partial match, but the calendar sometimes shows some days from the previous month, but they are disabled (not clickable).
So, if futureDay === 6 and the 26th of the previous month is showing, this disabled day will be selected and fail the test.
The solution is to use an exact text match, which can be done with a regex like this
.contains(new RegExp(`^${futureDay}$`))