Skip to content

Commit

Permalink
fix: Fire appropriate event when cy.type(). (#8255)
Browse files Browse the repository at this point in the history
  • Loading branch information
sainthkh authored and panzarino committed Sep 17, 2020
1 parent f30683f commit e56ca16
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 17 deletions.
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
// 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

0 comments on commit e56ca16

Please sign in to comment.