diff --git a/README.md b/README.md
index 7e689a88..47774b9e 100644
--- a/README.md
+++ b/README.md
@@ -189,6 +189,33 @@ it('should click at coordinate', async() => {
});
```
+Elements configured using the [Drag & Drop API](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API) can be interacted with using `dragDropElems(sourceElem, destElem)`:
+
+```javascript
+import { dragDropElems } from '@brightspace-ui/testing';
+
+it('should drag & drop', async() => {
+ const rootElem = await fixture(html`
+
+ `);
+ // NOTE: destination must have "dragover" and "drop"
+ // event listeners added for the drag & drop API to function
+ await dragDropElems(
+ rootElem.querySelector('#source'),
+ rootElem.querySelector('#target')
+ );
+ // do assertions
+});
+
+it('should click at coordinate', async() => {
+ await clickAt(100, 200);
+ // do assertions
+});
+```
+
### Using the Keyboard
To place focus on an element using the keyboard, use `focusElem(elem)`. Doing so will trigger its `:focus-visible` CSS pseudo-class.
diff --git a/src/browser/commands.js b/src/browser/commands.js
index c4ff67af..ab9b5a56 100644
--- a/src/browser/commands.js
+++ b/src/browser/commands.js
@@ -24,6 +24,15 @@ export async function clickElem(elem) {
return clickAt(position.x, position.y);
}
+export async function dragDropElems(elem, toElem) {
+ const fromPosition = getElementPosition(elem);
+ const toPosition = getElementPosition(toElem);
+ await sendMouse({ type: 'move', position: [fromPosition.x, fromPosition.y] });
+ await sendMouse({ type: 'down' });
+ await sendMouse({ type: 'move', position: [toPosition.x, toPosition.y] });
+ 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 });
diff --git a/src/browser/index.js b/src/browser/index.js
index 52898e33..317882fb 100644
--- a/src/browser/index.js
+++ b/src/browser/index.js
@@ -1,6 +1,6 @@
import './vdiff.js';
export { assert, aTimeout, defineCE, expect, html, nextFrame, oneDefaultPreventedEvent, oneEvent, waitUntil } from '@open-wc/testing';
-export { clickAt, clickElem, focusElem, hoverAt, hoverElem, sendKeys, sendKeysElem, setViewport } from './commands.js';
+export { clickAt, clickElem, dragDropElems, focusElem, hoverAt, hoverElem, sendKeys, sendKeysElem, setViewport } from './commands.js';
export { fixture } from './fixture.js';
export { runConstructor } from './constructor.js';
diff --git a/test/browser/commands.test.js b/test/browser/commands.test.js
index 857f7209..fce6bcf9 100644
--- a/test/browser/commands.test.js
+++ b/test/browser/commands.test.js
@@ -1,87 +1,131 @@
-import { clickAt, clickElem, expect, fixture, focusElem, hoverAt, hoverElem, sendKeys, sendKeysElem, setViewport } from '../../src/browser/index.js';
+import { clickAt, clickElem, dragDropElems, expect, fixture, focusElem, hoverAt, hoverElem, sendKeys, sendKeysElem, setViewport } from '../../src/browser/index.js';
import { html } from 'lit';
import { spy } from 'sinon';
describe('commands', () => {
- let elem;
- const input = html``;
- beforeEach(async() => {
- elem = await fixture(input);
- });
+ describe('click/hover', () => {
- it('should click on element', async() => {
- const clickSpy = spy();
- elem.addEventListener('click', clickSpy);
- await clickElem(elem);
- expect(clickSpy).to.be.calledOnce;
- });
+ let elem;
+ beforeEach(async() => {
+ elem = await fixture(html``);
+ });
- it('should click at position', async() => {
- const clickPos = { x: 0, y: 0 };
- function onClick(e) {
- clickPos.x = e.clientX;
- clickPos.y = e.clientY;
- }
- window.addEventListener('click', onClick);
- await clickAt(200, 300);
- expect(clickPos.x).to.equal(200);
- expect(clickPos.y).to.equal(300);
- window.removeEventListener('click', onClick);
- });
+ it('should click on element', async() => {
+ const clickSpy = spy();
+ elem.addEventListener('click', clickSpy);
+ await clickElem(elem);
+ expect(clickSpy).to.be.calledOnce;
+ });
- it('should focus on element', async() => {
- let focussed = false;
- elem.addEventListener('focus', () => focussed = true);
- await focusElem(elem);
- expect(focussed).to.be.true;
- });
+ it('should click at position', async() => {
+ const clickPos = { x: 0, y: 0 };
+ function onClick(e) {
+ clickPos.x = e.clientX;
+ clickPos.y = e.clientY;
+ }
+ window.addEventListener('click', onClick);
+ await clickAt(200, 300);
+ expect(clickPos.x).to.equal(200);
+ expect(clickPos.y).to.equal(300);
+ window.removeEventListener('click', onClick);
+ });
- it('should hover over element', async() => {
- let hovered = false;
- elem.addEventListener('mouseover', () => hovered = true);
- elem.addEventListener('mouseout', () => hovered = false);
- await hoverElem(elem);
- expect(hovered).to.be.true;
- });
+ it('should hover over element', async() => {
+ let hovered = false;
+ elem.addEventListener('mouseover', () => hovered = true);
+ elem.addEventListener('mouseout', () => hovered = false);
+ await hoverElem(elem);
+ expect(hovered).to.be.true;
+ });
+
+ it('should hover at position', async() => {
+ const mousePos = { x: 0, y: 0 };
+ function onMouseMove(e) {
+ mousePos.x = e.clientX;
+ mousePos.y = e.clientY;
+ }
+ window.addEventListener('mousemove', onMouseMove);
+ await hoverAt(50, 100);
+ expect(mousePos.x).to.equal(50);
+ expect(mousePos.y).to.equal(100);
+ window.removeEventListener('mousemove', onMouseMove);
+ });
- it('should hover at position', async() => {
- const mousePos = { x: 0, y: 0 };
- function onMouseMove(e) {
- mousePos.x = e.clientX;
- mousePos.y = e.clientY;
- }
- window.addEventListener('mousemove', onMouseMove);
- await hoverAt(50, 100);
- expect(mousePos.x).to.equal(50);
- expect(mousePos.y).to.equal(100);
- window.removeEventListener('mousemove', onMouseMove);
});
- it('should send keys to element', async() => {
- await sendKeysElem(elem, 'type', 'Hello');
- expect(elem.value).to.equal('Hello');
+ describe('keyboard/focus', async() => {
+
+ let elem;
+ beforeEach(async() => {
+ elem = await fixture(html``);
+ });
+
+ it('should focus on element', async() => {
+ let focussed = false;
+ elem.addEventListener('focus', () => focussed = true);
+ await focusElem(elem);
+ expect(focussed).to.be.true;
+ });
+
+ it('should send keys to element', async() => {
+ await sendKeysElem(elem, 'type', 'Hello');
+ expect(elem.value).to.equal('Hello');
+ });
+
+ it('should send keys to browser', async() => {
+ let key = undefined;
+ function onKeyDown(e) {
+ key = e.key;
+ }
+ window.addEventListener('keydown', onKeyDown);
+ await sendKeys('press', 'Escape');
+ expect(key).to.equal('Escape');
+ window.removeEventListener('keydown', onKeyDown);
+ });
+
});
- it('should send keys to browser', async() => {
- let key = undefined;
- function onKeyDown(e) {
- key = e.key;
- }
- window.addEventListener('keydown', onKeyDown);
- await sendKeys('press', 'Escape');
- expect(key).to.equal('Escape');
- window.removeEventListener('keydown', onKeyDown);
+ describe('drag & drop', () => {
+
+ it('should drag & drop element', (done) => {
+ fixture(html``).then(rootElem => {
+
+ let dragSource;
+ const sourceElem = rootElem.querySelector('#source');
+ sourceElem.addEventListener('dragstart', e => dragSource = e.target);
+
+ const destElem = rootElem.querySelector('#dest');
+ destElem.addEventListener('dragover', e => e.preventDefault());
+ destElem.addEventListener('drop', (e) => {
+ e.preventDefault();
+ expect(dragSource).to.equal(sourceElem);
+ done();
+ });
+
+ dragDropElems(sourceElem, destElem);
+
+ });
+ });
+
});
describe('mouseReset', () => {
+
const mousePos = { x: 0, y: 0 };
function onMouseMove(e) {
mousePos.x = e.clientX;
mousePos.y = e.clientY;
}
- beforeEach(() => {
+ const buttonTemplate = html``;
+
+ let elem;
+ beforeEach(async() => {
+ elem = await fixture(buttonTemplate);
window.addEventListener('mousemove', onMouseMove);
});
@@ -99,7 +143,7 @@ describe('commands', () => {
await action(elem);
expect(mousePos.x).to.not.equal(0);
expect(mousePos.y).to.not.equal(0);
- await fixture(input);
+ await fixture(buttonTemplate);
expect(mousePos.x).to.equal(0);
expect(mousePos.y).to.equal(0);
});
@@ -108,6 +152,10 @@ describe('commands', () => {
describe('viewport', () => {
+ beforeEach(async() => {
+ await fixture(html``);
+ });
+
it('should set width and height', async() => {
await setViewport({ height: 200, width: 300 });
expect(window.innerHeight).to.equal(200);