I'm writing my bachelor thesis about e2e testing in JavaScript although I'm not familiar with testing or JavaScript.
There is range-type input "slider" in the DOM I'm testing:
<input id="sum_slider"
class="input-range js-inv-calc-input-sum-range js-input-range"
type="range" name="investmentsum"
min1="20000"
max="150000"
value="20000"
step="1000"
title="Investitionsbetrag"
style="background: -webkit-linear-gradient(left, rgb(255, 196, 0) 0%, rgb(255, 196, 0) 0%, rgb(119, 119, 119) 0%) no-repeat;">
The Cypress Documentation suggests this
cy.get('input[type=range]').as('range')
.invoke('val', 25)
.trigger('change')
cy.get('@range').siblings('p').should('have.text', '25')
I tried this:
cy.get('#sum_slider[type=range]').as('range')
.invoke('val', 0%)
.trigger('change')
I am choosing the percent values because the two last percent values are the only ones that change when using the slider manually.
I'm writing my bachelor thesis about e2e testing in JavaScript although I'm not familiar with testing or JavaScript.
There is range-type input "slider" in the DOM I'm testing:
<input id="sum_slider"
class="input-range js-inv-calc-input-sum-range js-input-range"
type="range" name="investmentsum"
min1="20000"
max="150000"
value="20000"
step="1000"
title="Investitionsbetrag"
style="background: -webkit-linear-gradient(left, rgb(255, 196, 0) 0%, rgb(255, 196, 0) 0%, rgb(119, 119, 119) 0%) no-repeat;">
The Cypress Documentation suggests this
cy.get('input[type=range]').as('range')
.invoke('val', 25)
.trigger('change')
cy.get('@range').siblings('p').should('have.text', '25')
I tried this:
cy.get('#sum_slider[type=range]').as('range')
.invoke('val', 0%)
.trigger('change')
I am choosing the percent values because the two last percent values are the only ones that change when using the slider manually.
Share Improve this question edited Nov 4, 2024 at 10:12 Marty Martin 1495 bronze badges asked Mar 6, 2019 at 12:43 user8995745user89957453 Answers
Reset to default 6You must set the value to a number
not a percent. You should take a look at the element and see what values are valid. Usually there is a min
and max
attribute on the element.
Notice those attributes on your element
<input id="sum_slider" class="input-range js-inv-calc-input-sum-range js-input-range" type="range" name="investmentsum" min="20000" max="150000" value="20000" step="1000" title="Investitionsbetrag" style="background: -webkit-linear-gradient(left, rgb(255, 196, 0) 0%, rgb(255, 196, 0) 0%, rgb(119, 119, 119) 0%) no-repeat;">
So with your element, the value you set must be between 20000
and 150000
. The following should work:
cy.get('input[type=range]')
.invoke('val', 20001)
.trigger('change')
Kuceb's answer is still valid, but the example he gives fails because the test must not only obey the min and max range values but also the step must be correct in the test.
Kuceb increments the slider by 1, but the step is 1000.
Run with a value that's an increment of step
and the example passes:
cy.get('input[type=range]')
.invoke('val')
.should('eq', '20000')
cy.get('input[type=range]')
.invoke('val', 100_000)
cy.get('input[type=range]')
.invoke('val')
.should('eq', '100000')
Note in the current Cypress version 13.15.1 you don't need to trigger a change event.
These are the before and after snapshots of the slider
A custom mand to check min, max, and step
Cypress.Commands.add('range', (selector, value) => {
const log = Cypress.log({displayName:'range', message: selector})
if (value) {
log.set({message: `${log.get('message')} - setting to ${value}`})
const min = +Cypress.$(selector).attr('min')
const max = +Cypress.$(selector).attr('max')
const step = +Cypress.$(selector).attr('step')
if (min && value < min) {
throw new RangeError(`Requested value ${value} is below the range minimum ${min}`)
}
if (max && value > max) {
throw new RangeError(`Requested value ${value} is above the range maximum ${max}`)
}
if (step && (value % step) !== 0) {
throw new RangeError(`Requested value ${value} is not a multiple of the range step ${step}`)
}
Cypress.$(selector).val(value)
}
return Cypress.$(selector).val()
})
Usage
cy.range('input[type=range]')
.should('eq', '20000')
cy.range('input[type=range]', 100_000)
.should('eq', '100000')
With a valid value:
With an incorrect test value for the configured step:
Five years later this could not be solved. Here is a work around:
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
window.HTMLInputElement.prototype,
"value"
).set
cy.get('input[type="range"]')
.then(($range) => {
// get the DOM node
const range = $range[0]
// set the value manually
nativeInputValueSetter.call(range, 50)
// now dispatch the event
range.dispatchEvent(
new Event("change", { value: 50, bubbles: true })
)
})
cy.wait(2000)
// assert that the value has been changed
cy.get("input[type='range']").should("have.value", 50)
What this basically does is that it retrieves the browser's native value setter for the input elements to directly set the slider's value using the native method which bypasses any interference from React's control. It then dispatches a change event to notify the app of the update, ensuring that any event listeners respond to the new value.
Please refer here and join the discussion.