Skip to content

Commit

Permalink
feat: basic keyboard and mouse commands (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
dlockhart authored Jun 20, 2023
1 parent 7dd40e2 commit d53acfb
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 18 deletions.
45 changes: 45 additions & 0 deletions src/browser/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { sendKeys as cmdSendKeys, sendMouse } from '@web/test-runner-commands';

function getElementPosition(elem) {
const { x, y, width, height } = elem.getBoundingClientRect();
return {
x: Math.floor(x + window.scrollX + width / 2),
y: Math.floor(y + window.scrollY + height / 2),
};
}

export async function clickAt(x, y) {
await sendMouse({ type: 'click', position: [x, y] });
}

export async function clickElem(elem) {
const position = getElementPosition(elem);
return clickAt(position.x, position.y);
}

export async function focusElem(elem) {
await cmdSendKeys({ press: 'Shift' }); // Tab moves focus, Escape causes dismissible things to close
elem.focus({ focusVisible: true });
}

export async function hoverAt(x, y) {
await sendMouse({ type: 'move', position: [x, y] });
}

export async function hoverElem(elem) {
const position = getElementPosition(elem);
return hoverAt(position.x, position.y);
}

export async function sendKeys(action, keys) {
const val = {};
val[action] = keys;
await cmdSendKeys(val);
}

export async function sendKeysElem(action, keys, elem) {
if (elem) {
await focusElem(elem);
}
return sendKeys(action, keys);
}
12 changes: 0 additions & 12 deletions src/browser/focus.js

This file was deleted.

2 changes: 1 addition & 1 deletion src/browser/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import './vdiff.js';

export { assert, aTimeout, defineCE, expect, html, nextFrame, oneEvent, waitUntil } from '@open-wc/testing';
export { focusWithKeyboard, focusWithMouse } from './focus.js';
export { clickAt, clickElem, focusElem, hoverAt, hoverElem, sendKeys, sendKeysElem } from './commands.js';
export { fixture } from './fixture.js';
76 changes: 76 additions & 0 deletions test/browser/commands.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { clickAt, clickElem, expect, fixture, focusElem, hoverAt, hoverElem, sendKeys, sendKeysElem } from '../../src/browser/index.js';
import { html } from 'lit';
import { spy } from 'sinon';

describe('commands', () => {

let elem;
beforeEach(async() => {
elem = await fixture(html`<input type="text">`);
});

it('should click on element', async() => {
const clickSpy = spy();
elem.addEventListener('click', clickSpy);
await clickElem(elem);
expect(clickSpy).to.be.calledOnce;
});

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 focus on element', async() => {
let focussed = false;
elem.addEventListener('focus', () => focussed = true);
await focusElem(elem);
expect(focussed).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 send keys to element', async() => {
await sendKeysElem('type', 'Hello', elem);
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);
});

});
9 changes: 4 additions & 5 deletions test/browser/fixture.test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@

import { defineCE, expect, waitUntil } from '@open-wc/testing';
import { html, LitElement } from 'lit';
import { defineCE, expect, fixture, html, waitUntil } from '../../src/browser/index.js';
import { restore, stub } from 'sinon';
import { fixture } from '../../src/browser/index.js';
import { focusWithKeyboard } from '../../src/browser/focus.js';
import { focusElem } from '../../src/browser/commands.js';
import { LitElement } from 'lit';
import { sendMouse } from '@web/test-runner-commands';
import { unsafeHTML } from 'lit/directives/unsafe-html.js';

Expand Down Expand Up @@ -97,7 +96,7 @@ describe('fixture', () => {
it('should reset focus', async() => {
const elem = await fixture(html`<button>hello</button>`);
expect(document.activeElement).to.equal(document.body);
await focusWithKeyboard(elem);
await focusElem(elem);
expect(document.activeElement).to.equal(elem);
await fixture(html`<div>hello</div>`);
expect(document.activeElement).to.equal(document.body);
Expand Down

0 comments on commit d53acfb

Please sign in to comment.