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

cy.focused() inconsistent behavior #752

Closed
verheyenkoen opened this issue Oct 17, 2017 · 17 comments
Closed

cy.focused() inconsistent behavior #752

verheyenkoen opened this issue Oct 17, 2017 · 17 comments
Labels
pkg/driver This is due to an issue in the packages/driver directory type: bug
Milestone

Comments

@verheyenkoen
Copy link
Contributor

  • Operating System: Mac OS X Sierra
  • Cypress Version: 1.0.2
  • Browser Version: All

Is this a Feature or Bug?

Bug

Current behavior:

cy.focused() does the right thing when you keep the Cypress UI window focused. It does the wrong thing if you blur the Cypress UI window or if you run headlessly.

Desired behavior:

cy.focused() should produce consistent results, regardless of being run headed/headless or focused/blurred.

How to reproduce:

https://github.com/verheyenkoen/cypress-focused-issue

@verheyenkoen verheyenkoen changed the title cy.focused() is inconsistent behavior cy.focused() inconsistent behavior Oct 17, 2017
@jennifer-shehane jennifer-shehane added pkg/driver This is due to an issue in the packages/driver directory type: bug labels Oct 17, 2017
@jennifer-shehane
Copy link
Member

I'm curious if chai-jQuery's newer .should.have.focus() would highlight some of the issues with our cy.focused() command when run headlessly. chaijs/chai-jquery#73

@jennifer-shehane
Copy link
Member

@brian-mann
Copy link
Member

We don't use chai-jquery anymore, nor did we ever support have.focus. Under the hood Cypress tries to normalize the focus behavior of a browser and for that we have to control the API's which return the focusable element. We store them internally as opposed to use the native DOM API's for this.

@verheyenkoen
Copy link
Contributor Author

Can you think of any workarounds?

@dwelle
Copy link

dwelle commented Oct 25, 2017

We don't use chai-jquery anymore

@brian-mann meaning these docs are out of date, and you implement the chai-jquery natively (via the string args in .should())?

I also second the OP -- currently cy.focused() yields window object (in some(?) cases) ).

IMO cy.focused() should correctly yield focused element.

Meanwhile, it can be done like this:

// get focused element
cy.get(":focus")

// assert if yielded element has focus
cy.get( selector ).should( $elem => {
    expect( $elem.is(":focus") ).to.be.true;
})

@brian-mann
Copy link
Member

We technically do not use chai-jquery anymore. We rewrote the API and fixed a lot of things - but it behaves almost identically to what is currently documented on chai-jquery. We haven't updated the docs because its debatable what the docs should actually document.

Here's the code:
https://github.com/cypress-io/cypress/blob/develop/packages/driver/src/cypress/chai_jquery.coffee

The problem with focus in general is that it behaves differently whether or not the:

  • browser is actually in focus
  • the actual window of the frame is in focus
  • or the dev tools are open

Because of this we normalized the focus behavior (or at least attempted to) with cy.focused(). When you call cy.focus() on an element that does not receive focus due to the above listed reasons - we not only normalize the event and fire all of the appropriate events but we keep track of the state of the 'focused' element internally. That enables us to then fire the proper 'blur' events when the element should have lost focus.

What we do is basically a polyfill for when the browser doesn't do the "right thing" just because its out of focus.

I believe there was a specific technical reason we chose not to implement have.focus in the chai-jquery rewrite, but I can't remember what it was.

The problem is that because we are normalizing focus it means Cypress is the only source of truth to understand what should be in focus even when its not. Because of that - the have.focus assertion would have to call into the Cypress machinery and could not use anything else. It would basically just be the same thing as the yielded result from cy.focused().

We could override jquery's :is the same way we do visible + hidden to call into these internal functions. I guess that would work but I'd have to play with it to see if I'm missing edge cases. I want to say that every time we went down this path we couldn't figure out a way to consistently get it to work.

@bugzpodder
Copy link

I ran into this issue when testing moving between text boxes in a form.
Basically was testing the behavior of focusing on the first text box, typed something, jumped to next one and typing something else.

@jennifer-shehane jennifer-shehane added the stage: needs investigating Someone from Cypress needs to look at this label Nov 1, 2017
@jbmusso
Copy link

jbmusso commented Feb 1, 2018

@verheyenkoen Did you find any workaround for this?

I'm also running into this using cypress@v1.4.1. Tests with .focused() will consistently fail when the Cypress UI is blurred, and will consistently succeed otherwise. The use case is similar to @bugzpodder's: filling a form (security number field) where focus automatically goes to the next field.

Sample test case:

cy
  .get('input[name="digit-1"]')
  .type('1')
  .should('have.value', '1')
  .focused()
  .should('have.attr', 'name', 'digit-2')

  .focused()
  .type('2')
  .should('have.value', '2')

  .focused()
  .type('3')
  .should('have.value', '3')
  // ...

@verheyenkoen
Copy link
Contributor Author

I think I now tested for the existence of the autofocus attribute, which is not a consistent workaround obviously.

@kyleoliveiro
Copy link

kyleoliveiro commented Jun 28, 2018

Running into this issue as well. I'm testing a listbox component. Tests are passing when I run Cypress through the GUI, but fails in headless mode.

Cypress test:

it('when listbox does not have option selected and receives focus, focus is delegated to the first option', function() {
    cy.get('#listbox--static .listbox__options').focus();
    cy.focused().then($el => {
      expect($el[0].className).to.equal('listbox__option');
      expect($el[0].innerText).to.contain('Option 1');
    })
  });

The feature is working and test is passing in GUI mode. But fails in headless Electron mode.

@kuceb
Copy link
Contributor

kuceb commented Jul 17, 2018

This issue was probably fixed in 3.0.2 via #1962 , I cannot reproduce the focus issue. cy.focused() should be consistent with document.activeElement

@kuceb kuceb added this to the 3.0.2 milestone Jul 17, 2018
@kuceb
Copy link
Contributor

kuceb commented Jul 17, 2018

I'm closing this for now, but leave a comment if something still seems broken

@kuceb kuceb closed this as completed Jul 17, 2018
@kuceb kuceb removed the stage: needs investigating Someone from Cypress needs to look at this label Jul 17, 2018
@verheyenkoen
Copy link
Contributor Author

verheyenkoen commented Jul 18, 2018

I cannot confirm this fix. I upgraded my test repo to Cypress 3.0.2 and my test still fails. Please reopen.

@kuceb
Copy link
Contributor

kuceb commented Jul 18, 2018

@verheyenkoen I looked at your test repo. Can you explain what behavior you expect? Looking at the event handler you added:

document.getElementById('field').onkeyup = function() {

window.setTimeout(function() {

document.getElementById('field').blur();

}, 100)

}

I don't see why the element would be focused after typing into '#field'

@verheyenkoen
Copy link
Contributor Author

Damn, what was I thinking?? Nevermind all that. Sorry for bothering...

@henrykuzmick
Copy link

Hey, while this works in headless mode, focused() still fails when using the ui and not having the cypress window focused.
It would be great if it worked even when I'm on another tab or in my IDE, etc.

@kuceb
Copy link
Contributor

kuceb commented Jan 24, 2019

@henrykuzmick what version of cypress are you on? cy.focused() should yield the same as document.activeElement or null if the body is focused, which will be unaffected by window focus

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg/driver This is due to an issue in the packages/driver directory type: bug
Projects
None yet
Development

No branches or pull requests

9 participants