Cypress: Change event is not fired on number input

Created on 9 Jan 2018  路  19Comments  路  Source: cypress-io/cypress

  • Operating System: MacOs
  • Cypress Version: 1.4.1
  • Browser Version: Chrome 63 & Electron 53
  • React: 16.2.0

Is this a Feature or Bug?

Bug

Current behavior:

Change event is not fired on "number" type inputs after .type() nor .click() or .focus() to other element.
It works fine with "text" input types

Desired behavior:

Change event should fire with number input just like with text input type

How to reproduce:

https://stackblitz.com/edit/react-byhe3e?file=index.js

App code:

import React, { Component } from 'react';
import { render } from 'react-dom';

class App extends Component {
  state = {
    inputTextValue: '',
    inputNumberValue: ''
  };

  handleTextChange = (event) => {
    this.setState({ 
      inputTextValue: event.currentTarget.value,
    });
  }

 handleNumberChange = (event) => {
    this.setState({ 
      inputNumberValue: event.currentTarget.value,
    });
  }

  render() {
    return (
      <div>
        <div>
          Input text: {this.state.inputTextValue} <br/>
          <input id="textInput" onChange={this.handleTextChange } value={this.state.inputTextValue} type="text" /> <br/><br/>
        </div>
        <div>
          Input number: {this.state.inputNumberValue} <br/>
          <input id="numberInput" onChange={this.handleNumberChange } value={this.state.inputNumberValue} type="number" />
        </div>
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));

Test code:

describe("Change event bug repro", function() {
    it("Should fire change on textInput", function() {
        cy.visit("https://react-byhe3e.stackblitz.io");

        cy
            .get("#textInput")
            .type("hello")
            .should("have.value", "hello");
        cy.get("#inputTextValue").contains("hello");
    });

    it("Should fire change on numberInput entering integers", function() {
        cy
            .get("#numberInput")
            .type("1234.56")
            .should("have.value", "1234");
        cy.get("#inputNumberValue").contains("1234.56");
    });

    it("Should fire change on numberInput entering decimals", function() {
        cy
            .get("#numberInput")
            .type("1234.56")
            .should("have.value", "1234.56");
        cy.get("#inputNumberValue").contains("1234.56");
    });
});

Additional Info (images, stack traces, etc):

related issue: https://github.com/cypress-io/cypress/issues/816
test results:
image

pkdriver bug

Most helpful comment

Thanks for sharing. Our app is a single page app (React).
As a quick-n-dirty workaround, I fixed my Cypress test suite by casting the input to a type="text":

cy
    .get('input[name="birthDate"]')
    .type('1970-06-15')
    .should('have.value', '1970-06-15') // Failed assertion

// Workaround, cast to "type"
cy
    .get('input[name="birthDate"]')
    .invoke('attr', 'type', 'text')
    .should('have.value', '1970-06-15') // Successful assertion

It looks like that the change event now fires, which triggers form validation (use case: form validation using mobx-react-form).

Also, wrapped up:

cy
    .get('input[name="birthDate"]')
    .invoke('attr', 'type', 'text') // Cast
    .type('1970-06-15')
    .should('have.value', '1970-06-15') // Successful assertion

All 19 comments

Appreciate you putting together a detailed bug report. We'll look at this.

I accidentally found what's going on.
The event isn't triggered when I pass string to type(), if I pass number then events are firing.
Although the behaviour is weird and works different than browser when passing string even if it contains only numbers

UPDATE: @GavinThompson is right, events are not triggered when the value contains a decimal point. I've updated the test case to demonstrate the issue

Just to piggyback on this really detailed bug, I'm actually encountering the same bug with number fields and change events not firing. Specifically however I believe it's only happening when the input contains a decimal (at least in our case).

If I use the following command cy.get('#price').type('9122') and log the changes I can watch the following logs scroll by in Cypress:

Price change output on number field: 9
Price change output on number field: 91
Price change output on number field: 912
Price change output on number field: 9122

When I change the command to include a decimal -- cy.get('#price').type('9122.99') I get the following:

Price change output on number field: undefined
Price change output on number field: undefined
Price change output on number field: ....etc

This works with or without single quotes around the number in question.

I'd like to add that we are having this same issue, but for <input type="date" /> fields, even when typing the date with the Date Input format noted in the cypress docs: "YYYY-MM-DD".

@mjfaga I think I'm experimenting the same issue with <input type="date" />. Have you been able to find a workaround by chance?
Date input value is being cleared in the DOM despite a should('have.value') assertion is successful. I can only reproduce this issue when filling form in cypress - I'm still trying to figure out if this is a cypress bug, or somewhere down in my app. Will reply if I find a workaround/fix.

@jbmusso I can reproduce this by running the following in my console...

const datePicker = document.querySelector('input[type="date"]');
datePicker.value = "2015-01-01";

...and then clicking the submit button on my form manually.

From the research I've done, it comes down to that fact that doing what I note above doesn't trigger the react life cycle events, so the react change event is never fired, and therefore, the field doesn't technically have a value as a result.

I can get things working when using ReactTestUtils.Simulate.change(datePicker); in a debug session, but I haven't found a way to hook that up properly in cypress to get things to execute properly.

That is as far as I've gotten thus far. No work around yet.

Thanks for sharing. Our app is a single page app (React).
As a quick-n-dirty workaround, I fixed my Cypress test suite by casting the input to a type="text":

cy
    .get('input[name="birthDate"]')
    .type('1970-06-15')
    .should('have.value', '1970-06-15') // Failed assertion

// Workaround, cast to "type"
cy
    .get('input[name="birthDate"]')
    .invoke('attr', 'type', 'text')
    .should('have.value', '1970-06-15') // Successful assertion

It looks like that the change event now fires, which triggers form validation (use case: form validation using mobx-react-form).

Also, wrapped up:

cy
    .get('input[name="birthDate"]')
    .invoke('attr', 'type', 'text') // Cast
    .type('1970-06-15')
    .should('have.value', '1970-06-15') // Successful assertion

In my situaion,

cy.get('input').type('10.0001').trigger('blur');

I set something for input#onBlur, but seems input#onChange didn't work when with decimals

This issue will be fixed in PR #2016 along with many other cy.type() improvements

It seems that the issue still occurs on the current version

type: "number"
pattern: "^([0-9]{6})$"

Removing both accepts the values.

@ervicsangel are you saying using the pattern attribute will not lead to desired behavior? or any number input?

@ervicsangel are you saying using the pattern attribute will not lead to desired behavior? or any number input?

The scenarios are:

  • Using the pattern I mentioned earlier: No input was accepted in the UI but it was logged in the commands panel

    • Assigning the type as number: Ditto

    • Using pattern and assigning the type as number: Ditto

    • Removing both: Input was typed

The test data provided is merely '222222'

UPDATE: I just found out that it does not work when using mat-form-field. I tried rerunning it against a simple input box and it worked; changing it back to mat-form-field (textbox), the issue recurred.

Cheers

@ervicsangel can you provide a reproducible example using the mat-form-field element? What library is that component from? Possibly just link us to the demo of the component if it's in documentation somewhere

I think it was because the maxLength was not explicitly set. As I did so, it worked not just using Cypress but also in IE. I think that's enough for now, thanks.

Cheers

Thank you. I was getting frustrated with my decimals not typing in and just by upgrading I got past it..

I'd like to add that we are having this same issue, but for <input type="date" /> fields, even when typing the date with the Date Input format noted in the cypress docs: "YYYY-MM-DD".

I have the issue that in browser the input field is
<input type="date">
but when Cypress is running browser the input field is
<input type="text">
Why is it?

I'm using Cypress with the following versions (installed yesterday):

Cypress package version: 3.5.0
Cypress binary version: 3.5.0

Using .type('yyyy-mm-dd') on an input type=date does not fire React's onChange event.

Worked around by manually triggering by calling .trigger('change')

This issue will be closed to further comment as the exact issue here was resolved and tested.

If you're experiencing a bug similar to this in Cypress, please open a new issue with a fully reproducible example that we can run. There may be a specific edge case with the issue that we need more detail to fix.

Was this page helpful?
0 / 5 - 0 ratings