Skip to content

Commit

Permalink
feat(core): keyboard shortcuts
Browse files Browse the repository at this point in the history
  • Loading branch information
blakebyrnes committed Mar 1, 2022
1 parent af23474 commit 19fa006
Show file tree
Hide file tree
Showing 9 changed files with 50 additions and 3 deletions.
3 changes: 3 additions & 0 deletions client/interfaces/IInteractions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { IKeyboardKeyCode } from '@ulixee/hero-interfaces/IKeyboardLayoutUS';
import { IKeyboardShortcut } from '@ulixee/hero-interfaces/IKeyboardShortcuts';
import {
IElementInteractVerification,
IMousePositionXY,
Expand Down Expand Up @@ -36,6 +37,7 @@ export enum Command {

keyPress = 'keyPress',
keyDown = 'keyDown',
keyShortcut = 'keyShortcut',
keyUp = 'keyUp',
type = 'type',

Expand Down Expand Up @@ -68,6 +70,7 @@ export interface ICommandDetailed {
[Command.keyPress]?: IKeyboardKeyCode;
[Command.keyUp]?: IKeyboardKeyCode;
[Command.keyDown]?: IKeyboardKeyCode;
[Command.keyShortcut]?: IKeyboardShortcut;

[Command.waitForMillis]?: number;
}
Expand Down
4 changes: 2 additions & 2 deletions client/lib/DomExtender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import Interactor from './Interactor';
import XPathResult from 'awaited-dom/impl/official-klasses/XPathResult';
import { createSuperNode } from 'awaited-dom/impl/create';
import { getAwaitedPathAsMethodArg } from './SetupAwaitedHandler';
import { KeyboardShortcuts } from '@ulixee/hero-interfaces/IKeyboardShortcuts';

const awaitedPathState = StateMachine<
any,
Expand Down Expand Up @@ -118,8 +119,7 @@ const NodeExtensionFns: INodeExtensionFns = {
const coreFrame = await awaitedOptions.coreFrame;
await Interactor.run(coreFrame, [
{ click: this },
{ keyDown: KeyboardKey.Meta, keyPress: KeyboardKey.a },
{ keyUp: KeyboardKey.Meta },
{ keyShortcut: KeyboardShortcuts.selectAll },
{ keyPress: KeyboardKey.Backspace },
]);
},
Expand Down
8 changes: 8 additions & 0 deletions client/lib/Interactor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import IInteractions, {
} from '../interfaces/IInteractions';
import CoreFrameEnvironment from './CoreFrameEnvironment';
import { isAwaitedNode } from './SetupAwaitedHandler';
import { IKeyboardShortcut } from '@ulixee/hero-interfaces/IKeyboardShortcuts';

const { getState } = StateMachine<ISuperElement | ISuperNode, { awaitedPath: AwaitedPath }>();

Expand Down Expand Up @@ -200,6 +201,13 @@ function convertInteractionToInteractionGroup(interaction: IInteraction): IInter
const command = CoreCommand.type;
return iGroup.push({ command, keyboardCommands: [{ down: value as IKeyboardKeyCode }] });
}
case Command.keyShortcut: {
const command = CoreCommand.type;
return iGroup.push({
command,
keyboardCommands: [{ shortcut: value as IKeyboardShortcut }],
});
}
case Command.keyUp: {
const command = CoreCommand.type;
return iGroup.push({ command, keyboardCommands: [{ up: value as IKeyboardKeyCode }] });
Expand Down
2 changes: 2 additions & 0 deletions core/lib/Interactor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,8 @@ export default class Interactor implements IInteractionsHelper {
} else if ('down' in keyboardCommand) {
const key = getKeyboardKey(keyboardCommand.down);
await this.keyboard.down(key);
} else if ('shortcut' in keyboardCommand) {
await this.keyboard.command(keyboardCommand.shortcut);
} else if ('string' in keyboardCommand) {
const text = keyboardCommand.string;
for (const char of text) {
Expand Down
9 changes: 9 additions & 0 deletions fullstack/test/domExtenders.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ describe('basic DomExtender tests', () => {
await expect(hero.querySelector('#field').$click()).resolves.toBe(undefined);
await expect(hero.querySelector('#field').$hasFocus).resolves.toBe(true);
});

it('can clear a field', async () => {
koaServer.get('/domextender-clear', ctx => {
ctx.body = `<body><input id="field" type="text" value="1234Test"/></body>`;
});
const hero = await openBrowser(`/domextender-clear`);
await expect(hero.querySelector('#field').$clearValue()).resolves.toBe(undefined);
await expect(hero.querySelector('#field').value).resolves.toBe('');
});
});

async function openBrowser(path: string) {
Expand Down
6 changes: 5 additions & 1 deletion interfaces/IInteractions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { IJsPath } from 'awaited-dom/base/AwaitedPath';
import { IKeyboardKeyCode } from './IKeyboardLayoutUS';
import IMouseResult from './IMouseResult';
import IPoint from './IPoint';
import { IKeyboardShortcut } from './IKeyboardShortcuts';

export type IElementInteractVerification = 'elementAtPath' | 'exactElement' | 'none';

Expand Down Expand Up @@ -71,13 +72,16 @@ export type IMousePosition = IMousePositionXY | IJsPath;
// Keyboard-specific Types

export type IKeyboardCommand = IKeyPress | IKeyboardObject;
export type IKeyboardObject = IKeyboardString | IKeyboardUp | IKeyboardDown;
export type IKeyboardObject = IKeyboardString | IKeyboardUp | IKeyboardDown | IKeyShortcutPress;
export interface IKeyboardString {
string: string;
}
export interface IKeyPress {
keyCode: IKeyboardKeyCode;
}
export interface IKeyShortcutPress {
shortcut: IKeyboardShortcut;
}
export interface IKeyboardUp {
up: IKeyboardKeyCode;
}
Expand Down
13 changes: 13 additions & 0 deletions interfaces/IKeyboardShortcuts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export enum KeyboardShortcuts {
'selectAll' = 'selectAll',

'delete' = 'delete',
'deleteBackward' = 'deleteBackward',
'deleteForward' = 'deleteForward',
'deleteToEndOfParagraph' = 'deleteToEndOfParagraph',
'deleteWordForward' = 'deleteWordForward',
'deleteWordBackward' = 'deleteWordBackward',
'deleteToBeginningOfLine' = 'deleteToBeginningOfLine',
}

export type IKeyboardShortcut = keyof typeof KeyboardShortcuts;
1 change: 1 addition & 0 deletions interfaces/IPuppetInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export interface IPuppetKeyboard {
up(key: IKeyboardKey): Promise<void>;
down(key: IKeyboardKey): Promise<void>;
press(key: IKeyboardKey, keyupDelay?: number): Promise<void>;
command(command: string): Promise<void>;
insertText(text: string): Promise<void>;
sendCharacter(char: string): Promise<void>;
}
Expand Down
7 changes: 7 additions & 0 deletions puppet-chrome/lib/Keyboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ export class Keyboard implements IPuppetKeyboard {
});
}

async command(command: string): Promise<void> {
await this.devtoolsSession.send('Input.dispatchKeyEvent', {
type: 'rawKeyDown',
commands: [command],
});
}

async up(key: IKeyboardKey): Promise<void> {
const description = this.keyDescriptionForString(key);

Expand Down

0 comments on commit 19fa006

Please sign in to comment.