cypress: Inconsistant and invalid Events Typing using cypress

Current behavior:

Testing a code who used event instanceof KeyboardEvent, I’ve seen some strange behavior, digging up, it seems that there is some strange inconsistencies between the events triggered and also into the way they are sent to the eventListener.

Desired behavior:

Consistent behavior:

  • .type
  • .trigger({..., type: 'keydown'})
  • .get('#element').then(element.dispatchEvent(new KeyboardEvent('keydown', ...)))

Should all send a KeyboardEvent type event.

And the eventListener:

element.addEventListener('keydown', (event) => (event instanceof KeyboardEvent));

Should always return true.

Steps to reproduce: (app code and test code)

I’ve tested three different methods: cy.type, cy.trigger, cy.get('#element').then( element.dispatchEvent).

And two different eventListener for each test:

  1. One directly into a <script> inside the html page itself
  2. One created into the test itself using cy.get -> addEventListener

You can find MWE here: https://github.com/avallete/cypress-test-tiny-event-bug

Simply run:

npm install
npm run cypress:open

# Then run the test and check the console.log inside the debuging tools.
# Each test is a specific case the 2 first show that event is type Event instead of KeyboardEvent.
# The third test show the inconsistency of the same eventListener if it's declared inside the test or outside (into the html <script>).

Versions

3.6.1, Linux, Chromium 78 / Electron 73

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 1
  • Comments: 17 (14 by maintainers)

Most upvoted comments

Before I go fix cy.trigger(), I want to ask this question. When does this consistency necessary? Can I get some real world use cases?

I’m running into this issue because I have some Rust code which uses typed bindings to DOM APIs. The bindings provide a number of type definitions generated from WebIDL, and it’s possible to cast between JS types. By default those casts use instanceof checks before returning to catch common bugs.

I have event handler helpers that take a typed callback and perform the conversion under the hood for the user. Elsewhere there are definitions mapping strings like "keydown" to types so that the callbacks always have the correct type. This works quite nicely “in production” so far but breaks when using cypress to enter text due to this issue.

I’ve had mixed results with removing the checks as it seems the bindings may rely on prototypes for doing their property lookups. The easiest fix that’d allow me to use cypress would be to emit an event with the correct prototype in its chain.

EDIT: I should also note that https://github.com/cypress-io/cypress/pull/8255 will address the most common cases.

There are 3 problems in this issue:

  • Event -> `KeyboardEvent: Actually, this is also the solution for the #6125. I need to investigate what’s the real problem in that code. And it’ll be fixed with it. => #8255
  • cy.window() issue: I think it should be written in FAQ, cy.window(), and/or The Test Runner. => cypress-io/cypress-documentation#3073.
  • trigger issue: it should be treated separately.

Investigating a little bit on this issue, I’ve been able to found what seem to be the root of the behaviour I describe on this issue:

https://github.com/cypress-io/cypress/blob/6749a0edc69a0052497e3a12766723274d78a135/packages/driver/src/cy/keyboard.ts#L892

Replacing the win['Event'] by win['KeyboardEvent'] on this line, make the .type function to properly send an event which is instanceof KeyboardEvent into the tests.

But looking on the comment on top of this line, this fix may lead to some regression on Chrome < 63.