Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cypress' type() not compatible with react 15.6's onChange? #536

Closed
arthens opened this issue Jun 15, 2017 · 13 comments
Closed

Cypress' type() not compatible with react 15.6's onChange? #536

arthens opened this issue Jun 15, 2017 · 13 comments
Assignees
Milestone

Comments

@arthens
Copy link

arthens commented Jun 15, 2017

  • Operating System: Mac os X and Linux
  • Cypress Version: 0.19.2 (app) and 0.13.1 (cli)
  • Browser/Browser Version: Chrome 58

Are you requesting a feature or reporting a bug?

Bug

Our cypress tests started to fail when we bumped react from 15.5.4 to 15.6.1. We debugged the problem and came to the conclusion that onChange doesn't fire as it should when the input field is being manipulated using .type('some text').

cli + headless chrome: broken
app + real chrome: broken
user interacting with the browser: working

React component:

<input
    className="input-text"
    onChange={() => {
        // this will executed with react 15.5.4, but not with 15.6.1
    }}
    value={this.props.value}
    type="text"
    data-stock-url />

and this is how we are manipulating it

cy.visit('https://...')
    .get('[data-stock-url]').type('https://google.com/stock/123')

onChange doesn't fire anymore. The problem went away when we downgraded back to 15.5.4.

Not sure if related, but react-dom's CHANGELOG says:

  • Fix issues with onChange not firing properly for some inputs. (@jquense in #8575)

which is suspicious. Is cypress' type() relying on an implementation detail that is not true anymore?

@arthens arthens changed the title Cypress' type() not compatible with react 15.6 onChange? Cypress' type() not compatible with react 15.6's onChange? Jun 15, 2017
@brian-mann
Copy link
Member

Cypress doesn't rely on any specific JS frameworks' implementation. It's firing events at the lowest possible level.

We'll take a look at this. In 0.20.0 we have many fixes going out for cy.type, so we'll first see if it's a new potential problem.

We use React internally on all of our projects. @chrisbreiding can you look at this?

@jquense
Copy link

jquense commented Jun 15, 2017

The input logic in React now dedupe's change events so they don't fire more than once per value. It listens for both browser onChange/onInput events as well as sets on the DOM node value prop (when you update the value via javascript). This has the side effect of meaning that if you update the input's value manually input.value = 'foo' then dispatch a ChangeEvent with { target: input } React will register both the set and the event, see it's value is still `'foo', consider it a duplicate event and swallow it.

This works fine in normal cases because a "real" browser initiated event doesn't trigger sets on the element.value. You can bail out of this logic secretly by tagging the event you trigger with a simulated flag and react will always fire the event. https://github.com/jquense/react/blob/9a93af4411a8e880bbc05392ccf2b195c97502d1/src/renderers/dom/client/eventPlugins/ChangeEventPlugin.js#L128

@KittyGiraudel
Copy link
Contributor

I can confirm this problem is happening.

@brian-mann
Copy link
Member

We've been able to reproduce and fix it. We're going to release an 0.19.4 patch with just this fix in it.

@arthens
Copy link
Author

arthens commented Jun 15, 2017

Thank you @brian-mann

@KittyGiraudel
Copy link
Contributor

Thank you for your quick work. :)

@chrisbreiding
Copy link
Contributor

Thanks for the timely info, @jquense! That helped a lot.

@brian-mann
Copy link
Member

Fixed in 0.19.4.

@brian-mann brian-mann added this to the 0.19.4 milestone Jun 19, 2017
@kevinch
Copy link

kevinch commented Jun 28, 2017

@brian-mann i'm having the same issue in a non-related project. Could you share the way you fixed this? I'm guessing you switched from input radio to <button> or <a> tags? Or did you manage to keep the radios and get the onChange event to fire on each click? Thanks in advance.

@jquense
Copy link

jquense commented Jun 28, 2017

@brian-mann btw if you used my simulated workaround I'd bring your use case up to on React team. That has been removed in v16.

@brian-mann
Copy link
Member

We did use the simulated hack just to get out the patch immediately (because we created several tests for it and they all pass)

However we thought about it later and have a "real" fix being implemented that's not React specific, and should actually fix the problem permanently...

This is from my notes:

screen shot 2017-06-28 at 11 21 38 am

@brian-mann
Copy link
Member

To clarify I don't think the react team needs to make this change. We determined the exact situation where Cypress deviates from the way a real browser behaves. A real browser will NOT call the value setter when changes the value from a default action. It will just "magically" update.

Since we call the setter (this is the difference). However as long as we call the original setter (that 3rd party code cannot possibly get notified of) we'll essentially reproduce the real browser behavior without needing any 3rd party library to change the way it works.

@jquense
Copy link

jquense commented Jun 28, 2017

sounds great :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants