zillow / react-slider

Accessible, CSS agnostic, slider component for React.
https://zillow.github.io/react-slider
MIT License
883 stars 231 forks source link

Slider not changing value when running Cypress tests #304

Closed andrussuitsu closed 9 months ago

andrussuitsu commented 9 months ago

Description

When sending rightArrow keystrokes to slider using Cypress integration test, the value of the slider is not incremented. The keystrokes are registered by the slider because the events are fired but they all have the same value for the first parameter.

Comparing the order of events I see that when running Cypress test the order is: onBeforeChange, OnAfterChange, onChange while when using the slider by a regular user at the browser the order is: onBeforeChange, onChange, onAfterChange.

I am relatively new to using Cypress so I struggle creating a CodeSandbox quickly. I will try to add it but it might take some time.

CodeSandbox

Please provide a CodeSandbox that clearly reproduces the issue. Issues without a CodeSandbox are less likely to get resolved quickly.

Edit zillow/react-slider

andrussuitsu commented 9 months ago

I am now starting to believe that this is not an issue with the Slider component after all. It might be that Cypress is not sending the keyUp event properly. In any case, I am looking elsewhere for a solution.

axelboc commented 9 months ago

I'm also experiencing this after upgrading to React 18. It seems to originate from this line in the move method: https://github.com/zillow/react-slider/blob/master/src/components/ReactSlider/ReactSlider.jsx#L908

// Normally you would use `shouldComponentUpdate`,
// but since the slider is a low-level component,
// the extra complexity might be worth the extra performance.
this.setState({ value }, this.fireChangeEvent.bind(this, 'onChange'));

For some reason, in Cypress, ~the setState callback is never called and the onChange event never fired. As a result, since I use the slider as a controlled component, my local state is not updated and the slider thumb doesn't move.~

EDIT 1: sorry, it's a bit more complicated than that. Will keep investigating and report back. EDIT 2: okay so the onChange event is fired, but it receives a stale value, just like onAfterChange after upgrading to v2.0.5 as explained below. Also, onAfterChange seems to be fired before onChange.

Before v2.0.5, I could work around this by listening also to the onAfterChange event, which was correctly fired with the new value in Cypress.

onChange={(newValue) => { setValue(newValue); }}
onAfterChange={(newValue) => { setValue(newValue); }}

Unfortunately, since v2.0.5, this workaround no longer works because the onAfterChange callback now receives the old value of the slider (i.e. the value before the change). I assume this is a result of this commit: https://github.com/zillow/react-slider/commit/6ca5853341022cfc85e0e114ad893582f29dfb97

Everything works fine outside of Cypress, so there's definitely something slightly different going on in there. Note that I'm using Cypress Testing Library and user-event to simulate arrow key presses:

cy.findByRole('slider', { name: 'My slider' }).type('{upArrow}');
axelboc commented 9 months ago

To summarise, let's consider a scenario with one vertical slider from 0 to 10 (thumb at 0) and the following Cypress command:

cy.findByRole('slider', { name: 'My slider' }).type('{upArrow}');

Cypress triggers the following events on the slider: all kinds of pointer/mouse events (over, move, down...), then click, then keydown, then keyup.

This is what I'm seeing in the debugger:

React 17 + react-slider 2.0.4 or 2.0.5

React 18 + react-slider 2.0.4

React 18 + react-slider 2.0.5