feat: implement mac keyboard
This commit is contained in:
parent
44d6f608ef
commit
41868b0472
|
|
@ -10,7 +10,7 @@
|
||||||
"playwright": {
|
"playwright": {
|
||||||
"chromium_revision": "719491",
|
"chromium_revision": "719491",
|
||||||
"firefox_revision": "1004",
|
"firefox_revision": "1004",
|
||||||
"webkit_revision": "1023"
|
"webkit_revision": "1025"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"unit": "node test/test.js",
|
"unit": "node test/test.js",
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
type KeyDefinition = {
|
type KeyDefinition = {
|
||||||
keyCode?: number;
|
keyCode?: number;
|
||||||
|
keyCodeWithoutLocation?: number;
|
||||||
shiftKeyCode?: number;
|
shiftKeyCode?: number;
|
||||||
key?: string;
|
key?: string;
|
||||||
shiftKey?: string;
|
shiftKey?: string;
|
||||||
|
|
@ -51,12 +52,12 @@ export const keyDefinitions: { [s: string]: KeyDefinition; } = {
|
||||||
'Enter': {'keyCode': 13, 'code': 'Enter', 'key': 'Enter', 'text': '\r'},
|
'Enter': {'keyCode': 13, 'code': 'Enter', 'key': 'Enter', 'text': '\r'},
|
||||||
'\r': {'keyCode': 13, 'code': 'Enter', 'key': 'Enter', 'text': '\r'},
|
'\r': {'keyCode': 13, 'code': 'Enter', 'key': 'Enter', 'text': '\r'},
|
||||||
'\n': {'keyCode': 13, 'code': 'Enter', 'key': 'Enter', 'text': '\r'},
|
'\n': {'keyCode': 13, 'code': 'Enter', 'key': 'Enter', 'text': '\r'},
|
||||||
'ShiftLeft': {'keyCode': 16, 'code': 'ShiftLeft', 'key': 'Shift', 'location': 1, 'windowsVirtualKeyCode': 160},
|
'ShiftLeft': {'keyCode': 160, 'keyCodeWithoutLocation': 16, 'code': 'ShiftLeft', 'key': 'Shift', 'location': 1, 'windowsVirtualKeyCode': 160},
|
||||||
'ShiftRight': {'keyCode': 16, 'code': 'ShiftRight', 'key': 'Shift', 'location': 2, 'windowsVirtualKeyCode': 161},
|
'ShiftRight': {'keyCode': 161, 'keyCodeWithoutLocation': 16, 'code': 'ShiftRight', 'key': 'Shift', 'location': 2, 'windowsVirtualKeyCode': 161},
|
||||||
'ControlLeft': {'keyCode': 17, 'code': 'ControlLeft', 'key': 'Control', 'location': 1, 'windowsVirtualKeyCode': 162},
|
'ControlLeft': {'keyCode': 162, 'keyCodeWithoutLocation': 17, 'code': 'ControlLeft', 'key': 'Control', 'location': 1, 'windowsVirtualKeyCode': 162},
|
||||||
'ControlRight': {'keyCode': 17, 'code': 'ControlRight', 'key': 'Control', 'location': 2, 'windowsVirtualKeyCode': 163},
|
'ControlRight': {'keyCode': 163, 'keyCodeWithoutLocation': 17, 'code': 'ControlRight', 'key': 'Control', 'location': 2, 'windowsVirtualKeyCode': 163},
|
||||||
'AltLeft': {'keyCode': 18, 'code': 'AltLeft', 'key': 'Alt', 'location': 1, 'windowsVirtualKeyCode': 164},
|
'AltLeft': {'keyCode': 164, 'keyCodeWithoutLocation': 18, 'code': 'AltLeft', 'key': 'Alt', 'location': 1, 'windowsVirtualKeyCode': 164},
|
||||||
'AltRight': {'keyCode': 18, 'code': 'AltRight', 'key': 'Alt', 'location': 2, 'windowsVirtualKeyCode': 165},
|
'AltRight': {'keyCode': 165, 'keyCodeWithoutLocation': 18, 'code': 'AltRight', 'key': 'Alt', 'location': 2, 'windowsVirtualKeyCode': 165},
|
||||||
'Pause': {'keyCode': 19, 'code': 'Pause', 'key': 'Pause'},
|
'Pause': {'keyCode': 19, 'code': 'Pause', 'key': 'Pause'},
|
||||||
'CapsLock': {'keyCode': 20, 'code': 'CapsLock', 'key': 'CapsLock'},
|
'CapsLock': {'keyCode': 20, 'code': 'CapsLock', 'key': 'CapsLock'},
|
||||||
'Escape': {'keyCode': 27, 'code': 'Escape', 'key': 'Escape'},
|
'Escape': {'keyCode': 27, 'code': 'Escape', 'key': 'Escape'},
|
||||||
|
|
@ -178,9 +179,9 @@ export const keyDefinitions: { [s: string]: KeyDefinition; } = {
|
||||||
'Props': {'keyCode': 247, 'code': 'Props', 'key': 'CrSel'},
|
'Props': {'keyCode': 247, 'code': 'Props', 'key': 'CrSel'},
|
||||||
'Cancel': {'keyCode': 3, 'key': 'Cancel', 'code': 'Abort'},
|
'Cancel': {'keyCode': 3, 'key': 'Cancel', 'code': 'Abort'},
|
||||||
'Clear': {'keyCode': 12, 'key': 'Clear', 'code': 'Numpad5', 'location': 3},
|
'Clear': {'keyCode': 12, 'key': 'Clear', 'code': 'Numpad5', 'location': 3},
|
||||||
'Shift': {'keyCode': 16, 'key': 'Shift', 'code': 'ShiftLeft', 'location': 1, 'windowsVirtualKeyCode': 160},
|
'Shift': {'keyCode': 160, 'keyCodeWithoutLocation': 16, 'key': 'Shift', 'code': 'ShiftLeft', 'location': 1, 'windowsVirtualKeyCode': 160},
|
||||||
'Control': {'keyCode': 17, 'key': 'Control', 'code': 'ControlLeft', 'location': 1, 'windowsVirtualKeyCode': 162},
|
'Control': {'keyCode': 162, 'keyCodeWithoutLocation': 17, 'key': 'Control', 'code': 'ControlLeft', 'location': 1, 'windowsVirtualKeyCode': 162},
|
||||||
'Alt': {'keyCode': 18, 'key': 'Alt', 'code': 'AltLeft', 'location': 1, 'windowsVirtualKeyCode': 164},
|
'Alt': {'keyCode': 164, 'keyCodeWithoutLocation': 18, 'key': 'Alt', 'code': 'AltLeft', 'location': 1, 'windowsVirtualKeyCode': 164},
|
||||||
'Accept': {'keyCode': 30, 'key': 'Accept'},
|
'Accept': {'keyCode': 30, 'key': 'Accept'},
|
||||||
'ModeChange': {'keyCode': 31, 'key': 'ModeChange'},
|
'ModeChange': {'keyCode': 31, 'key': 'ModeChange'},
|
||||||
' ': {'keyCode': 32, 'key': ' ', 'code': 'Space'},
|
' ': {'keyCode': 32, 'key': ' ', 'code': 'Space'},
|
||||||
|
|
@ -286,3 +287,114 @@ export const keyDefinitions: { [s: string]: KeyDefinition; } = {
|
||||||
'VolumeDown': {'keyCode': 182, 'key': 'VolumeDown', 'code': 'VolumeDown', 'location': 4},
|
'VolumeDown': {'keyCode': 182, 'key': 'VolumeDown', 'code': 'VolumeDown', 'location': 4},
|
||||||
'VolumeUp': {'keyCode': 183, 'key': 'VolumeUp', 'code': 'VolumeUp', 'location': 4},
|
'VolumeUp': {'keyCode': 183, 'key': 'VolumeUp', 'code': 'VolumeUp', 'location': 4},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const macEditingCommands: {[key: string]: string|string[]} = {
|
||||||
|
'Backspace': 'deleteBackward:',
|
||||||
|
'Tab': 'insertTab:',
|
||||||
|
'Enter': 'insertNewline:',
|
||||||
|
'Escape': 'cancelOperation:',
|
||||||
|
'ArrowUp': 'moveUp:',
|
||||||
|
'ArrowDown': 'moveDown:',
|
||||||
|
'ArrowLeft': 'moveLeft:',
|
||||||
|
'ArrowRight': 'moveRight:',
|
||||||
|
'F5': 'complete:',
|
||||||
|
'Delete': 'deleteForward:',
|
||||||
|
'Home': 'scrollToBeginningOfDocument:',
|
||||||
|
'End': 'scrollToEndOfDocument:',
|
||||||
|
'PageUp': 'scrollPageUp:',
|
||||||
|
'PageDown': 'scrollPageDown:',
|
||||||
|
'Shift+Backspace': 'deleteBackward:',
|
||||||
|
'Shift+Enter': 'insertNewline:',
|
||||||
|
'Shift+Tab': 'insertBacktab:',
|
||||||
|
'Shift+Escape': 'cancelOperation:',
|
||||||
|
'Shift+ArrowUp': 'moveUpAndModifySelection:',
|
||||||
|
'Shift+ArrowDown': 'moveDownAndModifySelection:',
|
||||||
|
'Shift+ArrowLeft': 'moveLeftAndModifySelection:',
|
||||||
|
'Shift+ArrowRight': 'moveRightAndModifySelection:',
|
||||||
|
'Shift+F5': 'complete:',
|
||||||
|
'Shift+Delete': 'deleteForward:',
|
||||||
|
'Shift+Home': 'moveToBeginningOfDocumentAndModifySelection:',
|
||||||
|
'Shift+End': 'moveToEndOfDocumentAndModifySelection:',
|
||||||
|
'Shift+PageUp': 'pageUpAndModifySelection:',
|
||||||
|
'Shift+PageDown': 'pageDownAndModifySelection:',
|
||||||
|
'Shift+Numpad5': 'delete:',
|
||||||
|
'Control+Tab': 'selectNextKeyView:',
|
||||||
|
'Control+Enter': 'insertLineBreak:',
|
||||||
|
'Control+Quote': 'insertSingleQuoteIgnoringSubstitution:',
|
||||||
|
'Control+KeyA': 'moveToBeginningOfParagraph:',
|
||||||
|
'Control+KeyB': 'moveBackward:',
|
||||||
|
'Control+KeyD': 'deleteForward:',
|
||||||
|
'Control+KeyE': 'moveToEndOfParagraph:',
|
||||||
|
'Control+KeyF': 'moveForward:',
|
||||||
|
'Control+KeyH': 'deleteBackward:',
|
||||||
|
'Control+KeyK': 'deleteToEndOfParagraph:',
|
||||||
|
'Control+KeyL': 'centerSelectionInVisibleArea:',
|
||||||
|
'Control+KeyN': 'moveDown:',
|
||||||
|
'Control+KeyO': ['insertNewlineIgnoringFieldEditor:', 'moveBackward:'],
|
||||||
|
'Control+KeyP': 'moveUp:',
|
||||||
|
'Control+KeyT': 'transpose:',
|
||||||
|
'Control+KeyV': 'pageDown:',
|
||||||
|
'Control+KeyY': 'yank:',
|
||||||
|
'Control+Backspace': 'deleteBackwardByDecomposingPreviousCharacter:',
|
||||||
|
'Control+ArrowUp': 'scrollPageUp:',
|
||||||
|
'Control+ArrowDown': 'scrollPageDown:',
|
||||||
|
'Control+ArrowLeft': 'moveToLeftEndOfLine:',
|
||||||
|
'Control+ArrowRight': 'moveToRightEndOfLine:',
|
||||||
|
'Shift+Control+Enter': 'insertLineBreak:',
|
||||||
|
'Shift+Control+Tab': 'selectPreviousKeyView:',
|
||||||
|
'Shift+Control+Quote': 'insertDoubleQuoteIgnoringSubstitution:',
|
||||||
|
'Shift+Control+KeyA': 'moveToBeginningOfParagraphAndModifySelection:',
|
||||||
|
'Shift+Control+KeyB': 'moveBackwardAndModifySelection:',
|
||||||
|
'Shift+Control+KeyE': 'moveToEndOfParagraphAndModifySelection:',
|
||||||
|
'Shift+Control+KeyF': 'moveForwardAndModifySelection:',
|
||||||
|
'Shift+Control+KeyN': 'moveDownAndModifySelection:',
|
||||||
|
'Shift+Control+KeyP': 'moveUpAndModifySelection:',
|
||||||
|
'Shift+Control+KeyV': 'pageDownAndModifySelection:',
|
||||||
|
'Shift+Control+Backspace': 'deleteBackwardByDecomposingPreviousCharacter:',
|
||||||
|
'Shift+Control+ArrowUp': 'scrollPageUp:',
|
||||||
|
'Shift+Control+ArrowDown': 'scrollPageDown:',
|
||||||
|
'Shift+Control+ArrowLeft': 'moveToLeftEndOfLineAndModifySelection:',
|
||||||
|
'Shift+Control+ArrowRight': 'moveToRightEndOfLineAndModifySelection:',
|
||||||
|
'Alt+Backspace': 'deleteWordBackward:',
|
||||||
|
'Alt+Tab': 'insertTabIgnoringFieldEditor:',
|
||||||
|
'Alt+Enter': 'insertNewlineIgnoringFieldEditor:',
|
||||||
|
'Alt+Escape': 'complete:',
|
||||||
|
"Alt+ArrowUp": ['moveBackward:', 'moveToBeginningOfParagraph:'],
|
||||||
|
"Alt+ArrowDown": ['moveForward:', 'moveToEndOfParagraph:'],
|
||||||
|
'Alt+ArrowLeft': 'moveWordLeft:',
|
||||||
|
'Alt+ArrowRight': 'moveWordRight:',
|
||||||
|
'Alt+Delete': 'deleteWordForward:',
|
||||||
|
'Alt+PageUp': 'pageUp:',
|
||||||
|
'Alt+PageDown': 'pageDown:',
|
||||||
|
'Shift+Alt+Backspace': 'deleteWordBackward:',
|
||||||
|
'Shift+Alt+Tab': 'insertTabIgnoringFieldEditor:',
|
||||||
|
'Shift+Alt+Enter': 'insertNewlineIgnoringFieldEditor:',
|
||||||
|
'Shift+Alt+Escape': 'complete:',
|
||||||
|
'Shift+Alt+ArrowUp': 'moveParagraphBackwardAndModifySelection:',
|
||||||
|
'Shift+Alt+ArrowDown': 'moveParagraphForwardAndModifySelection:',
|
||||||
|
'Shift+Alt+ArrowLeft': 'moveWordLeftAndModifySelection:',
|
||||||
|
'Shift+Alt+ArrowRight': 'moveWordRightAndModifySelection:',
|
||||||
|
'Shift+Alt+Delete': 'deleteWordForward:',
|
||||||
|
'Shift+Alt+PageUp': 'pageUp:',
|
||||||
|
'Shift+Alt+PageDown': 'pageDown:',
|
||||||
|
'Control+Alt+KeyB': 'moveWordBackward:',
|
||||||
|
'Control+Alt+KeyF': 'moveWordForward:',
|
||||||
|
'Control+Alt+Backspace': 'deleteWordBackward:',
|
||||||
|
'Shift+Control+Alt+KeyB': 'moveWordBackwardAndModifySelection:',
|
||||||
|
'Shift+Control+Alt+KeyF': 'moveWordForwardAndModifySelection:',
|
||||||
|
'Shift+Control+Alt+Backspace': 'deleteWordBackward:',
|
||||||
|
'Meta+NumpadSubtract': 'cancel:',
|
||||||
|
'Meta+Backspace': 'deleteToBeginningOfLine:',
|
||||||
|
'Meta+ArrowUp': 'moveToBeginningOfDocument:',
|
||||||
|
'Meta+ArrowDown': 'moveToEndOfDocument:',
|
||||||
|
'Meta+ArrowLeft': 'moveToLeftEndOfLine:',
|
||||||
|
'Meta+ArrowRight': 'moveToRightEndOfLine:',
|
||||||
|
'Shift+Meta+NumpadSubtract': 'cancel:',
|
||||||
|
'Shift+Meta+Backspace': 'deleteToBeginningOfLine:',
|
||||||
|
'Shift+Meta+ArrowUp': 'moveToBeginningOfDocumentAndModifySelection:',
|
||||||
|
'Shift+Meta+ArrowDown': 'moveToEndOfDocumentAndModifySelection:',
|
||||||
|
'Shift+Meta+ArrowLeft': 'moveToLeftEndOfLineAndModifySelection:',
|
||||||
|
'Shift+Meta+ArrowRight': 'moveToRightEndOfLineAndModifySelection:',
|
||||||
|
|
||||||
|
'Meta+KeyA': 'selectAll:',
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -38,11 +38,11 @@ export class RawKeyboardImpl implements input.RawKeyboard {
|
||||||
this._client = client;
|
this._client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
async keydown(modifiers: Set<input.Modifier>, code: string, keyCode: number, key: string, location: number, autoRepeat: boolean, text: string | undefined): Promise<void> {
|
async keydown(modifiers: Set<input.Modifier>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number, autoRepeat: boolean, text: string | undefined): Promise<void> {
|
||||||
await this._client.send('Input.dispatchKeyEvent', {
|
await this._client.send('Input.dispatchKeyEvent', {
|
||||||
type: text ? 'keyDown' : 'rawKeyDown',
|
type: text ? 'keyDown' : 'rawKeyDown',
|
||||||
modifiers: toModifiersMask(modifiers),
|
modifiers: toModifiersMask(modifiers),
|
||||||
windowsVirtualKeyCode: keyCode,
|
windowsVirtualKeyCode: keyCodeWithoutLocation,
|
||||||
code,
|
code,
|
||||||
key,
|
key,
|
||||||
text,
|
text,
|
||||||
|
|
@ -53,12 +53,12 @@ export class RawKeyboardImpl implements input.RawKeyboard {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async keyup(modifiers: Set<input.Modifier>, code: string, keyCode: number, key: string, location: number): Promise<void> {
|
async keyup(modifiers: Set<input.Modifier>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number): Promise<void> {
|
||||||
await this._client.send('Input.dispatchKeyEvent', {
|
await this._client.send('Input.dispatchKeyEvent', {
|
||||||
type: 'keyUp',
|
type: 'keyUp',
|
||||||
modifiers: toModifiersMask(modifiers),
|
modifiers: toModifiersMask(modifiers),
|
||||||
key,
|
key,
|
||||||
windowsVirtualKeyCode: keyCode,
|
windowsVirtualKeyCode: keyCodeWithoutLocation,
|
||||||
code,
|
code,
|
||||||
location
|
location
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -58,14 +58,14 @@ export class RawKeyboardImpl implements input.RawKeyboard {
|
||||||
this._client = client;
|
this._client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
async keydown(modifiers: Set<input.Modifier>, code: string, keyCode: number, key: string, location: number, autoRepeat: boolean, text: string | undefined): Promise<void> {
|
async keydown(modifiers: Set<input.Modifier>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number, autoRepeat: boolean, text: string | undefined): Promise<void> {
|
||||||
if (code === 'MetaLeft')
|
if (code === 'MetaLeft')
|
||||||
code = 'OSLeft';
|
code = 'OSLeft';
|
||||||
if (code === 'MetaRight')
|
if (code === 'MetaRight')
|
||||||
code = 'OSRight';
|
code = 'OSRight';
|
||||||
await this._client.send('Page.dispatchKeyEvent', {
|
await this._client.send('Page.dispatchKeyEvent', {
|
||||||
type: 'keydown',
|
type: 'keydown',
|
||||||
keyCode,
|
keyCode: keyCodeWithoutLocation,
|
||||||
code,
|
code,
|
||||||
key,
|
key,
|
||||||
repeat: autoRepeat,
|
repeat: autoRepeat,
|
||||||
|
|
@ -73,7 +73,7 @@ export class RawKeyboardImpl implements input.RawKeyboard {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async keyup(modifiers: Set<input.Modifier>, code: string, keyCode: number, key: string, location: number): Promise<void> {
|
async keyup(modifiers: Set<input.Modifier>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number): Promise<void> {
|
||||||
if (code === 'MetaLeft')
|
if (code === 'MetaLeft')
|
||||||
code = 'OSLeft';
|
code = 'OSLeft';
|
||||||
if (code === 'MetaRight')
|
if (code === 'MetaRight')
|
||||||
|
|
@ -81,7 +81,7 @@ export class RawKeyboardImpl implements input.RawKeyboard {
|
||||||
await this._client.send('Page.dispatchKeyEvent', {
|
await this._client.send('Page.dispatchKeyEvent', {
|
||||||
type: 'keyup',
|
type: 'keyup',
|
||||||
key,
|
key,
|
||||||
keyCode,
|
keyCode: keyCodeWithoutLocation,
|
||||||
code,
|
code,
|
||||||
location,
|
location,
|
||||||
repeat: false
|
repeat: false
|
||||||
|
|
|
||||||
14
src/input.ts
14
src/input.ts
|
|
@ -38,6 +38,7 @@ export const keypadLocation = keyboardLayout.keypadLocation;
|
||||||
|
|
||||||
type KeyDescription = {
|
type KeyDescription = {
|
||||||
keyCode: number,
|
keyCode: number,
|
||||||
|
keyCodeWithoutLocation: number,
|
||||||
key: string,
|
key: string,
|
||||||
text: string,
|
text: string,
|
||||||
code: string,
|
code: string,
|
||||||
|
|
@ -47,8 +48,8 @@ type KeyDescription = {
|
||||||
const kModifiers: Modifier[] = ['Alt', 'Control', 'Meta', 'Shift'];
|
const kModifiers: Modifier[] = ['Alt', 'Control', 'Meta', 'Shift'];
|
||||||
|
|
||||||
export interface RawKeyboard {
|
export interface RawKeyboard {
|
||||||
keydown(modifiers: Set<Modifier>, code: string, keyCode: number, key: string, location: number, autoRepeat: boolean, text: string | undefined): Promise<void>;
|
keydown(modifiers: Set<Modifier>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number, autoRepeat: boolean, text: string | undefined): Promise<void>;
|
||||||
keyup(modifiers: Set<Modifier>, code: string, keyCode: number, key: string, location: number): Promise<void>;
|
keyup(modifiers: Set<Modifier>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number): Promise<void>;
|
||||||
sendText(text: string): Promise<void>;
|
sendText(text: string): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,7 +69,7 @@ export class Keyboard {
|
||||||
if (kModifiers.includes(description.key as Modifier))
|
if (kModifiers.includes(description.key as Modifier))
|
||||||
this._pressedModifiers.add(description.key as Modifier);
|
this._pressedModifiers.add(description.key as Modifier);
|
||||||
const text = options.text === undefined ? description.text : options.text;
|
const text = options.text === undefined ? description.text : options.text;
|
||||||
await this._raw.keydown(this._pressedModifiers, description.code, description.keyCode, description.key, description.location, autoRepeat, text);
|
await this._raw.keydown(this._pressedModifiers, description.code, description.keyCode, description.keyCodeWithoutLocation, description.key, description.location, autoRepeat, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _keyDescriptionForString(keyString: string): KeyDescription {
|
private _keyDescriptionForString(keyString: string): KeyDescription {
|
||||||
|
|
@ -76,6 +77,7 @@ export class Keyboard {
|
||||||
const description: KeyDescription = {
|
const description: KeyDescription = {
|
||||||
key: '',
|
key: '',
|
||||||
keyCode: 0,
|
keyCode: 0,
|
||||||
|
keyCodeWithoutLocation: 0,
|
||||||
code: '',
|
code: '',
|
||||||
text: '',
|
text: '',
|
||||||
location: 0
|
location: 0
|
||||||
|
|
@ -112,6 +114,10 @@ export class Keyboard {
|
||||||
if (this._pressedModifiers.size > 1 || (!this._pressedModifiers.has('Shift') && this._pressedModifiers.size === 1))
|
if (this._pressedModifiers.size > 1 || (!this._pressedModifiers.has('Shift') && this._pressedModifiers.size === 1))
|
||||||
description.text = '';
|
description.text = '';
|
||||||
|
|
||||||
|
if (definition.keyCodeWithoutLocation)
|
||||||
|
description.keyCodeWithoutLocation = definition.keyCodeWithoutLocation;
|
||||||
|
else
|
||||||
|
description.keyCodeWithoutLocation = description.keyCode;
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,7 +126,7 @@ export class Keyboard {
|
||||||
if (kModifiers.includes(description.key as Modifier))
|
if (kModifiers.includes(description.key as Modifier))
|
||||||
this._pressedModifiers.delete(description.key as Modifier);
|
this._pressedModifiers.delete(description.key as Modifier);
|
||||||
this._pressedKeys.delete(description.code);
|
this._pressedKeys.delete(description.code);
|
||||||
await this._raw.keyup(this._pressedModifiers, description.code, description.keyCode, description.key, description.location);
|
await this._raw.keyup(this._pressedModifiers, description.code, description.keyCode, description.keyCodeWithoutLocation, description.key, description.location);
|
||||||
}
|
}
|
||||||
|
|
||||||
async sendCharacters(text: string) {
|
async sendCharacters(text: string) {
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as input from '../input';
|
import * as input from '../input';
|
||||||
|
import { helper } from '../helper';
|
||||||
|
import { macEditingCommands } from '../USKeyboardLayout';
|
||||||
import { TargetSession } from './Connection';
|
import { TargetSession } from './Connection';
|
||||||
|
|
||||||
function toModifiersMask(modifiers: Set<input.Modifier>): number {
|
function toModifiersMask(modifiers: Set<input.Modifier>): number {
|
||||||
|
|
@ -39,7 +41,17 @@ export class RawKeyboardImpl implements input.RawKeyboard {
|
||||||
this._session = session;
|
this._session = session;
|
||||||
}
|
}
|
||||||
|
|
||||||
async keydown(modifiers: Set<input.Modifier>, code: string, keyCode: number, key: string, location: number, autoRepeat: boolean, text: string | undefined): Promise<void> {
|
async keydown(modifiers: Set<input.Modifier>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number, autoRepeat: boolean, text: string | undefined): Promise<void> {
|
||||||
|
const parts = [];
|
||||||
|
for (const modifier of (['Shift', 'Control', 'Alt', 'Meta']) as input.Modifier[]) {
|
||||||
|
if (modifiers.has(modifier))
|
||||||
|
parts.push(modifier);
|
||||||
|
}
|
||||||
|
parts.push(code);
|
||||||
|
const shortcut = parts.join('+');
|
||||||
|
let commands = macEditingCommands[shortcut];
|
||||||
|
if (helper.isString(commands))
|
||||||
|
commands = [commands];
|
||||||
await this._session.send('Input.dispatchKeyEvent', {
|
await this._session.send('Input.dispatchKeyEvent', {
|
||||||
type: 'keyDown',
|
type: 'keyDown',
|
||||||
modifiers: toModifiersMask(modifiers),
|
modifiers: toModifiersMask(modifiers),
|
||||||
|
|
@ -49,11 +61,12 @@ export class RawKeyboardImpl implements input.RawKeyboard {
|
||||||
text,
|
text,
|
||||||
unmodifiedText: text,
|
unmodifiedText: text,
|
||||||
autoRepeat,
|
autoRepeat,
|
||||||
|
macCommands: commands,
|
||||||
isKeypad: location === input.keypadLocation
|
isKeypad: location === input.keypadLocation
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async keyup(modifiers: Set<input.Modifier>, code: string, keyCode: number, key: string, location: number): Promise<void> {
|
async keyup(modifiers: Set<input.Modifier>, code: string, keyCode: number, keyCodeWithoutLocation: number, key: string, location: number): Promise<void> {
|
||||||
await this._session.send('Input.dispatchKeyEvent', {
|
await this._session.send('Input.dispatchKeyEvent', {
|
||||||
type: 'keyUp',
|
type: 'keyUp',
|
||||||
modifiers: toModifiersMask(modifiers),
|
modifiers: toModifiersMask(modifiers),
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
|
|
||||||
module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT, MAC}) {
|
||||||
const {describe, xdescribe, fdescribe} = testRunner;
|
const {describe, xdescribe, fdescribe} = testRunner;
|
||||||
const {it, fit, xit} = testRunner;
|
const {it, fit, xit} = testRunner;
|
||||||
const {beforeAll, beforeEach, afterAll, afterEach} = testRunner;
|
const {beforeAll, beforeEach, afterAll, afterEach} = testRunner;
|
||||||
|
|
@ -39,7 +39,7 @@ module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
||||||
window.keyPromise = new Promise(resolve => document.addEventListener('keydown', event => resolve(event.key)));
|
window.keyPromise = new Promise(resolve => document.addEventListener('keydown', event => resolve(event.key)));
|
||||||
});
|
});
|
||||||
await page.keyboard.press('Meta');
|
await page.keyboard.press('Meta');
|
||||||
expect(await page.evaluate('keyPromise')).toBe(FFOX && os.platform() !== 'darwin' ? 'OS' : 'Meta');
|
expect(await page.evaluate('keyPromise')).toBe(FFOX && !MAC ? 'OS' : 'Meta');
|
||||||
});
|
});
|
||||||
it('should move with the arrow keys', async({page, server}) => {
|
it('should move with the arrow keys', async({page, server}) => {
|
||||||
await page.goto(server.PREFIX + '/input/textarea.html');
|
await page.goto(server.PREFIX + '/input/textarea.html');
|
||||||
|
|
@ -226,6 +226,34 @@ module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
||||||
await textarea.type('👹 Tokyo street Japan 🇯🇵');
|
await textarea.type('👹 Tokyo street Japan 🇯🇵');
|
||||||
expect(await frame.$eval('textarea', textarea => textarea.value)).toBe('👹 Tokyo street Japan 🇯🇵');
|
expect(await frame.$eval('textarea', textarea => textarea.value)).toBe('👹 Tokyo street Japan 🇯🇵');
|
||||||
});
|
});
|
||||||
|
it.skip(CHROME && MAC)('should handle selectAll', async({page, server}) => {
|
||||||
|
await page.goto(server.PREFIX + '/input/textarea.html');
|
||||||
|
const textarea = await page.$('textarea');
|
||||||
|
await textarea.type('some text');
|
||||||
|
const modifier = MAC ? 'Meta' : 'Control';
|
||||||
|
await page.keyboard.down(modifier);
|
||||||
|
await page.keyboard.press('a');
|
||||||
|
await page.keyboard.up(modifier);
|
||||||
|
await page.keyboard.press('Backspace');
|
||||||
|
expect(await page.$eval('textarea', textarea => textarea.value)).toBe('');
|
||||||
|
});
|
||||||
|
it.skip(CHROME && MAC)('should be able to prevent selectAll', async({page, server}) => {
|
||||||
|
await page.goto(server.PREFIX + '/input/textarea.html');
|
||||||
|
const textarea = await page.$('textarea');
|
||||||
|
await textarea.type('some text');
|
||||||
|
await page.$eval('textarea', textarea => {
|
||||||
|
textarea.addEventListener('keydown', event => {
|
||||||
|
if (event.key === 'a' && (event.metaKey || event.ctrlKey))
|
||||||
|
event.preventDefault();
|
||||||
|
}, false);
|
||||||
|
});
|
||||||
|
const modifier = MAC ? 'Meta' : 'Control';
|
||||||
|
await page.keyboard.down(modifier);
|
||||||
|
await page.keyboard.press('a');
|
||||||
|
await page.keyboard.up(modifier);
|
||||||
|
await page.keyboard.press('Backspace');
|
||||||
|
expect(await page.$eval('textarea', textarea => textarea.value)).toBe('some tex');
|
||||||
|
});
|
||||||
it('should press the meta key', async({page}) => {
|
it('should press the meta key', async({page}) => {
|
||||||
await page.evaluate(() => {
|
await page.evaluate(() => {
|
||||||
window.result = null;
|
window.result = null;
|
||||||
|
|
@ -235,7 +263,7 @@ module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
||||||
});
|
});
|
||||||
await page.keyboard.press('Meta');
|
await page.keyboard.press('Meta');
|
||||||
const [key, code, metaKey] = await page.evaluate('result');
|
const [key, code, metaKey] = await page.evaluate('result');
|
||||||
if (FFOX && os.platform() !== 'darwin')
|
if (FFOX && !MAC)
|
||||||
expect(key).toBe('OS');
|
expect(key).toBe('OS');
|
||||||
else
|
else
|
||||||
expect(key).toBe('Meta');
|
expect(key).toBe('Meta');
|
||||||
|
|
@ -245,7 +273,7 @@ module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
||||||
else
|
else
|
||||||
expect(code).toBe('MetaLeft');
|
expect(code).toBe('MetaLeft');
|
||||||
|
|
||||||
if (FFOX && os.platform() !== 'darwin')
|
if (FFOX && !MAC)
|
||||||
expect(metaKey).toBe(false);
|
expect(metaKey).toBe(false);
|
||||||
else
|
else
|
||||||
expect(metaKey).toBe(true);
|
expect(metaKey).toBe(true);
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ const statAsync = helper.promisify(fs.stat);
|
||||||
const TMP_FOLDER = path.join(os.tmpdir(), 'pptr_tmp_folder-');
|
const TMP_FOLDER = path.join(os.tmpdir(), 'pptr_tmp_folder-');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
|
|
||||||
module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, playwright, FFOX, CHROME, WEBKIT}) {
|
module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, playwright, FFOX, CHROME, WEBKIT, WIN}) {
|
||||||
const {describe, xdescribe, fdescribe} = testRunner;
|
const {describe, xdescribe, fdescribe} = testRunner;
|
||||||
const {it, fit, xit} = testRunner;
|
const {it, fit, xit} = testRunner;
|
||||||
const {beforeAll, beforeEach, afterAll, afterEach} = testRunner;
|
const {beforeAll, beforeEach, afterAll, afterEach} = testRunner;
|
||||||
|
|
@ -51,7 +51,7 @@ module.exports.addTests = function({testRunner, expect, defaultBrowserOptions, p
|
||||||
revisionInfo = await browserFetcher.download('123456');
|
revisionInfo = await browserFetcher.download('123456');
|
||||||
expect(revisionInfo.local).toBe(true);
|
expect(revisionInfo.local).toBe(true);
|
||||||
expect(await readFileAsync(revisionInfo.executablePath, 'utf8')).toBe('LINUX BINARY\n');
|
expect(await readFileAsync(revisionInfo.executablePath, 'utf8')).toBe('LINUX BINARY\n');
|
||||||
const expectedPermissions = os.platform() === 'win32' ? 0666 : 0755;
|
const expectedPermissions = WIN ? 0666 : 0755;
|
||||||
expect((await statAsync(revisionInfo.executablePath)).mode & 0777).toBe(expectedPermissions);
|
expect((await statAsync(revisionInfo.executablePath)).mode & 0777).toBe(expectedPermissions);
|
||||||
expect(await browserFetcher.localRevisions()).toEqual(['123456']);
|
expect(await browserFetcher.localRevisions()).toEqual(['123456']);
|
||||||
await browserFetcher.remove('123456');
|
await browserFetcher.remove('123456');
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ module.exports.addTests = function({testRunner, expect, FFOX, CHROME, WEBKIT}) {
|
||||||
await page.evaluate(() => document.querySelector('#button-3').addEventListener('mousedown', e => window.lastEvent = e, true));
|
await page.evaluate(() => document.querySelector('#button-3').addEventListener('mousedown', e => window.lastEvent = e, true));
|
||||||
const modifiers = {'Shift': 'shiftKey', 'Control': 'ctrlKey', 'Alt': 'altKey', 'Meta': 'metaKey'};
|
const modifiers = {'Shift': 'shiftKey', 'Control': 'ctrlKey', 'Alt': 'altKey', 'Meta': 'metaKey'};
|
||||||
// In Firefox, the Meta modifier only exists on Mac
|
// In Firefox, the Meta modifier only exists on Mac
|
||||||
if (FFOX && os.platform() !== 'darwin')
|
if (FFOX && !MAC)
|
||||||
delete modifiers['Meta'];
|
delete modifiers['Meta'];
|
||||||
for (const modifier in modifiers) {
|
for (const modifier in modifiers) {
|
||||||
await page.keyboard.down(modifier);
|
await page.keyboard.down(modifier);
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const os = require('os');
|
||||||
const rm = require('rimraf').sync;
|
const rm = require('rimraf').sync;
|
||||||
const GoldenUtils = require('./golden-utils');
|
const GoldenUtils = require('./golden-utils');
|
||||||
const {Matchers} = require('../utils/testrunner/');
|
const {Matchers} = require('../utils/testrunner/');
|
||||||
|
|
@ -30,6 +31,9 @@ module.exports.addTests = ({testRunner, product, playwrightPath}) => {
|
||||||
const CHROME = product === 'Chromium';
|
const CHROME = product === 'Chromium';
|
||||||
const FFOX = product === 'Firefox';
|
const FFOX = product === 'Firefox';
|
||||||
const WEBKIT = product === 'WebKit';
|
const WEBKIT = product === 'WebKit';
|
||||||
|
const MAC = os.platform() === 'darwin';
|
||||||
|
const LINUX = os.platform() === 'linux';
|
||||||
|
const WIN = os.platform() === 'win32';
|
||||||
|
|
||||||
const playwright = require(playwrightPath);
|
const playwright = require(playwrightPath);
|
||||||
|
|
||||||
|
|
@ -72,6 +76,9 @@ module.exports.addTests = ({testRunner, product, playwrightPath}) => {
|
||||||
FFOX,
|
FFOX,
|
||||||
WEBKIT,
|
WEBKIT,
|
||||||
CHROME,
|
CHROME,
|
||||||
|
MAC,
|
||||||
|
LINUX,
|
||||||
|
WIN,
|
||||||
playwright,
|
playwright,
|
||||||
expect,
|
expect,
|
||||||
defaultBrowserOptions,
|
defaultBrowserOptions,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue