Skip to content

Commit e8f2313

Browse files
authored
Merge pull request #54 from nut-tree/feature/53/api_overhaul
Feature/53/api overhaul
2 parents 14068d0 + fd65034 commit e8f2313

14 files changed

+121
-165
lines changed

Diff for: README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ The following snippet shows a valid NUT example (on macOS)
2828
```js
2929
"use strict";
3030

31-
const { keyboard, Key, mouse, movement } = require("@nut-tree/nut-js");
31+
const { keyboard, Key, mouse, left, right, up, down } = require("@nut-tree/nut-js");
3232

3333
const square = async () => {
34-
await mouse.move(movement.right(500));
35-
await mouse.move(movement.down(500));
36-
await mouse.move(movement.left(500));
37-
await mouse.move(movement.up(500));
34+
await mouse.move(right(500));
35+
await mouse.move(down(500));
36+
await mouse.move(left(500));
37+
await mouse.move(up(500));
3838
};
3939

4040
const openSpotlight = async () => {

Diff for: index.e2e.spec.ts

+6-11
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { assert, Key, keyboard, Location, mouse, movement, screen } from "./index";
1+
import { assert, centerOf, Key, keyboard, mouse, screen, straightTo } from "./index";
22

33
const openXfceMenu = async () => {
4-
const menu = await screen.find("menu.png");
5-
await mouse.move(await movement.straightTo(Location.centerOf(menu)));
4+
await mouse.move(straightTo(centerOf(screen.find("menu.png"))));
65
await mouse.leftClick();
76
await mouse.leftClick();
87
};
@@ -14,22 +13,18 @@ const run = async (cmd: string) => {
1413
};
1514

1615
const calculate = async () => {
17-
const plus = await screen.find("plus.png");
18-
await mouse.move(await movement.straightTo(Location.centerOf(plus)));
16+
await mouse.move(straightTo(centerOf(screen.find("plus.png"))));
1917
await mouse.leftClick();
20-
const one = await screen.find("one.png");
21-
await mouse.move(await movement.straightTo(Location.centerOf(one)));
18+
await mouse.move(straightTo(centerOf(screen.find("one.png"))));
2219
await mouse.leftClick();
23-
const zero = await screen.find("zero.png");
24-
await mouse.move(await movement.straightTo(Location.centerOf(zero)));
20+
await mouse.move(straightTo(centerOf(screen.find("zero.png"))));
2521
await mouse.leftClick();
2622
await mouse.leftClick();
2723
await keyboard.type(Key.Enter);
2824
};
2925

3026
const close = async () => {
31-
const x = await screen.find("close.png");
32-
await mouse.move(await movement.straightTo(Location.centerOf(x)));
27+
await mouse.move(straightTo(centerOf(screen.find("close.png"))));
3328
await mouse.leftClick();
3429
};
3530

Diff for: index.ts

+18-6
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,40 @@ import { Assert } from "./lib/assert.class";
44
import { Clipboard } from "./lib/clipboard.class";
55
import { Keyboard } from "./lib/keyboard.class";
66
import { Mouse } from "./lib/mouse.class";
7-
import { Movement } from "./lib/movement.class";
7+
import { createMovementApi } from "./lib/movement.function";
88
import { Screen } from "./lib/screen.class";
99
import { LineHelper } from "./lib/util/linehelper.class";
1010

1111
export { jestMatchers } from "./lib/expect/jest.matcher.function";
1212
export { Image } from "./lib/image.class";
1313
export { Key } from "./lib/key.enum";
14-
export { Location } from "./lib/location.class";
14+
export { centerOf, randomPointIn } from "./lib/location.function";
1515
export { LocationParameters } from "./lib/locationparameters.class";
16-
export { Movement } from "./lib/movement.class";
17-
export { MovementType } from "./lib/movementtype.class";
16+
export { linear } from "./lib/movementtype.function";
1817
export { Point } from "./lib/point.class";
1918
export { Region } from "./lib/region.class";
2019

2120
const screenActions = new VisionAdapter();
2221
const nativeActions = new NativeAdapter();
22+
const lineHelper = new LineHelper();
2323

2424
const clipboard = new Clipboard(nativeActions);
2525
const keyboard = new Keyboard(nativeActions);
2626
const mouse = new Mouse(nativeActions);
27-
const movement = new Movement(nativeActions, new LineHelper());
2827
const screen = new Screen(screenActions);
2928
const assert = new Assert(screen);
3029

31-
export { clipboard, keyboard, mouse, movement, screen, assert };
30+
const {straightTo, up, down, left, right} = createMovementApi(nativeActions, lineHelper);
31+
32+
export {
33+
clipboard,
34+
keyboard,
35+
mouse,
36+
screen,
37+
assert,
38+
straightTo,
39+
up,
40+
down,
41+
left,
42+
right,
43+
};

Diff for: lib/keyboard.class.spec.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ beforeEach(() => {
99
});
1010

1111
describe("Keyboard", () => {
12-
it("should have a default delay of 500 ms", () => {
12+
it("should have a default delay of 300 ms", () => {
1313
// GIVEN
1414
const adapterMock = new NativeAdapter();
1515
const SUT = new Keyboard(adapterMock);
1616

1717
// WHEN
1818

1919
// THEN
20-
expect(SUT.config.autoDelayMs).toEqual(500);
20+
expect(SUT.config.autoDelayMs).toEqual(300);
2121
});
2222

2323
it("should pass input strings down to the type call.", async () => {
@@ -38,6 +38,7 @@ describe("Keyboard", () => {
3838

3939
it("should pass multiple input strings down to the type call.", async () => {
4040
// GIVEN
41+
jest.setTimeout(10000);
4142
const adapterMock = new NativeAdapter();
4243
const SUT = new Keyboard(adapterMock);
4344
const payload = ["Test input!", "Array test2"];

Diff for: lib/keyboard.class.ts

+3-20
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { NativeAdapter } from "./adapter/native.adapter.class";
22
import { Key } from "./key.enum";
3+
import { sleep } from "./sleep.function";
34

45
type StringOrKey = string[] | Key[];
56

@@ -10,24 +11,20 @@ const inputIsString = (input: string[] | Key[]): input is string[] => {
1011
export class Keyboard {
1112

1213
public config = {
13-
autoDelayMs: 500,
14+
autoDelayMs: 300,
1415
};
1516

16-
private lastAction: number;
17-
1817
constructor(private nativeAdapter: NativeAdapter) {
1918
this.nativeAdapter.setKeyboardDelay(this.config.autoDelayMs);
20-
this.lastAction = Date.now();
2119
}
2220

2321
public type(...input: StringOrKey): Promise<Keyboard> {
2422
return new Promise<Keyboard>(async (resolve, reject) => {
2523
try {
2624
if (inputIsString(input)) {
2725
for (const char of input.join(" ").split("")) {
28-
await this.nextTick();
26+
await sleep(this.config.autoDelayMs);
2927
await this.nativeAdapter.type(char);
30-
this.updateTick();
3128
}
3229
} else {
3330
await this.nativeAdapter.click(...input as Key[]);
@@ -60,18 +57,4 @@ export class Keyboard {
6057
}
6158
});
6259
}
63-
64-
private updateTick() {
65-
this.lastAction = Date.now();
66-
}
67-
68-
private async nextTick(): Promise<void> {
69-
return new Promise<void>(resolve => {
70-
let current = Date.now();
71-
while (current - this.lastAction < this.config.autoDelayMs) {
72-
current = Date.now();
73-
}
74-
resolve();
75-
});
76-
}
7760
}

Diff for: lib/location.class.ts

-19
This file was deleted.

Diff for: lib/location.class.spec.ts renamed to lib/location.function.spec.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Location } from "./location.class";
1+
import { centerOf, randomPointIn } from "./location.function";
22
import { Point } from "./point.class";
33
import { Region } from "./region.class";
44

@@ -7,12 +7,12 @@ describe("Location", () => {
77
const expected = new Point(2, 2);
88
const testRegion = new Region(0, 0, 4, 4);
99

10-
expect(Location.centerOf(testRegion)).toEqual(expected);
10+
expect(centerOf(testRegion)).resolves.toEqual(expected);
1111
});
1212

13-
it("should return a random point inside of an area.", () => {
13+
it("should return a random point inside of an area.", async () => {
1414
const testRegion = new Region(100, 20, 50, 35);
15-
const result = Location.randomPointIn(testRegion);
15+
const result = await randomPointIn(testRegion);
1616
expect(result.x).toBeGreaterThanOrEqual(testRegion.left);
1717
expect(result.x).toBeLessThanOrEqual(testRegion.left + testRegion.width);
1818
expect(result.y).toBeGreaterThanOrEqual(testRegion.top);

Diff for: lib/location.function.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Point } from "./point.class";
2+
import { Region } from "./region.class";
3+
4+
export const centerOf = async (target: Region | Promise<Region>): Promise<Point> => {
5+
const targetRegion = await target;
6+
const x = Math.floor(targetRegion.left + targetRegion.width / 2);
7+
const y = Math.floor(targetRegion.top + targetRegion.height / 2);
8+
9+
return new Point(x, y);
10+
};
11+
12+
export const randomPointIn = async (target: Region | Promise<Region>): Promise<Point> => {
13+
const targetRegion = await target;
14+
const x = Math.floor(targetRegion.left + Math.random() * targetRegion.width);
15+
const y = Math.floor(targetRegion.top + Math.random() * targetRegion.height);
16+
17+
return new Point(x, y);
18+
};

Diff for: lib/mouse.class.ts

+16-39
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
import { NativeAdapter } from "./adapter/native.adapter.class";
22
import { Button } from "./button.enum";
3-
import { MovementType } from "./movementtype.class";
3+
import { linear } from "./movementtype.function";
44
import { Point } from "./point.class";
5+
import { sleep } from "./sleep.function";
56

67
export class Mouse {
78
public config = {
89
autoDelayMs: 100,
910
mouseSpeed: 1000,
1011
};
1112

12-
private lastAction: number;
13-
1413
constructor(private native: NativeAdapter) {
1514
this.native.setMouseDelay(0);
16-
this.lastAction = Date.now();
1715
}
1816

1917
public async setPosition(target: Point): Promise<Mouse> {
@@ -31,16 +29,16 @@ export class Mouse {
3129
return this.native.currentMousePosition();
3230
}
3331

34-
public async move(path: Point[], movementType = MovementType.linear): Promise<Mouse> {
32+
public async move(path: Point[] | Promise<Point[]>, movementType = linear): Promise<Mouse> {
3533
return new Promise<Mouse>(async (resolve, reject) => {
3634
try {
37-
const timeSteps = movementType(path.length, this.config.mouseSpeed);
38-
for (let idx = 0; idx < path.length; ++idx) {
39-
const node = path[idx];
35+
const pathSteps = await path;
36+
const timeSteps = movementType(pathSteps.length, this.config.mouseSpeed);
37+
for (let idx = 0; idx < pathSteps.length; ++idx) {
38+
const node = pathSteps[idx];
4039
const minTime = timeSteps[idx];
41-
await this.waitForNextTick(minTime);
40+
await sleep(minTime);
4241
await this.native.setMousePosition(node);
43-
await this.updateTick();
4442
}
4543
resolve(this);
4644
} catch (e) {
@@ -51,19 +49,17 @@ export class Mouse {
5149

5250
public async leftClick(): Promise<Mouse> {
5351
return new Promise<Mouse>(async resolve => {
54-
await this.waitForNextTick(this.config.autoDelayMs);
52+
await sleep(this.config.autoDelayMs);
5553
await this.native.leftClick();
56-
await this.updateTick();
5754
resolve(this);
5855
});
5956
}
6057

6158
public async rightClick(): Promise<Mouse> {
6259
return new Promise<Mouse>(async (resolve, reject) => {
6360
try {
64-
await this.waitForNextTick(this.config.autoDelayMs);
61+
await sleep(this.config.autoDelayMs);
6562
await this.native.rightClick();
66-
await this.updateTick();
6763
resolve(this);
6864
} catch (e) {
6965
reject(e);
@@ -74,9 +70,8 @@ export class Mouse {
7470
public async scrollDown(amount: number): Promise<Mouse> {
7571
return new Promise<Mouse>(async (resolve, reject) => {
7672
try {
77-
await this.waitForNextTick(this.config.autoDelayMs);
73+
await sleep(this.config.autoDelayMs);
7874
await this.native.scrollDown(amount);
79-
await this.updateTick();
8075
resolve(this);
8176
} catch (e) {
8277
reject(e);
@@ -87,9 +82,8 @@ export class Mouse {
8782
public async scrollUp(amount: number): Promise<Mouse> {
8883
return new Promise<Mouse>(async (resolve, reject) => {
8984
try {
90-
await this.waitForNextTick(this.config.autoDelayMs);
85+
await sleep(this.config.autoDelayMs);
9186
await this.native.scrollUp(amount);
92-
await this.updateTick();
9387
resolve(this);
9488
} catch (e) {
9589
reject(e);
@@ -100,9 +94,8 @@ export class Mouse {
10094
public async scrollLeft(amount: number): Promise<Mouse> {
10195
return new Promise<Mouse>(async (resolve, reject) => {
10296
try {
103-
await this.waitForNextTick(this.config.autoDelayMs);
97+
await sleep(this.config.autoDelayMs);
10498
await this.native.scrollLeft(amount);
105-
await this.updateTick();
10699
resolve(this);
107100
} catch (e) {
108101
reject(e);
@@ -113,42 +106,26 @@ export class Mouse {
113106
public async scrollRight(amount: number): Promise<Mouse> {
114107
return new Promise<Mouse>(async (resolve, reject) => {
115108
try {
116-
await this.waitForNextTick(this.config.autoDelayMs);
109+
await sleep(this.config.autoDelayMs);
117110
await this.native.scrollRight(amount);
118-
await this.updateTick();
119111
resolve(this);
120112
} catch (e) {
121113
reject(e);
122114
}
123115
});
124116
}
125117

126-
public async drag(path: Point[]): Promise<Mouse> {
118+
public async drag(path: Point[] | Promise<Point[]>): Promise<Mouse> {
127119
return new Promise<Mouse>(async (resolve, reject) => {
128120
try {
129-
await this.waitForNextTick(this.config.autoDelayMs);
121+
await sleep(this.config.autoDelayMs);
130122
await this.native.pressButton(Button.LEFT);
131123
await this.move(path);
132124
await this.native.releaseButton(Button.LEFT);
133-
await this.updateTick();
134125
resolve(this);
135126
} catch (e) {
136127
reject(e);
137128
}
138129
});
139130
}
140-
141-
private async updateTick() {
142-
this.lastAction = Date.now();
143-
}
144-
145-
private async waitForNextTick(minTime: number): Promise<void> {
146-
return new Promise<void>(resolve => {
147-
let current = Date.now();
148-
while (current - this.lastAction < minTime) {
149-
current = Date.now();
150-
}
151-
resolve();
152-
});
153-
}
154131
}

0 commit comments

Comments
 (0)