From f081d7cead1698867fb25aad52536950c95aa8a5 Mon Sep 17 00:00:00 2001 From: KHeo Date: Tue, 28 Jul 2020 11:29:49 +0900 Subject: [PATCH 01/11] Add basic test case. --- .../driver/cypress/fixtures/issue-486.html | 29 +++++++++++++++++++ packages/driver/cypress/integration/a.js | 9 ++++++ 2 files changed, 38 insertions(+) create mode 100644 packages/driver/cypress/fixtures/issue-486.html create mode 100644 packages/driver/cypress/integration/a.js diff --git a/packages/driver/cypress/fixtures/issue-486.html b/packages/driver/cypress/fixtures/issue-486.html new file mode 100644 index 000000000000..8cd252fffe62 --- /dev/null +++ b/packages/driver/cypress/fixtures/issue-486.html @@ -0,0 +1,29 @@ + + + + Issue 486 + + + +
Result
+ + + diff --git a/packages/driver/cypress/integration/a.js b/packages/driver/cypress/integration/a.js new file mode 100644 index 000000000000..f0c901767434 --- /dev/null +++ b/packages/driver/cypress/integration/a.js @@ -0,0 +1,9 @@ +it('t', () => { + cy.visit('/fixtures/issue-486.html') + + cy.get('#button').click({ + ctrlKey: true, + }) + + cy.get('#result').should('contain', '{Ctrl}') +}) From fcc45adf675d5c8acb3e0b5f6487d49d9ac256d2 Mon Sep 17 00:00:00 2001 From: KHeo Date: Tue, 28 Jul 2020 12:07:51 +0900 Subject: [PATCH 02/11] Add working test. --- packages/driver/cypress/integration/a.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/driver/cypress/integration/a.js b/packages/driver/cypress/integration/a.js index f0c901767434..859d49bb0f4b 100644 --- a/packages/driver/cypress/integration/a.js +++ b/packages/driver/cypress/integration/a.js @@ -7,3 +7,12 @@ it('t', () => { cy.get('#result').should('contain', '{Ctrl}') }) + +it('x', () => { + cy.visit('/fixtures/issue-486.html') + + cy.get('#button').type('{ctrl}', { release: false }) + cy.get('#button').click() + + cy.get('#result').should('contain', '{Ctrl}') +}) From 7618e5f40ff9b585e70ed9a6c3d94b54759223bb Mon Sep 17 00:00:00 2001 From: KHeo Date: Wed, 29 Jul 2020 09:56:00 +0900 Subject: [PATCH 03/11] test --- packages/driver/src/cy/commands/actions/click.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/driver/src/cy/commands/actions/click.js b/packages/driver/src/cy/commands/actions/click.js index b564e2f99350..a55f8dc5a3f3 100644 --- a/packages/driver/src/cy/commands/actions/click.js +++ b/packages/driver/src/cy/commands/actions/click.js @@ -34,7 +34,7 @@ const formatMouseEvents = (events) => { } module.exports = (Commands, Cypress, cy, state, config) => { - const { mouse } = cy.devices + const { mouse, keyboard } = cy.devices const mouseAction = (eventName, { subject, positionOrX, y, userOptions, onReady, onTable, defaultOptions }) => { let position @@ -158,6 +158,15 @@ module.exports = (Commands, Cypress, cy, state, config) => { const moveEvents = mouse.move(fromElViewport, forceEl) + if (options.ctrlKey) { + keyboard.type({ + $el: options.$el, + delay: 10, + chars: '{ctrl}', + release: false, + }) + } + const onReadyProps = onReady(fromElViewport, forceEl) return createLog({ From f8dc04e28a3722c261d6ccd397a638e38ef10e90 Mon Sep 17 00:00:00 2001 From: KHeo Date: Wed, 29 Jul 2020 10:45:01 +0900 Subject: [PATCH 04/11] Move tests to click_spec --- packages/driver/cypress/integration/a.js | 18 ------ .../commands/actions/click_spec.js | 60 +++++++++++++++++++ .../driver/src/cy/commands/actions/click.js | 41 ++++++++++--- 3 files changed, 92 insertions(+), 27 deletions(-) delete mode 100644 packages/driver/cypress/integration/a.js diff --git a/packages/driver/cypress/integration/a.js b/packages/driver/cypress/integration/a.js deleted file mode 100644 index 859d49bb0f4b..000000000000 --- a/packages/driver/cypress/integration/a.js +++ /dev/null @@ -1,18 +0,0 @@ -it('t', () => { - cy.visit('/fixtures/issue-486.html') - - cy.get('#button').click({ - ctrlKey: true, - }) - - cy.get('#result').should('contain', '{Ctrl}') -}) - -it('x', () => { - cy.visit('/fixtures/issue-486.html') - - cy.get('#button').type('{ctrl}', { release: false }) - cy.get('#button').click() - - cy.get('#result').should('contain', '{Ctrl}') -}) diff --git a/packages/driver/cypress/integration/commands/actions/click_spec.js b/packages/driver/cypress/integration/commands/actions/click_spec.js index deb601cfa0a3..c8f9c029d9ca 100644 --- a/packages/driver/cypress/integration/commands/actions/click_spec.js +++ b/packages/driver/cypress/integration/commands/actions/click_spec.js @@ -882,6 +882,66 @@ describe('src/cy/commands/actions/click', () => { }) }) + describe('modifier options', () => { + beforeEach(() => { + cy.visit('/fixtures/issue-486.html') + }) + + it('ctrl', () => { + cy.get('#button').click({ + ctrlKey: true, + }) + + cy.get('#result').should('contain', '{Ctrl}') + + // ctrl should be released + cy.get('#button').click() + cy.get('#result').should('not.contain', '{Ctrl}') + }) + + it('alt', () => { + cy.get('#button').click({ + altKey: true, + }) + + cy.get('#result').should('contain', '{Alt}') + + // alt should be released + cy.get('#button').click() + cy.get('#result').should('not.contain', '{Alt}') + }) + + it('shift', () => { + cy.get('#button').click({ + shiftKey: true, + }) + + cy.get('#result').should('contain', '{Shift}') + + // shift should be released + cy.get('#button').click() + cy.get('#result').should('not.contain', '{Shift}') + }) + + it('multiple', () => { + cy.get('#button').click({ + ctrlKey: true, + altKey: true, + shiftKey: true, + }) + + cy.get('#result').should('contain', '{Ctrl}') + cy.get('#result').should('contain', '{Alt}') + cy.get('#result').should('contain', '{Shift}') + + // modifiers should be released + cy.get('#button').click() + cy.get('#result').should('not.contain', '{Ctrl}') + cy.get('#result').should('not.contain', '{Alt}') + cy.get('#result').should('not.contain', '{Shift}') + }) + }) + describe('pointer-events:none', () => { beforeEach(function () { cy.$$('
behind #ptrNone
').appendTo(cy.$$('#dom')) diff --git a/packages/driver/src/cy/commands/actions/click.js b/packages/driver/src/cy/commands/actions/click.js index a55f8dc5a3f3..ab84e86783b4 100644 --- a/packages/driver/src/cy/commands/actions/click.js +++ b/packages/driver/src/cy/commands/actions/click.js @@ -65,6 +65,30 @@ module.exports = (Commands, Cypress, cy, state, config) => { }) } + const pressModifiers = (release) => { + const keys = [] + + if (options.ctrlKey) { + keys.push('{ctrl}') + } + + if (options.altKey) { + keys.push('{alt}') + } + + if (options.shiftKey) { + keys.push('{shift}') + } + + keys.forEach((key) => { + keyboard.type({ + $el: options.$el, + chars: key, + release, + }) + }) + } + const perform = (el) => { let deltaOptions const $el = $dom.wrap(el) @@ -142,6 +166,8 @@ module.exports = (Commands, Cypress, cy, state, config) => { .return(null) } + pressModifiers(false) + // must use callbacks here instead of .then() // because we're issuing the clicks synchonrously // once we establish the coordinates and the element @@ -158,15 +184,6 @@ module.exports = (Commands, Cypress, cy, state, config) => { const moveEvents = mouse.move(fromElViewport, forceEl) - if (options.ctrlKey) { - keyboard.type({ - $el: options.$el, - delay: 10, - chars: '{ctrl}', - release: false, - }) - } - const onReadyProps = onReady(fromElViewport, forceEl) return createLog({ @@ -177,6 +194,12 @@ module.exports = (Commands, Cypress, cy, state, config) => { fromAutWindow) }, }) + .then((result) => { + // Release pressed modifiers + pressModifiers(true) + + return result + }) .catch((err) => { // snapshot only on click failure err.onFail = function () { From b4f4b383443721330d6d7531ba46273aec76d07a Mon Sep 17 00:00:00 2001 From: KHeo Date: Wed, 29 Jul 2020 10:50:04 +0900 Subject: [PATCH 05/11] Default option values. --- packages/driver/src/cy/commands/actions/click.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/driver/src/cy/commands/actions/click.js b/packages/driver/src/cy/commands/actions/click.js index ab84e86783b4..66f9f83b4113 100644 --- a/packages/driver/src/cy/commands/actions/click.js +++ b/packages/driver/src/cy/commands/actions/click.js @@ -54,6 +54,9 @@ module.exports = (Commands, Cypress, cy, state, config) => { errorOnSelect: true, waitForAnimations: config('waitForAnimations'), animationDistanceThreshold: config('animationDistanceThreshold'), + ctrlKey: false, + altKey: false, + shiftKey: false, ...defaultOptions, }) From f8056a5bef1de0a8f8dc480df7ca3522b6d496c9 Mon Sep 17 00:00:00 2001 From: KHeo Date: Wed, 29 Jul 2020 10:56:17 +0900 Subject: [PATCH 06/11] Add TypeScript definitions. --- cli/types/cypress.d.ts | 18 ++++++++++++++++++ cli/types/tests/chainer-examples.ts | 3 +++ 2 files changed, 21 insertions(+) diff --git a/cli/types/cypress.d.ts b/cli/types/cypress.d.ts index 03133300343d..5c2aa925fc79 100644 --- a/cli/types/cypress.d.ts +++ b/cli/types/cypress.d.ts @@ -2319,6 +2319,24 @@ declare namespace Cypress { * @default false */ multiple: boolean + /** + * Press ctrl key + * + * @default false + */ + ctrlKey: boolean + /** + * Press alt key + * + * @default false + */ + altKey: boolean + /** + * Press shift key + * + * @default false + */ + shiftKey: boolean } interface ResolvedConfigOptions { diff --git a/cli/types/tests/chainer-examples.ts b/cli/types/tests/chainer-examples.ts index 7538a638b297..6f72b6f5af1a 100644 --- a/cli/types/tests/chainer-examples.ts +++ b/cli/types/tests/chainer-examples.ts @@ -467,6 +467,9 @@ cy.writeFile('../file.path', '', { }) cy.get('foo').click() +cy.get('foo').click({ + ctrlKey: true, +}) cy.get('foo').rightclick() cy.get('foo').dblclick() From 66b684aeeb79007c86ed693843316864f90ea85b Mon Sep 17 00:00:00 2001 From: KHeo Date: Thu, 30 Jul 2020 10:15:02 +0900 Subject: [PATCH 07/11] Support meta key. --- cli/types/cypress.d.ts | 8 +++++++- packages/driver/cypress/fixtures/issue-486.html | 4 ++++ .../integration/commands/actions/click_spec.js | 15 +++++++++++++++ packages/driver/src/cy/commands/actions/click.js | 4 ++++ 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/cli/types/cypress.d.ts b/cli/types/cypress.d.ts index 5c2aa925fc79..5998d0641961 100644 --- a/cli/types/cypress.d.ts +++ b/cli/types/cypress.d.ts @@ -2326,7 +2326,7 @@ declare namespace Cypress { */ ctrlKey: boolean /** - * Press alt key + * Press alt key. It's option key in Mac. * * @default false */ @@ -2337,6 +2337,12 @@ declare namespace Cypress { * @default false */ shiftKey: boolean + /** + * Press meta key. It's Windows key in Windows and Command key in Mac. + * + * @default false + */ + metaKey: boolean } interface ResolvedConfigOptions { diff --git a/packages/driver/cypress/fixtures/issue-486.html b/packages/driver/cypress/fixtures/issue-486.html index 8cd252fffe62..0f5954a16764 100644 --- a/packages/driver/cypress/fixtures/issue-486.html +++ b/packages/driver/cypress/fixtures/issue-486.html @@ -23,6 +23,10 @@ if (e.shiftKey) { result.innerText += '{Shift}' } + + if (e.metaKey) { + result.innerText += '{Meta}' + } }) diff --git a/packages/driver/cypress/integration/commands/actions/click_spec.js b/packages/driver/cypress/integration/commands/actions/click_spec.js index c8f9c029d9ca..10b2d339a7c3 100644 --- a/packages/driver/cypress/integration/commands/actions/click_spec.js +++ b/packages/driver/cypress/integration/commands/actions/click_spec.js @@ -923,22 +923,37 @@ describe('src/cy/commands/actions/click', () => { cy.get('#result').should('not.contain', '{Shift}') }) + it('meta', () => { + cy.get('#button').click({ + metaKey: true, + }) + + cy.get('#result').should('contain', '{Meta}') + + // shift should be released + cy.get('#button').click() + cy.get('#result').should('not.contain', '{Meta}') + }) + it('multiple', () => { cy.get('#button').click({ ctrlKey: true, altKey: true, shiftKey: true, + metaKey: true, }) cy.get('#result').should('contain', '{Ctrl}') cy.get('#result').should('contain', '{Alt}') cy.get('#result').should('contain', '{Shift}') + cy.get('#result').should('contain', '{Meta}') // modifiers should be released cy.get('#button').click() cy.get('#result').should('not.contain', '{Ctrl}') cy.get('#result').should('not.contain', '{Alt}') cy.get('#result').should('not.contain', '{Shift}') + cy.get('#result').should('not.contain', '{Meta}') }) }) diff --git a/packages/driver/src/cy/commands/actions/click.js b/packages/driver/src/cy/commands/actions/click.js index 66f9f83b4113..01f2a6c47321 100644 --- a/packages/driver/src/cy/commands/actions/click.js +++ b/packages/driver/src/cy/commands/actions/click.js @@ -83,6 +83,10 @@ module.exports = (Commands, Cypress, cy, state, config) => { keys.push('{shift}') } + if (options.metaKey) { + keys.push('{meta}') + } + keys.forEach((key) => { keyboard.type({ $el: options.$el, From a273cbe3ab65d0cf5f2f75d4808819868c91fa24 Mon Sep 17 00:00:00 2001 From: KHeo Date: Thu, 30 Jul 2020 11:24:05 +0900 Subject: [PATCH 08/11] Implement with flagModifier. --- .../driver/src/cy/commands/actions/click.js | 32 ++++++------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/packages/driver/src/cy/commands/actions/click.js b/packages/driver/src/cy/commands/actions/click.js index 01f2a6c47321..99103907f298 100644 --- a/packages/driver/src/cy/commands/actions/click.js +++ b/packages/driver/src/cy/commands/actions/click.js @@ -68,32 +68,22 @@ module.exports = (Commands, Cypress, cy, state, config) => { }) } - const pressModifiers = (release) => { - const keys = [] - + const flagModifiers = (press) => { if (options.ctrlKey) { - keys.push('{ctrl}') + keyboard.flagModifier({ key: 'Control' }, press) } if (options.altKey) { - keys.push('{alt}') + keyboard.flagModifier({ key: 'Alt' }, press) } if (options.shiftKey) { - keys.push('{shift}') + keyboard.flagModifier({ key: 'Shift' }, press) } if (options.metaKey) { - keys.push('{meta}') + keyboard.flagModifier({ key: 'Meta' }, press) } - - keys.forEach((key) => { - keyboard.type({ - $el: options.$el, - chars: key, - release, - }) - }) } const perform = (el) => { @@ -173,8 +163,6 @@ module.exports = (Commands, Cypress, cy, state, config) => { .return(null) } - pressModifiers(false) - // must use callbacks here instead of .then() // because we're issuing the clicks synchonrously // once we establish the coordinates and the element @@ -191,8 +179,12 @@ module.exports = (Commands, Cypress, cy, state, config) => { const moveEvents = mouse.move(fromElViewport, forceEl) + flagModifiers(true) + const onReadyProps = onReady(fromElViewport, forceEl) + flagModifiers(false) + return createLog({ moveEvents, ...onReadyProps, @@ -201,12 +193,6 @@ module.exports = (Commands, Cypress, cy, state, config) => { fromAutWindow) }, }) - .then((result) => { - // Release pressed modifiers - pressModifiers(true) - - return result - }) .catch((err) => { // snapshot only on click failure err.onFail = function () { From ca2d073343c0600324d86020d7b6cdebc1f0a5a3 Mon Sep 17 00:00:00 2001 From: KHeo Date: Thu, 30 Jul 2020 11:31:29 +0900 Subject: [PATCH 09/11] Support for the aliases. --- cli/types/cypress.d.ts | 24 +++++++++++++++++++ .../commands/actions/click_spec.js | 24 +++++++++++++++++++ .../driver/src/cy/commands/actions/click.js | 7 +++--- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/cli/types/cypress.d.ts b/cli/types/cypress.d.ts index 5998d0641961..939fca109b10 100644 --- a/cli/types/cypress.d.ts +++ b/cli/types/cypress.d.ts @@ -2325,12 +2325,24 @@ declare namespace Cypress { * @default false */ ctrlKey: boolean + /** + * Alias for the ctrl key + * + * @default false + */ + controlKey: boolean /** * Press alt key. It's option key in Mac. * * @default false */ altKey: boolean + /** + * Alias for the alt key. + * + * @default false + */ + optionKey: boolean /** * Press shift key * @@ -2343,6 +2355,18 @@ declare namespace Cypress { * @default false */ metaKey: boolean + /** + * Alias for the meta key. + * + * @default false + */ + commandKey: boolean + /** + * Alias for the meta key. + * + * @default false + */ + cmdKey: boolean } interface ResolvedConfigOptions { diff --git a/packages/driver/cypress/integration/commands/actions/click_spec.js b/packages/driver/cypress/integration/commands/actions/click_spec.js index 10b2d339a7c3..674c299ade04 100644 --- a/packages/driver/cypress/integration/commands/actions/click_spec.js +++ b/packages/driver/cypress/integration/commands/actions/click_spec.js @@ -897,6 +897,12 @@ describe('src/cy/commands/actions/click', () => { // ctrl should be released cy.get('#button').click() cy.get('#result').should('not.contain', '{Ctrl}') + + cy.get('#button').click({ + controlKey: true, + }) + + cy.get('#result').should('contain', '{Ctrl}') }) it('alt', () => { @@ -909,6 +915,12 @@ describe('src/cy/commands/actions/click', () => { // alt should be released cy.get('#button').click() cy.get('#result').should('not.contain', '{Alt}') + + cy.get('#button').click({ + optionKey: true, + }) + + cy.get('#result').should('contain', '{Alt}') }) it('shift', () => { @@ -933,6 +945,18 @@ describe('src/cy/commands/actions/click', () => { // shift should be released cy.get('#button').click() cy.get('#result').should('not.contain', '{Meta}') + + cy.get('#button').click({ + commandKey: true, + }) + + cy.get('#result').should('contain', '{Meta}') + + cy.get('#button').click({ + cmdKey: true, + }) + + cy.get('#result').should('contain', '{Meta}') }) it('multiple', () => { diff --git a/packages/driver/src/cy/commands/actions/click.js b/packages/driver/src/cy/commands/actions/click.js index 99103907f298..9eaf597f6e1a 100644 --- a/packages/driver/src/cy/commands/actions/click.js +++ b/packages/driver/src/cy/commands/actions/click.js @@ -57,6 +57,7 @@ module.exports = (Commands, Cypress, cy, state, config) => { ctrlKey: false, altKey: false, shiftKey: false, + cmdKey: false, ...defaultOptions, }) @@ -69,11 +70,11 @@ module.exports = (Commands, Cypress, cy, state, config) => { } const flagModifiers = (press) => { - if (options.ctrlKey) { + if (options.ctrlKey || options.controlKey) { keyboard.flagModifier({ key: 'Control' }, press) } - if (options.altKey) { + if (options.altKey || options.optionKey) { keyboard.flagModifier({ key: 'Alt' }, press) } @@ -81,7 +82,7 @@ module.exports = (Commands, Cypress, cy, state, config) => { keyboard.flagModifier({ key: 'Shift' }, press) } - if (options.metaKey) { + if (options.metaKey || options.commandKey || options.cmdKey) { keyboard.flagModifier({ key: 'Meta' }, press) } } From cf6c5b84c027ba00011fec6fc55d939ef685da82 Mon Sep 17 00:00:00 2001 From: KHeo Date: Thu, 30 Jul 2020 11:46:05 +0900 Subject: [PATCH 10/11] Add alias defaults. --- packages/driver/src/cy/commands/actions/click.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/driver/src/cy/commands/actions/click.js b/packages/driver/src/cy/commands/actions/click.js index 9eaf597f6e1a..3cfd893a6629 100644 --- a/packages/driver/src/cy/commands/actions/click.js +++ b/packages/driver/src/cy/commands/actions/click.js @@ -55,8 +55,12 @@ module.exports = (Commands, Cypress, cy, state, config) => { waitForAnimations: config('waitForAnimations'), animationDistanceThreshold: config('animationDistanceThreshold'), ctrlKey: false, + controlKey: false, altKey: false, + optionKey: false, shiftKey: false, + metaKey: false, + commandKey: false, cmdKey: false, ...defaultOptions, }) From ef1685401c8b335cf546e143c4087ab78d71317c Mon Sep 17 00:00:00 2001 From: Jennifer Shehane Date: Mon, 3 Aug 2020 13:59:42 +0630 Subject: [PATCH 11/11] Update type descriptions to match docs + have same descriptions for aliases --- cli/types/cypress.d.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cli/types/cypress.d.ts b/cli/types/cypress.d.ts index 939fca109b10..e4413d9c12e8 100644 --- a/cli/types/cypress.d.ts +++ b/cli/types/cypress.d.ts @@ -2320,49 +2320,49 @@ declare namespace Cypress { */ multiple: boolean /** - * Press ctrl key + * Activates the control key during click * * @default false */ ctrlKey: boolean /** - * Alias for the ctrl key + * Activates the control key during click * * @default false */ controlKey: boolean /** - * Press alt key. It's option key in Mac. + * Activates the alt key (option key for Mac) during click * * @default false */ altKey: boolean /** - * Alias for the alt key. + * Activates the alt key (option key for Mac) during click * * @default false */ optionKey: boolean /** - * Press shift key + * Activates the shift key during click * * @default false */ shiftKey: boolean /** - * Press meta key. It's Windows key in Windows and Command key in Mac. + * Activates the meta key (Windows key or command key for Mac) during click * * @default false */ metaKey: boolean /** - * Alias for the meta key. + * Activates the meta key (Windows key or command key for Mac) during click * * @default false */ commandKey: boolean /** - * Alias for the meta key. + * Activates the meta key (Windows key or command key for Mac) during click * * @default false */