简体   繁体   中英

Cypress does not select a date on calendar

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}$`))

This is the correct code with some amendments in code of @Steve Zodiac

date.setDate(date.getDate() + 8)
let futureDay = date.getDate()
let futureMonth = date.getMonth()
cy.log(futureDay)               // get 6 (integer)
cy.log(futureMonth)            // gets 7 (integer) for August
cy.get('input[placeholder="Day"]').click({force:true})
cy.wait(5000)
cy.get('.flatpickr-current-month > select > option').eq(0)    
  .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({force: true}
    }

    cy.get('.dayContainer')                    // selects Aug 6
      .contains(new RegExp(futureDay, "g"))
      .click({force:true})                                 // plus 8 days
  })

Here is my solution for the datepicker "previous days" exist or not issue when testing with Cypress.

Cypress.Commands.add(
    'selectDate',
    (picker, date) => {
        
        let pickerDate = date.split('-')
        let year = pickerDate[0]
        let month = pickerDate[1]
        let day = pickerDate[2]

        cy.get(picker).click()

        cy.get('.numInput.cur-year').eq(0).filter(':visible').clear().type(year)
        let selectedMonth = parseInt(month, 10)
    
        cy.get('.flatpickr-monthDropdown-months')
            .eq(0)
            .select(selectedMonth - 1)

        //set day -> count how many 'prevMonthDay' is int the calendarMonth and add the number to the day we wants
        //filtering here for get the correct day
        // if there is any prev day !!
        cy.get('.flatpickr-rContainer')
            .then($body => {
                if ($body.find('.flatpickr-day.prevMonthDay').length) {
                    return ['.flatpickr-day.prevMonthDay', ($body.find('.flatpickr-day.prevMonthDay').length).toString()];
                }else{
                    return ['.flatpickr-day', '0'];
                }
            })
            .then(selector => {
                if(selector[0] === '.flatpickr-day.prevMonthDay'){
                    cy.log('prev days')
                    cy.get(`.dayContainer span:nth-child(${parseInt(day, 10) + parseInt(selector[1])})`)
                        .eq(0)
                        .click()
                }else{
                    cy.log('no prev days')
                    cy.get(`.dayContainer span:nth-child(${parseInt(day, 10)})`)
                        .eq(0)
                        .click()
                }
            });
    }
)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM