-
Notifications
You must be signed in to change notification settings - Fork 1
GAUD-10597 - Add drag test command #1069
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,6 +40,22 @@ export async function dragDropElems(elem, toElem) { | |
| await sendMouse({ type: 'up' }); | ||
| } | ||
|
|
||
| export async function dragElemBy(elem, offsetX = 0, offsetY = 0) { | ||
| const pixels = 10; // Mimic dragging by moving in 10px increments to the target position | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I want to simulate a user actually dragging something, which fires events every few pixels. Just moving from one place to another programmatically doesn't fire any intermediate values. I'm firing every 10px, but this could also just break up the values passed into 5 steps of |
||
| const numSteps = Math.ceil(Math.max(Math.abs(offsetX), Math.abs(offsetY)) / pixels); | ||
|
|
||
| const position = getElementPosition(elem); | ||
| await sendMouse({ type: 'move', position: [position.x, position.y] }); | ||
|
|
||
| await sendMouse({ type: 'down' }); | ||
| for (let i = 1; i <= numSteps; i++) { | ||
| const dx = Math.sign(offsetX) * Math.min(Math.abs(offsetX), pixels * i); | ||
| const dy = Math.sign(offsetY) * Math.min(Math.abs(offsetY), pixels * i); | ||
| await sendMouse({ type: 'move', position: [position.x + dx, position.y + dy] }); | ||
| } | ||
| await sendMouse({ type: 'up' }); | ||
| } | ||
|
|
||
| export async function focusElem(elem) { | ||
| await cmdSendKeys({ press: 'Shift' }); // Tab moves focus, Escape causes dismissible things to close | ||
| elem.focus({ focusVisible: true }); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,10 @@ | ||
| import { clickAt, clickElem, clickElemAt, dragDropElems, expect, fixture, focusElem, hoverAt, hoverElem, hoverElemAt, sendKeys, sendKeysElem, setViewport } from '../../src/browser/index.js'; | ||
| import { clickAt, clickElem, clickElemAt, dragDropElems, dragElemBy, expect, fixture, focusElem, hoverAt, hoverElem, hoverElemAt, sendKeys, sendKeysElem, setViewport } from '../../src/browser/index.js'; | ||
| import { html } from 'lit'; | ||
| import { spy } from 'sinon'; | ||
|
|
||
| describe('commands', () => { | ||
| const buttonTemplate = html`<button>text</button>`; | ||
| const dragTemplate = html`<div style="position: absolute; top: 95px; left: 95px; width: 10px; height: 10px;"></div>`; | ||
| const draggableTemplate = html` | ||
| <div> | ||
| <div id="dest" style="height: 100px; width: 100px;"></div> | ||
|
|
@@ -19,6 +20,7 @@ describe('commands', () => { | |
| let elem, focusSource, hovered, key, keys; | ||
| const clickPos = { x: 0, y: 0 }; | ||
| const mousePos = { x: 0, y: 0 }; | ||
| const pointerEvents = []; | ||
|
|
||
| function onClick(e) { | ||
| clickPos.x = e.clientX; | ||
|
|
@@ -41,6 +43,14 @@ describe('commands', () => { | |
| mousePos.y = e.clientY; | ||
| } | ||
|
|
||
| function onPointer(e) { | ||
| pointerEvents.push({ | ||
| type: e.type, | ||
| x: e.clientX, | ||
| y: e.clientY | ||
| }); | ||
| } | ||
|
|
||
| function onMouseOver() { | ||
| hovered = true; | ||
| } | ||
|
|
@@ -53,12 +63,22 @@ describe('commands', () => { | |
| window.addEventListener('click', onClick); | ||
| window.addEventListener('keydown', onKeyDown); | ||
| window.addEventListener('mousemove', onMouseMove); | ||
| window.addEventListener('pointerdown', onPointer); | ||
| window.addEventListener('pointermove', onPointer); | ||
| window.addEventListener('pointerup', onPointer); | ||
| }); | ||
|
|
||
| beforeEach(() => { | ||
| pointerEvents.length = 0; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also not sure I love this - was trying to follow the pattern of the file and define this stuff at the top level. But it might be better to just set it and remove it in the tests below, rather than having to clear this value every test, then clear it again after calling the fixture so I don't get any mouse moves as things reset.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is what that looks like instead: #1070 |
||
| }); | ||
|
|
||
| after(() => { | ||
| window.removeEventListener('click', onClick); | ||
| window.removeEventListener('keydown', onKeyDown); | ||
| window.removeEventListener('mousemove', onMouseMove); | ||
| window.removeEventListener('pointerdown', onPointer); | ||
| window.removeEventListener('pointermove', onPointer); | ||
| window.removeEventListener('pointerup', onPointer); | ||
| }); | ||
|
|
||
| describe('click/hover', () => { | ||
|
|
@@ -194,6 +214,53 @@ describe('commands', () => { | |
|
|
||
| }); | ||
|
|
||
| describe('drag', () => { | ||
| const getDragMoves = (events) => events.slice(1).filter(e => e.type === 'pointermove').map(e => ({ x: e.x, y: e.y })); | ||
|
|
||
| beforeEach(async() => { | ||
| elem = await fixture(dragTemplate); | ||
| pointerEvents.length = 0; | ||
| }); | ||
|
|
||
| it('should start dragging from the center of element and fire pointer events throughout the full drag flow', async() => { | ||
| await dragElemBy(elem, 20, 20); | ||
| expect(pointerEvents).to.deep.equal([ | ||
| { type: 'pointermove', x: 100, y: 100 }, // Move to element center | ||
| { type: 'pointerdown', x: 100, y: 100 }, // Start drag | ||
| { type: 'pointermove', x: 110, y: 110 }, // Drag 10px | ||
| { type: 'pointermove', x: 120, y: 120 }, // Drag 10px | ||
| { type: 'pointerup', x: 120, y: 120 }, // End drag | ||
| ]); | ||
| }); | ||
|
|
||
| it('should move to the target offset in 10px increments to the max', async() => { | ||
| await dragElemBy(elem, 25, 0); | ||
| expect(getDragMoves(pointerEvents)).to.deep.equal([ | ||
| { x: 110, y: 100 }, | ||
| { x: 120, y: 100 }, | ||
| { x: 125, y: 100 }, | ||
| ]); | ||
| }); | ||
|
|
||
| it('should clamp the shorter axis while the longer axis keeps stepping', async() => { | ||
| await dragElemBy(elem, 30, 15); | ||
| expect(getDragMoves(pointerEvents)).to.deep.equal([ | ||
| { x: 110, y: 110 }, | ||
| { x: 120, y: 115 }, | ||
| { x: 130, y: 115 }, | ||
| ]); | ||
| }); | ||
|
|
||
| it('should drag in negative directions', async() => { | ||
| await dragElemBy(elem, -25, -25); | ||
| expect(getDragMoves(pointerEvents)).to.deep.equal([ | ||
| { x: 90, y: 90 }, | ||
| { x: 80, y: 80 }, | ||
| { x: 75, y: 75 }, | ||
| ]); | ||
| }); | ||
| }); | ||
|
|
||
| describe('drag & drop', () => { | ||
|
|
||
| it('should drag & drop element', (done) => { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Name is a little odd. I'm trying to follow the pattern of the other helpers in this file, taking x and y offsets as parameters. They work a little differently though, and use "at" terminology, which doesn't make sense here.
But
dragElemToisn't correct, unless I take anxandylocation rather than an offset. This is nicer for the helper, worse for the consumer - it's much easier if I can say "Drag it back 5 pixels" instead of "Drag it to spot x = 250".