Search code examples
testingautomated-testscypresscypress-intercept

API is called automatically after clicking on an element in Cypress


Given the following code:

  cy.intercept('POST', 'get_time_slots', { fixture: data }).as('getTimeslotList');

  cy.get('input.datepicker').type("2024-01-10").trigger('change');

  cy.get("checkbox#flexCheckDefault").click()

Explaination:

  • The cy.get('input.datepicker').type("2024-01-10").trigger('change') command will trigger the call to the get_time_slots API, which returns a list of timeslot - which is mocked by a fixture file

    Note: Changing the date value is the only way to trigger the api call

  • The cy.get("checkbox#flexCheckDefault").click() command will show the timeslot list to the UI, but the weird things are:

    • It also calls the get_time_slots API 1 more time
    • This behavior doesn't happen if the checkbox is clicked manually via the UI

enter image description here


Components source code:

Date picker

<input 
   placeholder="Select date" type="date"
   class="form-control date-input-custom datepicker"
   t-att-max="state.maxDate"
   t-att-disabled="this.checkDatePickerDisable()"
   t-att-min="state.todayLabel"
   t-on-change="(e) => this.onSelectDate(e.target.value)"
   t-att-value="state.appointment.booking_date" />

The checkbox:

<input
   type="checkbox" value="" 
   id="flexCheckDefault"
   t-on-input="this.showSlot" />

(I got the same issue when using .check() instead of click())

Has anyone experienced this issue before, and how can it be fixed?


Solution

  • I would guess that the double-up of change event occurs because the app is already set up to fire change when the element loses focus.

    This would occur when the second element is clicked, see the docs for .click() at Focus

    Focus

    Focus is given to the first focusable element For example, clicking a inside of a gives the focus to the button...

    If this is true, you can omit the .trigger('change') and add a .blur() instead.

    cy.intercept('POST', 'get_time_slots', { fixture: data }).as('getTimeslotList');
    
    cy.get('input.datepicker').type("2024-01-10")  // see docs - unsafe to chain 
    cy.get('input.datepicker').blur()
    
    cy.wait('@getTimeslotList')  // you have this but have not shown it in the test code
    
    cy.get("checkbox#flexCheckDefault").click()
    

    Docs .type() says

    It is unsafe to chain further commands that rely on the subject after .type()

    This is particularly true if the change event is fired by the app - the DOM is likely to re-render. To be safe, issue another cy.get('input.datepicker') for the next action.