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: Fire appropriate event when cy.type(). #8255

Merged
merged 7 commits into from Sep 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 20 additions & 0 deletions packages/driver/cypress/fixtures/issue-6125.html
@@ -0,0 +1,20 @@
<!-- Simplified version of https://signin.simple.com-->

<!doctype html>
<html lang="en">
<head>
<title>Sign In | Simple</title>
</head>
<body>
<form id="login">
<label for="login_username">Username</label>
<input type="text" name="username" id="login_username" autofocus="autofocus" tabindex="1" autocapitalize="off" autocorrect="off" autocomplete="off" class="validate-text validate-username validate-email-username" />

<label for="login_password">Password</label>
<input type="password" name="password" id="login_password" tabindex="2" autocomplete="off" class="validate-text" />

<input type="submit" id="signin-btn" class="btn -primary" value="Sign In" tabindex="4" disabled>
</form>
<script src="issue-6125.js" type="text/javascript"></script>
</body>
</html>
12 changes: 12 additions & 0 deletions packages/driver/cypress/fixtures/issue-6125.js
@@ -0,0 +1,12 @@
// Extracted the code that causes the problem in signin.simple.com
// The cause was overriding the Event class.

(function() {
this.Event = function(n, i) {
const r = n.type

if (r.indexOf("key")) {
// do something
}
}
})()
22 changes: 22 additions & 0 deletions packages/driver/cypress/integration/commands/actions/type_spec.js
Expand Up @@ -177,6 +177,28 @@ describe('src/cy/commands/actions/type - #type', () => {
.should('have.value', 'foobar')
})

// https://github.com/cypress-io/cypress/issues/6125
it('works even if Event class is overridden', () => {
cy.visit('fixtures/issue-6125.html')
cy.get('#login_username')
.type('foobar')
})

// https://github.com/cypress-io/cypress/issues/5650
it('should trigger KeyboardEvent, not Event, for event listeners', (done) => {
cy.$$('input:first').on('keydown', (e) => {
if (e.originalEvent instanceof e.currentTarget.ownerDocument.defaultView.KeyboardEvent) {
done()

return
}

throw new Error('event was not instanceOf KeyboardEvent')
})

cy.get('input:first').type('A')
})

describe('actionability', () => {
it('can forcibly type + click even when element is invisible', () => {
const $txt = cy.$$(':text:first').hide()
Expand Down
32 changes: 19 additions & 13 deletions packages/driver/src/cy/commands/actions/type.js
Expand Up @@ -202,19 +202,25 @@ module.exports = function (Commands, Cypress, cy, state, config) {
return
}

// issue the click event to the 'default button' of the form
// we need this to be synchronous so not going through our
// own click command
// as of now, at least in Chrome, causing the click event
// on the button will indeed trigger the form submit event
// so we dont need to fire it manually anymore!
if (!clickedDefaultButton(defaultButton)) {
// if we werent able to click the default button
// then synchronously fire the submit event
// currently this is sync but if we use a waterfall
// promise in the submit command it will break again
// consider changing type to a Promise and juggle logging
return cy.now('submit', form, { log: false, $el: form })
// In Firefox, submit event is automatically fired
Copy link
Contributor

Choose a reason for hiding this comment

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

nice comments 👍

// when we send {Enter} KeyboardEvent to the input fields.
// Because of that, we don't have to click the submit buttons.
// Otherwise, we trigger submit events twice.
if (!Cypress.isBrowser('firefox')) {
// issue the click event to the 'default button' of the form
// we need this to be synchronous so not going through our
// own click command
// as of now, at least in Chrome, causing the click event
// on the button will indeed trigger the form submit event
// so we dont need to fire it manually anymore!
if (!clickedDefaultButton(defaultButton)) {
// if we werent able to click the default button
// then synchronously fire the submit event
// currently this is sync but if we use a waterfall
// promise in the submit command it will break again
// consider changing type to a Promise and juggle logging
return cy.now('submit', form, { log: false, $el: form })
}
}
}

Expand Down
13 changes: 9 additions & 4 deletions packages/driver/src/cy/keyboard.ts
Expand Up @@ -900,10 +900,15 @@ export class Keyboard {

// or is IE
} else {
// For some reason we can't set certain props on Keyboard Events in chrome < 63.
// So we'll use the plain Event constructor
// event = new win[eventConstructor](eventType, eventOptions)
event = new win['Event'](eventType, eventOptions)
let constructor = win[eventConstructor]

// When event constructor doesn't exist, fallback to KeyboardEvent.
// It's necessary because Firefox doesn't support InputEvent.
if (typeof constructor !== 'function') {
constructor = win['KeyboardEvent']
}

event = new constructor(eventType, eventOptions)
_.extend(event, eventOptions)
}

Expand Down