Skip to content

Commit

Permalink
(#366) Throw on invalid input to keyboard and mouse methods
Browse files Browse the repository at this point in the history
  • Loading branch information
s1hofmann committed Feb 1, 2022
1 parent 697ef1d commit cf1dc03
Show file tree
Hide file tree
Showing 4 changed files with 535 additions and 410 deletions.
55 changes: 26 additions & 29 deletions lib/provider/native/libnut-keyboard.class.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ beforeEach(() => {

describe("libnut keyboard action", () => {
describe("click", () => {
it("should forward the keyTap call to libnut for a known key", () => {
it("should forward the keyTap call to libnut for a known key", async () => {
// GIVEN
const SUT = new KeyboardAction();

// WHEN
SUT.click(Key.A);
await SUT.click(Key.A);

// THEN
expect(libnut.keyTap).toBeCalledTimes(1);
Expand All @@ -31,29 +31,28 @@ describe("libnut keyboard action", () => {
// WHEN

// THEN
expect(SUT.click(Key.A)).rejects.toThrowError("Test error");
await expect(SUT.click(Key.A)).rejects.toThrowError("Test error");
});

it("should not forward the keyTap call to libnut for an unknown key", () => {
it("should reject on unknown/unmapped keys", async () => {
// GIVEN
const SUT = new KeyboardAction();

// WHEN
SUT.click(Key.Add);

// THEN
expect(libnut.keyTap).not.toBeCalled();
await expect(() => SUT.click(Key.Pause)).rejects.toBe("Received invalid keys: [89]")
});
});

describe("type", () => {
it("should forward the type call to libnut", () => {
it("should forward the type call to libnut", async () => {
// GIVEN
const SUT = new KeyboardAction();
const payload = "testInput";

// WHEN
SUT.type(payload);
await SUT.type(payload);

// THEN
expect(libnut.typeString).toBeCalledTimes(1);
Expand All @@ -70,45 +69,44 @@ describe("libnut keyboard action", () => {
// WHEN

// THEN
expect(SUT.type("foo")).rejects.toThrowError("Test error");
await expect(SUT.type("foo")).rejects.toThrowError("Test error");
});
});

describe("pressKey", () => {
it("should forward the pressKey call to libnut for a known key", () => {
it("should forward the pressKey call to libnut for a known key", async () => {
// GIVEN
const SUT = new KeyboardAction();

// WHEN
SUT.pressKey(Key.A);
await SUT.pressKey(Key.A);

// THEN
expect(libnut.keyToggle).toBeCalledTimes(1);
expect(libnut.keyToggle).toBeCalledWith(KeyboardAction.keyLookup(Key.A), "down", []);
});

it("should treat a list of keys as modifiers + the actual key to press", () => {
it("should treat a list of keys as modifiers + the actual key to press", async () => {
// GIVEN
const SUT = new KeyboardAction();

// WHEN
SUT.pressKey(Key.LeftControl, Key.A);
await SUT.pressKey(Key.LeftControl, Key.A);

// THEN
expect(libnut.keyToggle).toBeCalledTimes(1);
expect(libnut.keyToggle)
.toBeCalledWith(KeyboardAction.keyLookup(Key.A), "down", [KeyboardAction.keyLookup(Key.LeftControl)]);
});

it("should not forward the pressKey call to libnut for an unknown key", () => {
it("should not forward the pressKey call to libnut for an unknown key", async () => {
// GIVEN
const SUT = new KeyboardAction();

// WHEN
SUT.pressKey(Key.Add);

// THEN
expect(libnut.keyToggle).not.toBeCalled();
await expect(() => SUT.pressKey(Key.Pause)).rejects.toBe("Received invalid keys. Key: 89, modifiers: []");
});

it("should reject on libnut errors", async () => {
Expand All @@ -121,45 +119,44 @@ describe("libnut keyboard action", () => {
// WHEN

// THEN
expect(SUT.pressKey(Key.A)).rejects.toThrowError("Test error");
await expect(SUT.pressKey(Key.A)).rejects.toThrowError("Test error");
});
});

describe("releaseKey", () => {
it("should forward the releaseKey call to libnut for a known key", () => {
it("should forward the releaseKey call to libnut for a known key", async () => {
// GIVEN
const SUT = new KeyboardAction();

// WHEN
SUT.releaseKey(Key.A);
await SUT.releaseKey(Key.A);

// THEN
expect(libnut.keyToggle).toBeCalledTimes(1);
expect(libnut.keyToggle).toBeCalledWith(KeyboardAction.keyLookup(Key.A), "up", []);
});

it("should treat a list of keys as modifiers + the actual key to release", () => {
it("should treat a list of keys as modifiers + the actual key to release", async () => {
// GIVEN
const SUT = new KeyboardAction();

// WHEN
SUT.releaseKey(Key.LeftControl, Key.A);
await SUT.releaseKey(Key.LeftControl, Key.A);

// THEN
expect(libnut.keyToggle).toBeCalledTimes(1);
expect(libnut.keyToggle)
.toBeCalledWith(KeyboardAction.keyLookup(Key.A), "up", [KeyboardAction.keyLookup(Key.LeftControl)]);
});

it("should not forward the releaseKey call to libnut for an unknown key", () => {
it("should not forward the releaseKey call to libnut for an unknown key", async () => {
// GIVEN
const SUT = new KeyboardAction();

// WHEN
SUT.releaseKey(Key.Add);

// THEN
expect(libnut.keyToggle).not.toBeCalled();
await expect(() => SUT.releaseKey(Key.Pause)).rejects.toBe("Received invalid keys. Key: 89, modifiers: []");
});

it("should reject on libnut errors", async () => {
Expand All @@ -172,29 +169,29 @@ describe("libnut keyboard action", () => {
// WHEN

// THEN
expect(SUT.releaseKey(Key.A)).rejects.toThrowError("Test error");
await expect(SUT.releaseKey(Key.A)).rejects.toThrowError("Test error");
});
});

describe("bugfix #260", () => {
it("should forward the pressKey call to libnut for 'delete'", () => {
it("should forward the pressKey call to libnut for 'delete'", async () => {
// GIVEN
const SUT = new KeyboardAction();

// WHEN
SUT.pressKey(Key.Delete);
await SUT.pressKey(Key.Delete);

// THEN
expect(libnut.keyToggle).toBeCalledTimes(1);
expect(libnut.keyToggle).toBeCalledWith("delete", "down", []);
});

it("should forward the releaseKey call to libnut for 'delete'", () => {
it("should forward the releaseKey call to libnut for 'delete'", async () => {
// GIVEN
const SUT = new KeyboardAction();

// WHEN
SUT.releaseKey(Key.Delete);
await SUT.releaseKey(Key.Delete);

// THEN
expect(libnut.keyToggle).toBeCalledTimes(1);
Expand Down
50 changes: 34 additions & 16 deletions lib/provider/native/libnut-keyboard.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export default class KeyboardAction implements KeyboardProviderInterface {
[Key.NumPad7, "numpad_7"],
[Key.NumPad8, "numpad_8"],
[Key.NumPad9, "numpad_9"],
[Key.Decimal, "numpad_decimal"],

[Key.Space, "space"],
[Key.Escape, "escape"],
Expand Down Expand Up @@ -119,16 +120,15 @@ export default class KeyboardAction implements KeyboardProviderInterface {
[Key.PageUp, "pageup"],
[Key.PageDown, "pagedown"],

[Key.Add, null],
[Key.Subtract, null],
[Key.Multiply, null],
[Key.Divide, null],
[Key.Decimal, null],
[Key.Add, "add"],
[Key.Subtract, "subtract"],
[Key.Multiply, "multiply"],
[Key.Divide, "divide"],
[Key.Enter, "enter"],

[Key.CapsLock, null],
[Key.ScrollLock, null],
[Key.NumLock, null],
[Key.CapsLock, "caps_lock"],
[Key.ScrollLock, "scroll_lock"],
[Key.NumLock, "num_lock"],

[Key.AudioMute, "audio_mute"],
[Key.AudioVolDown, "audio_vol_down"],
Expand Down Expand Up @@ -175,8 +175,12 @@ export default class KeyboardAction implements KeyboardProviderInterface {
public type(input: string): Promise<void> {
return new Promise<void>((resolve, reject) => {
try {
libnut.typeString(input);
resolve();
if (input) {
libnut.typeString(input);
resolve();
} else {
reject(`Received invalid input: ${input ? input : 'undefined'}`)
}
} catch (e) {
reject(e);
}
Expand All @@ -190,10 +194,12 @@ export default class KeyboardAction implements KeyboardProviderInterface {
const [key, ...modifiers] = keys;
const nativeKey = KeyboardAction.keyLookup(key);
const modifierKeys = KeyboardAction.mapModifierKeys(...modifiers);
if (nativeKey) {
if (nativeKey && !modifierKeys.some(modifier => modifier == null)) {
libnut.keyTap(nativeKey, modifierKeys);
resolve();
} else {
reject(`Received invalid keys: ${JSON.stringify(keys)}`)
}
resolve();
} catch (e) {
reject(e);
}
Expand All @@ -205,8 +211,14 @@ export default class KeyboardAction implements KeyboardProviderInterface {
try {
keys.reverse();
const [key, ...modifiers] = keys;
await KeyboardAction.key(key, "down", ...modifiers);
resolve();
const nativeKey = KeyboardAction.keyLookup(key);
const modifierKeys = KeyboardAction.mapModifierKeys(...modifiers);
if (nativeKey && !modifierKeys.some(modifier => modifier == null)) {
await KeyboardAction.key(key, "down", ...modifiers);
resolve();
} else {
reject(`Received invalid keys. Key: ${JSON.stringify(key)}, modifiers: ${JSON.stringify(modifiers)}`)
}
} catch (e) {
reject(e);
}
Expand All @@ -218,8 +230,14 @@ export default class KeyboardAction implements KeyboardProviderInterface {
try {
keys.reverse();
const [key, ...modifiers] = keys;
await KeyboardAction.key(key, "up", ...modifiers);
resolve();
const nativeKey = KeyboardAction.keyLookup(key);
const modifierKeys = KeyboardAction.mapModifierKeys(...modifiers);
if (nativeKey && !modifierKeys.some(modifier => modifier == null)) {
await KeyboardAction.key(key, "up", ...modifiers);
resolve();
} else {
reject(`Received invalid keys. Key: ${JSON.stringify(key)}, modifiers: ${JSON.stringify(modifiers)}`)
}
} catch (e) {
reject(e);
}
Expand Down
Loading

0 comments on commit cf1dc03

Please sign in to comment.