From a4a8c3d16f4587e38b89e27290da2d13eecddfb3 Mon Sep 17 00:00:00 2001 From: Sergey Vinogradov Date: Wed, 29 Jan 2025 13:06:33 +0400 Subject: [PATCH] test: add shortcut for pressing multiple keys simultaneously (#8536) --- .../test/focus-trap-controller.test.js | 4 +- packages/app-layout/test/helpers.js | 4 +- .../test/checkbox-group.common.js | 4 +- .../checkbox-group/test/validation.common.js | 8 +-- packages/checkbox/test/validation.common.js | 4 +- .../test/virtualizer-reorder-elements.test.js | 4 +- packages/context-menu/test/a11y.common.js | 4 +- .../date-picker/test/fullscreen.common.js | 8 +-- .../date-picker/test/keyboard-input.common.js | 16 ++---- .../test/keyboard-navigation.common.js | 32 +++--------- .../date-time-picker/test/validation.test.js | 4 +- .../test/field-components.test.js | 8 +-- packages/grid-pro/test/edit-column.common.js | 36 ++++--------- .../test/keyboard-navigation.common.js | 32 +++--------- packages/grid/test/disabled.common.js | 4 +- .../test/keyboard-interaction-mode.common.js | 8 +-- packages/menu-bar/test/menu-bar.common.js | 4 +- packages/menu-bar/test/sub-menu.common.js | 4 +- .../test/password-field.common.js | 12 ++--- packages/popover/test/a11y.test.js | 12 ++--- .../radio-group/test/radio-group.common.js | 4 +- .../radio-group/test/validation.common.js | 8 +-- packages/rich-text-editor/test/a11y.common.js | 4 +- packages/upload/test/file.common.js | 8 +-- test/integration/dialog-accordion.test.js | 8 +-- test/integration/dialog-date-picker.test.js | 12 ++--- .../grid-pro-custom-editor.test.js | 16 ++---- test/test-runner-commands/index.js | 52 +++++++++++++++++++ 28 files changed, 120 insertions(+), 204 deletions(-) diff --git a/packages/a11y-base/test/focus-trap-controller.test.js b/packages/a11y-base/test/focus-trap-controller.test.js index c9a3bbb24f3..67539939cee 100644 --- a/packages/a11y-base/test/focus-trap-controller.test.js +++ b/packages/a11y-base/test/focus-trap-controller.test.js @@ -58,9 +58,7 @@ async function tab() { } async function shiftTab() { - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); return document.activeElement; } diff --git a/packages/app-layout/test/helpers.js b/packages/app-layout/test/helpers.js index 1e39d559854..07809134714 100644 --- a/packages/app-layout/test/helpers.js +++ b/packages/app-layout/test/helpers.js @@ -9,7 +9,5 @@ export async function tab() { } export async function shiftTab() { - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); } diff --git a/packages/checkbox-group/test/checkbox-group.common.js b/packages/checkbox-group/test/checkbox-group.common.js index d53b29967d1..e91bc8335fc 100644 --- a/packages/checkbox-group/test/checkbox-group.common.js +++ b/packages/checkbox-group/test/checkbox-group.common.js @@ -287,9 +287,7 @@ describe('vaadin-checkbox-group', () => { await sendKeys({ press: 'Tab' }); // Move focus out of the checkbox group. - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(checkboxes[0].hasAttribute('focused')).to.be.false; expect(group.hasAttribute('focused')).to.be.false; diff --git a/packages/checkbox-group/test/validation.common.js b/packages/checkbox-group/test/validation.common.js index a109f6ea3f3..a383c8d875a 100644 --- a/packages/checkbox-group/test/validation.common.js +++ b/packages/checkbox-group/test/validation.common.js @@ -82,9 +82,7 @@ describe('validation', () => { expect(validateSpy.called).to.be.false; // Move focus out of the checkbox group. - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(validateSpy.calledOnce).to.be.true; }); @@ -132,9 +130,7 @@ describe('validation', () => { await sendKeys({ press: 'Tab' }); // Move focus out of the checkbox group. - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(validateSpy.called).to.be.false; }); diff --git a/packages/checkbox/test/validation.common.js b/packages/checkbox/test/validation.common.js index 59bc40d2952..b3afb6f6ebc 100644 --- a/packages/checkbox/test/validation.common.js +++ b/packages/checkbox/test/validation.common.js @@ -110,9 +110,7 @@ describe('validation', () => { await sendKeys({ press: 'Tab' }); // Blur the checkbox. - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(validateSpy.called).to.be.false; }); diff --git a/packages/component-base/test/virtualizer-reorder-elements.test.js b/packages/component-base/test/virtualizer-reorder-elements.test.js index 22c47705191..c34071b2eb5 100644 --- a/packages/component-base/test/virtualizer-reorder-elements.test.js +++ b/packages/component-base/test/virtualizer-reorder-elements.test.js @@ -152,9 +152,7 @@ describe('reorder elements', () => { // Tab upwards for (let i = tabToIndex - 1; i >= 0; i--) { await nextFrame(); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); await nextFrame(); expect(document.activeElement.id).to.equal(`item-${i}`); } diff --git a/packages/context-menu/test/a11y.common.js b/packages/context-menu/test/a11y.common.js index 54df497ef16..a7f6ffeb0b3 100644 --- a/packages/context-menu/test/a11y.common.js +++ b/packages/context-menu/test/a11y.common.js @@ -79,9 +79,7 @@ describe('a11y', () => { it('should move focus to the prev element outside the menu on Shift+Tab pressed inside', async () => { contextMenuButton.click(); await nextRender(); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(getDeepActiveElement()).to.equal(firstGlobalFocusable); }); diff --git a/packages/date-picker/test/fullscreen.common.js b/packages/date-picker/test/fullscreen.common.js index b73dddef2f6..a2fbec2abef 100644 --- a/packages/date-picker/test/fullscreen.common.js +++ b/packages/date-picker/test/fullscreen.common.js @@ -158,9 +158,7 @@ describe('fullscreen mode', () => { it('should move focus to Cancel button on date cell Shift Tab', async () => { const spy = sinon.spy(overlayContent._cancelButton, 'focus'); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(spy.calledOnce).to.be.true; }); @@ -170,9 +168,7 @@ describe('fullscreen mode', () => { const spy = sinon.spy(cell, 'focus'); // Move focus to Cancel button - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); await sendKeys({ press: 'Tab' }); diff --git a/packages/date-picker/test/keyboard-input.common.js b/packages/date-picker/test/keyboard-input.common.js index 03d7fd8aba5..deca6c5bc39 100644 --- a/packages/date-picker/test/keyboard-input.common.js +++ b/packages/date-picker/test/keyboard-input.common.js @@ -225,9 +225,7 @@ describe('keyboard', () => { const spy = sinon.spy(input, 'focus'); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(spy.calledOnce).to.be.true; }); @@ -240,9 +238,7 @@ describe('keyboard', () => { }); it('should move focus to Cancel button on input Shift Tab', async () => { - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(overlayContent._cancelButton.hasAttribute('focused')).to.be.true; }); @@ -250,9 +246,7 @@ describe('keyboard', () => { const spy = sinon.spy(overlayContent, 'revealDate'); overlayContent._todayButton.focus(); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); await aTimeout(1); expect(spy.called).to.be.true; @@ -295,9 +289,7 @@ describe('keyboard', () => { overlayContent._todayButton.focus(); // Move focus to the calendar - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); await waitForScrollToFinish(datePicker); diff --git a/packages/date-picker/test/keyboard-navigation.common.js b/packages/date-picker/test/keyboard-navigation.common.js index 685a2daba44..08ce25e56e6 100644 --- a/packages/date-picker/test/keyboard-navigation.common.js +++ b/packages/date-picker/test/keyboard-navigation.common.js @@ -342,17 +342,13 @@ describe('keyboard navigation', () => { }); it('should focus next year with shift and pagedown', async () => { - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'PageDown' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+PageDown' }); await waitForScrollToFinish(overlay); expect(overlay.focusedDate).to.eql(new Date(2001, 0, 1)); }); it('should focus previous year with shift and pageup', async () => { - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'PageUp' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+PageUp' }); await waitForScrollToFinish(overlay); expect(overlay.focusedDate).to.eql(new Date(1999, 0, 1)); }); @@ -361,9 +357,7 @@ describe('keyboard navigation', () => { const spy = sinon.spy(); overlay.addEventListener('scroll-animation-finished', spy); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'PageUp' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+PageUp' }); await waitForScrollToFinish(overlay); const e = spy.firstCall.args[0]; @@ -382,9 +376,7 @@ describe('keyboard navigation', () => { const spy = sinon.spy(); overlay.addEventListener('scroll-animation-finished', spy); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'PageDown' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+PageDown' }); await waitForScrollToFinish(overlay); const e = spy.firstCall.args[0]; @@ -455,9 +447,7 @@ describe('keyboard navigation', () => { it('should focus max date with shift and pagedown', async () => { overlay.maxDate = new Date(2000, 11, 28); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'PageDown' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+PageDown' }); await waitForScrollToFinish(overlay); const cell = getFocusedCell(overlay); @@ -467,9 +457,7 @@ describe('keyboard navigation', () => { it('should focus min date with shift and pageup', async () => { overlay.minDate = new Date(1999, 5, 3); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'PageUp' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+PageUp' }); await waitForScrollToFinish(overlay); const cell = getFocusedCell(overlay); @@ -501,9 +489,7 @@ describe('keyboard navigation', () => { overlay.minDate = new Date(1999, 11, 25); await nextRender(overlay); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'PageUp' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+PageUp' }); await waitForScrollToFinish(overlay); const cell = getFocusedCell(overlay); @@ -515,9 +501,7 @@ describe('keyboard navigation', () => { overlay.maxDate = new Date(1999, 11, 25); await nextRender(overlay); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'PageDown' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+PageDown' }); await waitForScrollToFinish(overlay); const cell = getFocusedCell(overlay); diff --git a/packages/date-time-picker/test/validation.test.js b/packages/date-time-picker/test/validation.test.js index dc073fb306a..2c7870d9b39 100644 --- a/packages/date-time-picker/test/validation.test.js +++ b/packages/date-time-picker/test/validation.test.js @@ -100,9 +100,7 @@ const fixtures = { await aTimeout(1); // Move focus to date-picker - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(validateSpy.called).to.be.false; }); diff --git a/packages/field-highlighter/test/field-components.test.js b/packages/field-highlighter/test/field-components.test.js index 6b7de8d7fb5..6b3827673e6 100644 --- a/packages/field-highlighter/test/field-components.test.js +++ b/packages/field-highlighter/test/field-components.test.js @@ -453,18 +453,14 @@ describe('field components', () => { it('should dispatch vaadin-highlight-hide event on Shift Tab to date picker', async () => { time.focus(); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(hideSpy.callCount).to.equal(1); expect(hideSpy.firstCall.args[0].detail.fieldIndex).to.equal(1); }); it('should dispatch second vaadin-highlight-show event on Shift Tab to date picker', async () => { time.focus(); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(showSpy.callCount).to.equal(2); expect(showSpy.getCalls()[1].args[0].detail.fieldIndex).to.equal(0); }); diff --git a/packages/grid-pro/test/edit-column.common.js b/packages/grid-pro/test/edit-column.common.js index 0dc00ea4494..2edee8178c2 100644 --- a/packages/grid-pro/test/edit-column.common.js +++ b/packages/grid-pro/test/edit-column.common.js @@ -63,16 +63,12 @@ describe('edit column', () => { await nextFrame(); // Press Shift + Tab to edit the select cell - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(getCellEditor(selectCell)).to.be.ok; await nextFrame(); // Press Shift + Tab to edit the text cell - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(getCellEditor(textCell)).to.be.ok; }); }); @@ -148,9 +144,7 @@ describe('edit column', () => { const firstCell = getContainerCell(grid.$.items, 1, 1); dblclick(firstCell._content); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(grid.$.table.scrollLeft).to.closeTo(1, 1); }); @@ -458,22 +452,16 @@ describe('edit column', () => { await sendKeys({ press: 'Enter' }); expect(getCellEditor(cell)).to.be.ok; - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); cell = getContainerCell(grid.$.items, 3, 1); expect(getCellEditor(cell)).to.be.ok; // Should skip non-editable rows - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); cell = getContainerCell(grid.$.items, 1, 3); expect(getCellEditor(cell)).to.be.ok; - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); cell = getContainerCell(grid.$.items, 1, 2); expect(getCellEditor(cell)).to.be.ok; }); @@ -514,9 +502,7 @@ describe('edit column', () => { expect(getCellEditor(cell)).to.be.ok; expect(grid.querySelector('vaadin-grid-pro-edit-text-field')).to.be.ok; - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(grid.querySelector('vaadin-grid-pro-edit-text-field')).to.not.be.ok; const target = cell._focusButton || cell; expect(grid.shadowRoot.activeElement).to.equal(target); @@ -546,9 +532,7 @@ describe('edit column', () => { await sendKeys({ press: 'Enter' }); expect(getCellEditor(cell)).to.be.ok; - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Enter' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Enter' }); cell = getContainerCell(grid.$.items, 1, 1); expect(getCellEditor(cell)).to.be.ok; }); @@ -574,9 +558,7 @@ describe('edit column', () => { expect(getCellEditor(cell)).to.be.ok; expect(grid.querySelector('vaadin-grid-pro-edit-text-field')).to.be.ok; - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Enter' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Enter' }); expect(grid.querySelector('vaadin-grid-pro-edit-text-field')).to.not.be.ok; const target = cell._focusButton || cell; expect(grid.shadowRoot.activeElement).to.equal(target); diff --git a/packages/grid-pro/test/keyboard-navigation.common.js b/packages/grid-pro/test/keyboard-navigation.common.js index 9bef4414a38..684964d8940 100644 --- a/packages/grid-pro/test/keyboard-navigation.common.js +++ b/packages/grid-pro/test/keyboard-navigation.common.js @@ -56,9 +56,7 @@ describe('keyboard navigation', () => { const secondCell = getContainerCell(grid.$.items, 1, 0); const spy = sinon.spy(secondCell, 'focus'); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(spy.calledOnce).to.be.true; }); @@ -80,9 +78,7 @@ describe('keyboard navigation', () => { const secondCell = getContainerCell(grid.$.items, 1, 1); const spy = sinon.spy(secondCell, 'focus'); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(spy.calledOnce).to.be.true; }); @@ -115,9 +111,7 @@ describe('keyboard navigation', () => { const secondCell = getContainerCell(grid.$.items, 0, 0); const spy = sinon.spy(secondCell, 'focus'); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Enter' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Enter' }); expect(spy.calledOnce).to.be.true; }); @@ -126,9 +120,7 @@ describe('keyboard navigation', () => { firstCell.focus(); await sendKeys({ press: 'Enter' }); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Enter' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Enter' }); expect(getCellEditor(firstCell)).to.be.not.ok; }); @@ -190,9 +182,7 @@ describe('keyboard navigation', () => { dblclick(firstCell._content); const secondCell = getContainerCell(grid.$.items, 1, 0); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(getCellEditor(secondCell)).to.be.ok; }); @@ -210,9 +200,7 @@ describe('keyboard navigation', () => { dblclick(firstCell._content); const secondCell = getContainerCell(grid.$.items, 1, 1); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(getCellEditor(secondCell)).to.be.ok; }); @@ -242,9 +230,7 @@ describe('keyboard navigation', () => { await sendKeys({ press: 'Enter' }); const secondCell = getContainerCell(grid.$.items, 0, 0); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Enter' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Enter' }); expect(getCellEditor(secondCell)).to.be.ok; }); @@ -263,9 +249,7 @@ describe('keyboard navigation', () => { const firstCell = getContainerCell(grid.$.items, 1, 0); dblclick(firstCell._content); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Enter' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Enter' }); expect(getCellEditor(firstCell)).to.be.not.ok; }); }); diff --git a/packages/grid/test/disabled.common.js b/packages/grid/test/disabled.common.js index aa03d182745..0739c11523d 100644 --- a/packages/grid/test/disabled.common.js +++ b/packages/grid/test/disabled.common.js @@ -82,9 +82,7 @@ describe('disabled', () => { it('should skip disabled grid when navigating on Shift Tab', async () => { inputAfter.focus(); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(document.activeElement).to.equal(inputBefore); }); diff --git a/packages/grid/test/keyboard-interaction-mode.common.js b/packages/grid/test/keyboard-interaction-mode.common.js index 2589f8753d5..41f4f4de6af 100644 --- a/packages/grid/test/keyboard-interaction-mode.common.js +++ b/packages/grid/test/keyboard-interaction-mode.common.js @@ -278,9 +278,7 @@ describe('keyboard interaction mode', () => { const previousInput = getCellInput(0, 1); // Shift+Tab to previous input - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(document.activeElement).to.equal(previousInput); }); @@ -550,9 +548,7 @@ describe('keyboard interaction mode', () => { // Tab upwards for (let i = tabToIndex - 1; i >= 0; i--) { await rendered(); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); await rendered(); const focusedRow = document.activeElement.parentElement.assignedSlot.parentElement.parentElement; expect(focusedRow.index).to.equal(i); diff --git a/packages/menu-bar/test/menu-bar.common.js b/packages/menu-bar/test/menu-bar.common.js index d59f5a2d07e..87c20e18384 100644 --- a/packages/menu-bar/test/menu-bar.common.js +++ b/packages/menu-bar/test/menu-bar.common.js @@ -243,9 +243,7 @@ describe('root menu layout', () => { it('should move focus to prev button on Shift Tab keydown', async () => { buttons[1].focus(); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(buttons[0].hasAttribute('focused')).to.be.true; }); diff --git a/packages/menu-bar/test/sub-menu.common.js b/packages/menu-bar/test/sub-menu.common.js index 950f11b163d..7e5dddad975 100644 --- a/packages/menu-bar/test/sub-menu.common.js +++ b/packages/menu-bar/test/sub-menu.common.js @@ -310,9 +310,7 @@ describe('sub-menu', () => { arrowDown(buttons[3]); await oneEvent(subMenu, 'opened-changed'); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); await nextRender(subMenu); expect(subMenu.opened).to.be.true; diff --git a/packages/password-field/test/password-field.common.js b/packages/password-field/test/password-field.common.js index 9c5c983e49d..4e6f2801b09 100644 --- a/packages/password-field/test/password-field.common.js +++ b/packages/password-field/test/password-field.common.js @@ -153,9 +153,7 @@ describe('password-field', () => { }); it('should not set focus-ring attribute when focusing reveal button with Shift Tab', async () => { - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(passwordField.hasAttribute('focus-ring')).to.be.false; }); @@ -165,9 +163,7 @@ describe('password-field', () => { revealButton.focus(); // Shift+Tab to the input element - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(passwordField.hasAttribute('focus-ring')).to.be.true; }); @@ -238,9 +234,7 @@ describe('disabled', () => { let focusInput; async function shiftTab() { - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); } beforeEach(() => { diff --git a/packages/popover/test/a11y.test.js b/packages/popover/test/a11y.test.js index 24acd107187..b49b4facf31 100644 --- a/packages/popover/test/a11y.test.js +++ b/packages/popover/test/a11y.test.js @@ -371,9 +371,7 @@ describe('a11y', () => { const spy = sinon.spy(target, 'focus'); // Move focus back to the target - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(spy).to.be.calledOnce; }); @@ -401,9 +399,7 @@ describe('a11y', () => { const focusable = overlay.querySelector('input'); const spy = sinon.spy(focusable, 'focus'); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(spy).to.be.calledOnce; }); @@ -429,9 +425,7 @@ describe('a11y', () => { await nextRender(); // Move focus back from the target - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); await nextRender(); const activeElement = getDeepActiveElement(); diff --git a/packages/radio-group/test/radio-group.common.js b/packages/radio-group/test/radio-group.common.js index 9a0842db1a8..ee04531ec2c 100644 --- a/packages/radio-group/test/radio-group.common.js +++ b/packages/radio-group/test/radio-group.common.js @@ -224,9 +224,7 @@ describe('radio-group', () => { await sendKeys({ press: 'Tab' }); // Move focus out of the group. - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(buttons[0].hasAttribute('focused')).to.be.false; expect(group.hasAttribute('focused')).to.be.false; diff --git a/packages/radio-group/test/validation.common.js b/packages/radio-group/test/validation.common.js index 3b823cabfb4..f669c532e2b 100644 --- a/packages/radio-group/test/validation.common.js +++ b/packages/radio-group/test/validation.common.js @@ -83,9 +83,7 @@ describe('validation', () => { expect(validateSpy.called).to.be.false; // Move focus out of the group. - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(validateSpy.calledOnce).to.be.true; }); @@ -124,9 +122,7 @@ describe('validation', () => { await sendKeys({ press: 'Tab' }); // Move focus out of the checkbox group. - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(validateSpy.called).to.be.false; }); diff --git a/packages/rich-text-editor/test/a11y.common.js b/packages/rich-text-editor/test/a11y.common.js index 43ff2a60112..d488861c60f 100644 --- a/packages/rich-text-editor/test/a11y.common.js +++ b/packages/rich-text-editor/test/a11y.common.js @@ -247,9 +247,7 @@ describe('accessibility', () => { it('should move focus to the first toolbar button after esc followed by shift-tab are pressed', async () => { await sendKeys({ press: 'Escape' }); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(getDeepActiveElement()).to.equal(buttons[0]); }); diff --git a/packages/upload/test/file.common.js b/packages/upload/test/file.common.js index 7eb5603980d..b88c626a5df 100644 --- a/packages/upload/test/file.common.js +++ b/packages/upload/test/file.common.js @@ -93,9 +93,7 @@ describe(' element', () => { button.focus(); // Move focus back to the upload file. - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(fileElement.hasAttribute('focus-ring')).to.be.true; }); @@ -106,9 +104,7 @@ describe(' element', () => { await sendKeys({ press: 'Tab' }); // Move focus back to the button. - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(fileElement.hasAttribute('focus-ring')).to.be.false; }); diff --git a/test/integration/dialog-accordion.test.js b/test/integration/dialog-accordion.test.js index 53797fe945d..9b6feaa3d69 100644 --- a/test/integration/dialog-accordion.test.js +++ b/test/integration/dialog-accordion.test.js @@ -49,9 +49,7 @@ describe('accordion in dialog', () => { panels[0].querySelector('input').focus(); // Move focus back to heading - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(document.activeElement).to.equal(panels[0].focusElement); }); @@ -75,9 +73,7 @@ describe('accordion in dialog', () => { panels[1].focus(); // Move focus back to first panel - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(document.activeElement).to.equal(panels[0].focusElement); }); diff --git a/test/integration/dialog-date-picker.test.js b/test/integration/dialog-date-picker.test.js index ab0fe522d91..b34e7941a13 100644 --- a/test/integration/dialog-date-picker.test.js +++ b/test/integration/dialog-date-picker.test.js @@ -51,9 +51,7 @@ describe('date-picker in dialog', () => { it('should focus the Cancel button on Shift + Tab when inside a dialog', async () => { // Focus the Cancel button - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(overlayContent._cancelButton.hasAttribute('focused')).to.be.true; }); @@ -67,9 +65,7 @@ describe('date-picker in dialog', () => { const spy = sinon.spy(datePicker.inputElement, 'focus'); - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); expect(spy.calledOnce).to.be.true; }); @@ -114,9 +110,7 @@ describe('date-picker in dialog', () => { it('should not close the dialog when closing date-picker on Cancel button Escape', async () => { // Focus the Cancel button - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); await sendKeys({ press: 'Escape' }); diff --git a/test/integration/grid-pro-custom-editor.test.js b/test/integration/grid-pro-custom-editor.test.js index 1df0f528eae..981c5ef1ac3 100644 --- a/test/integration/grid-pro-custom-editor.test.js +++ b/test/integration/grid-pro-custom-editor.test.js @@ -149,9 +149,7 @@ describe('grid-pro custom editor', () => { await waitForOverlayRender(); // Move focus back to the input - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); // Change single digit to avoid calendar scroll const input = cell._content.querySelector('input'); @@ -248,9 +246,7 @@ describe('grid-pro custom editor', () => { expect(cell._content.querySelector('vaadin-date-time-picker')).to.be.ok; // Move focus to the date-picker - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); await nextRender(); expect(cell._content.querySelector('vaadin-date-time-picker')).to.be.ok; }); @@ -260,9 +256,7 @@ describe('grid-pro custom editor', () => { await waitForOverlayRender(); // Move focus back to the input - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); // Change single digit to avoid calendar scroll const input = cell._content.querySelector('input'); @@ -318,9 +312,7 @@ describe('grid-pro custom editor', () => { expect(cell._content.querySelector('vaadin-custom-field')).to.be.ok; // Move focus to the first field - await sendKeys({ down: 'Shift' }); - await sendKeys({ press: 'Tab' }); - await sendKeys({ up: 'Shift' }); + await sendKeys({ press: 'Shift+Tab' }); await nextRender(); expect(cell._content.querySelector('vaadin-custom-field')).to.be.ok; }); diff --git a/test/test-runner-commands/index.js b/test/test-runner-commands/index.js index e2837d1a472..41abcd8f7c5 100644 --- a/test/test-runner-commands/index.js +++ b/test/test-runner-commands/index.js @@ -1 +1,53 @@ +import { executeServerCommand } from '@web/test-runner-commands'; + export * from '@web/test-runner-commands'; + +/** + * Extends the `sendKeys` command to support pressing multiple keys + * simultaneously when provided in the format "Shift+Tab". This format + * is natively supported by Playwright but not by Puppeteer. This wrapper + * enables the same syntax to be used in Puppeteer. + * + * In WebDriver, this functionality is still unavailable because + * web-test-runner does not provide an API for holding keys down. + * + * For more documentation on the original command, please see + * https://modern-web.dev/docs/test-runner/commands/#send-keys + * + * @typedef {{ type: string }} TypePayload + * @typedef {{ press: string }} PressPayload + * @typedef {{ down: string }} DownPayload + * @typedef {{ up: string }} UpPayload + * @param payload {TypePayload | PressPayload | DownPayload | UpPayload} + * + * @example + * // Tab to the next element + * await sendKeys({ press: 'Tab' }); + * + * @example + * // Tab to the previous element + * await sendKeys({ press: 'Shift+Tab' }); + * + * @example + * await sendKeys({ down: 'Shift' }); + * // Do something while holding Shift + * await sendKeys({ up: 'Shift' }); + */ +export async function sendKeys(payload) { + const { press } = payload; + if (press && press.includes('+')) { + const keys = press.split('+').map((key) => key.trim()); + + for (const key of keys) { + await executeServerCommand('send-keys', { down: key }); + } + + for (const key of keys.reverse()) { + await executeServerCommand('send-keys', { up: key }); + } + + return; + } + + await executeServerCommand('send-keys', payload); +}