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

fix: iFrame input focus should not cause blur if input already activeElement #8112

Merged
merged 4 commits into from
Aug 3, 2020
Merged

Conversation

martynchamberlin
Copy link

@martynchamberlin martynchamberlin commented Jul 28, 2020

User facing changelog

Fixed an issue where focusing on an input inside iFrame contents causes blur if the input was already selected.

Additional details

Here's a quick rundown on what's wrong and how this PR seeks to fix it.

We are looking to start using Cypress to integration-test our credit card checkout experience at Chess.com. Our payment vendor is Adyen and the way it works, each credit card input field is an iFrame coming from Adyen's server. Here's a screenshot with each iFrame annotated with a pink background:

Screen Shot 2020-07-28 at 5 09 36 PM

When you complete the expiration month field, Adyen auto-tabs you to the expiration year field. When you complete that, Adyen auto-tabs you to the security code. When auto-tabbing, Adyen also auto-focuses on the <input> within each iFrame.

My integration test in part looks like this:

  cy.getFrame('encryptedExpiryMonth')
    .find('#encryptedExpiryMonth')
    .type('12');

  cy.getFrame('encryptedExpiryYear')
    .find('#encryptedExpiryYear')
    .type('25');

When .type() executes for each of these, this click event occurs:

return cy.now('click', $elToClick, {

...which triggers this:

const mouseDownPhase = mouse.down(fromElViewport, forceEl, pointerEvtOptionsExtend, mouseEvtOptionsExtend)

...which triggers this:

focused.fireBlur($focused.get(0))

...which triggers this:

fireBlur($focused.get(0))

In other words, this focusing on an input that's already focused results in it blurring, which is the bug. In this scenario, this conditional here is evaluating true where it should be evaluating false:

if ($focused && $focused.get(0) !== el) {

That is because there's a hardcoded assumption here that the document in question is the top document, not the document that the element in question belongs to:

const { activeElement } = state('document')

By giving an optional argument to specify the document in the getFocused function, iFrames get better support in Cypress.

How has the user experience changed?

n/a

PR Tasks

  • Have tests been added/updated? Maybe there's a way to get the idea at Add a failing test for iFrames cypress-test-tiny#61 incorporated into a test, although I'm still trying to figure out how to get that to fail on CI. In our more complex environment internally it certainly fails CI.

@cypress-bot
Copy link
Contributor

cypress-bot bot commented Jul 28, 2020

Thanks for taking the time to open a PR!

@CLAassistant
Copy link

CLAassistant commented Jul 28, 2020

CLA assistant check
All committers have signed the CLA.

@martynchamberlin martynchamberlin changed the title Fix bug with iFrame focus causing blur if input already selected fix: iFrame input focus should not cause blur if input already activeElement Jul 28, 2020
Copy link
Member

@jennifer-shehane jennifer-shehane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did manually verify that this fixes the original issue. A test would be ideal...maybe someone else on the team has an idea on how to test this. @chrisbreiding @bkucera ?

packages/driver/src/cy/focused.js Show resolved Hide resolved
@chrisbreiding
Copy link
Contributor

I added a test. It's the repro one from the issue. Needed to try it out to make sure it would work. It did, so I figured I'd go ahead and commit it.

chrisbreiding
chrisbreiding previously approved these changes Jul 29, 2020
@martynchamberlin
Copy link
Author

@chrisbreiding This test would fail in the develop branch apart from the changes in this PR. I can't figure out how to get the test to fail in develop because to reproduce, you have to blur the entire browser. Not sure that's programmatically possible. 🤔

Copy link
Member

@jennifer-shehane jennifer-shehane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

K, I found a way to make this break in the tests without manually focusing out. This basically breaks if you open DevTools, so we can have the Devtools auto open to make this test fail.

This will only work in Chrome, I don't know how to open devtools in Electron from preferences. This bug doesn't happen in Firefox, so we won't need a test for that. I think this is better than nothing.

@chrisbreiding I'm not sure what the best way is to have these preferences apply for a single spec run in our driver tests.

module.exports = (on, config) => {
  on('before:browser:launch', (browser = {}, launchOptions) => {
    if (browser.family === 'chromium' && browser.name !== 'electron') {
      // auto open devtools
      launchOptions.args.push('--auto-open-devtools-for-tabs')
    }

    return launchOptions
  })
}

@chrisbreiding
Copy link
Contributor

I moved the test to be an e2e test so the open devtools could be applied to it. Don't think there's a way to do that individually for a driver test.

@jennifer-shehane jennifer-shehane self-requested a review August 3, 2020 07:32
Copy link
Member

@jennifer-shehane jennifer-shehane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, this test also depends on the Chrome browser being headed so I added that to the e2e test. I checked that the e2e test fails without this fix and passes with it and added some clarifying comments. 👍

@martynchamberlin
Copy link
Author

Groovy. Thanks for all your help everyone! 💪

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

Successfully merging this pull request may close these issues.

iFrame elements that focus, when calling .type() are actually blurred (when Test Runner is not focused)
4 participants