Test IonRange in Cypress

Issue

It is interesting, that such standard behaviour in such a standard component is so hard to test.

Given an IonRange element in my Ionic React component:

<IonRange
  min={0}
  max={30}
  onIonInput={()=> console.log("changed")}
/>

When I manually test the IonRange, I get the console output as expected.
However, when I have my cypress test like this (pretty much copied over from the docs):

cy.get("ion-range")
  .as('range')
  .invoke('val', 10)
  .trigger('change')

I expect to see the log statement in the output.

Actual behaviour: the range knob jumps to the expected position but the onIonInout callback is never invoked.

I also tried other triggers, such as

  .trigger('ion-change')
  .trigger('input')
  .trigger('ion-input')
  .trigger('range-change')
  .trigger('ionChange')
  .trigger('ionInput')

all leading to the same behaviour.

I also tried to workaround using arrow keys.
That would be a very unsatisfying solution, because it does not generalise for cases with ranges of, say, 0 to 10,000. I tried it anyway:

cy.get("ion-range").type('{rightArrow}') // trows "this is a non-typable element"

The range knob jumps to the centre (weirdly).

The workaround that I ended up with is:

cy.get("ion-range").click() // clicks in the centre 

(also mentioned by @SuchAnIgnorantThingToDo-UKR)
and then I expect the value 15. But due to differences in rendering resolutions (even with a set viewport), the result flakes between 15 and 16. Also, this solution is very unsatisfying given we might want to assert for specific values)

I reviewed the following:

Please let me know if you have any idea for this very trivial every-day problem.

Solution

@SuchAnIgnorantThingToDo-UKR already answered in great detail.

I just want to add how to test the dragging. You can do this:

describe('Components', () => {
  it('ion-range', () => {
    cy.visit('https://ionicframework.com/docs/usage/v7/range/basic/demo.html?ionic:mode=ios')

    cy.get('ion-range').as('slider')

    const waitTime = 200

    cy.get('@slider') //
      .trigger('mouseenter')
      .wait(waitTime)
      .trigger('mousedown', 100, 0)
      .wait(waitTime)
      .trigger('mousemove', 150, 1, { force: true })
      .wait(waitTime)
      .trigger('mousemove', 200, 1, { force: true })
      .wait(waitTime)
      .trigger('mousemove', 300, 1, { force: true })
      .wait(waitTime)
      .trigger('mouseup', 300, 1)
  })
})

Answered By – Darko Riđić

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published