cypress-io / cypress

Fast, easy and reliable testing for anything that runs in a browser.
https://cypress.io
MIT License
46.72k stars 3.16k forks source link

Blur event is not fired reliably in some situations #1176

Closed bahmutov closed 5 years ago

bahmutov commented 6 years ago

bug

Mac, Cypress 1.4.1, Electron and Chrome 63

I have investigated source of failures in Todomvc app some more and found interesting thing. Take a look at https://github.com/cypress-io/cypress-test-tiny/tree/blur-test (I put entire Ampersand TodoMVC there in the branch blur-test, you can just open ampersand/index.html to see and test).

The test adds 3 todos, edits second, then checks if the local storage has been updated with new title text.

it('edits todo', () => {
  createDefaultTodos()
  // let everything settle
  cy.wait(1000)

  visibleTodos()
    .eq(1)
    .find('label')
    .dblclick()

  // clear out the inputs current value
  // and type a new value
  visibleTodos()
    .eq(1)
    .find('.edit')
    .should('have.value', 'bar')
    .clear()
    .type('buy some sausages{enter}')
  cy.wait(1000)

  // confirm that new value is in localStorage
  cy
    .window()
    .its('localStorage')
    .its('todos-ampersand')
    .then(JSON.parse)
    .should('have.length', 3)
    .its('1')
    .its('title')
    .should('equal', 'buy some sausages')
})

When running in Electron or Chrome browser with Devtools closed, the test passes. I can open DevTools AFTER the test and see the "enter" + "blur" events triggered and propagating into the app.

screen shot 2018-01-09 at 3 10 24 pm screen shot 2018-01-09 at 3 10 35 pm

If I open DevTools but keep the FOCUS on the app iframe or on the command log and reload the tests, they still work. But if I click on the devtools, for example into the console tab and reload the tests, the "blur" event is not fired anymore and the test fails

screen shot 2018-01-09 at 3 11 22 pm

Probably related to blur event is the run mode. It just fails 100%

screen shot 2018-01-09 at 3 12 15 pm

If I could see console.log messages during this run (https://github.com/cypress-io/cypress/issues/448) it could shed some light

DanielMSchmidt commented 6 years ago

Hey there, I think I have a similar issue with focussing a field. I created a small demo if you check this repo out, run npm install and then cypress open the test works, if you run cypress run it fails. Maybe this helps to reproduce the issue 👍

kuceb commented 6 years ago

This might be fixed by #1939 , can anyone confirm the bug on 3.0.2?

kuceb commented 6 years ago

@DanielMSchmidt there is actually a problem with using the jquery *:focus selectors. Instead you should use cy.getFocused().should(... as that uses document.activeElement under the hood, and is more consistent and has better performance than searching the DOM for :focus.

The change event not firing is something specific to the framework and i'm not sure why it's failing

warpdesign commented 5 years ago

@Bkucera I am having the same problem: the blur event isn't sent in some situations, I'm using Cypress 3.1.3 on macOS (mojave).

Here is what I noticed:

If the Chrome window where the Cypress test gets executed is active, the event is correctly sent/received by my app, but if the window isn't the active one or if I click on the Chrome's devtools area before the test is ran, the blur event isn't received.

Here is the test:

        cy.get('#view_0 [data-cy-path]')
            .type('/{esc}')
            .should('have.value', '');

My app is a React app that does this:

    private onKeyUp = (event: React.KeyboardEvent<HTMLElement>) => {
        console.log('path keyup', event.keyCode);
        if (event.keyCode === KEYS.Escape) {
            event.nativeEvent.stopImmediatePropagation();
            // lose focus
            this.input.blur();
        } else if (event.keyCode === KEYS.Enter) {
            this.onSubmit();
        }
    }

My input element also has an onBlur event which is never triggered if the Chrome window is not active while the tests are being run.

Note that this doesn't happen in real life since the Chrome window must be active for the user to type something into an input.

Hope this helps.

kuceb commented 5 years ago

This should fixed by PR #2982 We now polyfill focus/blur events that would otherwise be queued by the browser until it regains focus.

cypress-bot[bot] commented 5 years ago

The code for this is done in cypress-io/cypress#2982, but has yet to be released. We'll update this issue and reference the changelog when it's released.

hereiscasio commented 5 years ago

Hi, i also face the same issue, that's,

cy.get(...).type(...)

when Cypress's browser is not the active browser

then seems like type() will fire blur event, but if Cypress's browser is under focusing, type() works great

at now, how can we user solve this issue . . . 😔 ? i test this wired behavior 10x times

cypress-bot[bot] commented 5 years ago

Released in 3.3.2.

drumslave-git commented 4 years ago

Hi, i also face the same issue, that's,

cy.get(...).type(...)

when Cypress's browser is not the active browser

then seems like type() will fire blur event, but if Cypress's browser is under focusing, type() works great

at now, how can we user solve this issue . . . 😔 ? i test this wired behavior 10x times

can someone answer this please? I have a lot of logic based on blur event, and it is hard to work with tests because of that.

jennifer-shehane commented 4 years ago

@drumslave-git This issue is closed and has been resolved. If you are seeing a bug in Cypress, open a new issue with a reproducible example. If this is a question, we recommend questions relating to how to use Cypress be asked in our community chat.