usecomputer 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +324 -0
- package/dist/bridge-contract.test.js +124 -63
- package/dist/bridge.d.ts.map +1 -1
- package/dist/bridge.js +241 -46
- package/dist/cli-parsing.test.js +34 -11
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +323 -28
- package/dist/coord-map.d.ts +14 -0
- package/dist/coord-map.d.ts.map +1 -0
- package/dist/coord-map.js +75 -0
- package/dist/coord-map.test.d.ts +2 -0
- package/dist/coord-map.test.d.ts.map +1 -0
- package/dist/coord-map.test.js +157 -0
- package/dist/darwin-arm64/usecomputer.node +0 -0
- package/dist/darwin-x64/usecomputer.node +0 -0
- package/dist/debug-point-image.d.ts +8 -0
- package/dist/debug-point-image.d.ts.map +1 -0
- package/dist/debug-point-image.js +43 -0
- package/dist/debug-point-image.test.d.ts +2 -0
- package/dist/debug-point-image.test.d.ts.map +1 -0
- package/dist/debug-point-image.test.js +44 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/lib.d.ts +26 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/lib.js +88 -0
- package/dist/native-click-smoke.test.js +69 -29
- package/dist/native-lib.d.ts +59 -1
- package/dist/native-lib.d.ts.map +1 -1
- package/dist/terminal-table.d.ts +10 -0
- package/dist/terminal-table.d.ts.map +1 -0
- package/dist/terminal-table.js +55 -0
- package/dist/terminal-table.test.d.ts +2 -0
- package/dist/terminal-table.test.d.ts.map +1 -0
- package/dist/terminal-table.test.js +41 -0
- package/dist/types.d.ts +45 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +16 -4
- package/src/bridge-contract.test.ts +140 -69
- package/src/bridge.ts +293 -53
- package/src/cli-parsing.test.ts +61 -0
- package/src/cli.ts +393 -32
- package/src/coord-map.test.ts +178 -0
- package/src/coord-map.ts +105 -0
- package/src/debug-point-image.test.ts +50 -0
- package/src/debug-point-image.ts +69 -0
- package/src/index.ts +3 -1
- package/src/lib.ts +125 -0
- package/src/native-click-smoke.test.ts +81 -63
- package/src/native-lib.ts +39 -1
- package/src/terminal-table.test.ts +44 -0
- package/src/terminal-table.ts +88 -0
- package/src/types.ts +50 -0
- package/zig/src/lib.zig +1258 -267
- package/zig/src/scroll.zig +213 -0
- package/zig/src/window.zig +123 -0
package/src/bridge.ts
CHANGED
|
@@ -1,37 +1,114 @@
|
|
|
1
|
-
// Native bridge that maps typed TS calls to
|
|
1
|
+
// Native bridge that maps typed TS calls to direct Zig N-API methods.
|
|
2
2
|
|
|
3
3
|
import { native, type NativeModule } from './native-lib.js'
|
|
4
|
+
import { z } from 'zod'
|
|
4
5
|
import type {
|
|
5
6
|
ClickInput,
|
|
7
|
+
DisplayInfo,
|
|
6
8
|
DragInput,
|
|
9
|
+
NativeCommandResult,
|
|
10
|
+
NativeDataResult,
|
|
7
11
|
Point,
|
|
8
12
|
PressInput,
|
|
13
|
+
Region,
|
|
9
14
|
ScreenshotInput,
|
|
10
15
|
ScreenshotResult,
|
|
11
16
|
ScrollInput,
|
|
12
17
|
TypeInput,
|
|
13
18
|
UseComputerBridge,
|
|
14
|
-
|
|
19
|
+
WindowInfo,
|
|
15
20
|
} from './types.js'
|
|
16
21
|
|
|
22
|
+
const displayInfoSchema = z.object({
|
|
23
|
+
id: z.number(),
|
|
24
|
+
index: z.number(),
|
|
25
|
+
name: z.string(),
|
|
26
|
+
x: z.number(),
|
|
27
|
+
y: z.number(),
|
|
28
|
+
width: z.number(),
|
|
29
|
+
height: z.number(),
|
|
30
|
+
scale: z.number(),
|
|
31
|
+
isPrimary: z.boolean(),
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
const displayListSchema = z.array(displayInfoSchema)
|
|
35
|
+
|
|
36
|
+
const windowInfoSchema = z.object({
|
|
37
|
+
id: z.number(),
|
|
38
|
+
ownerPid: z.number(),
|
|
39
|
+
ownerName: z.string(),
|
|
40
|
+
title: z.string(),
|
|
41
|
+
x: z.number(),
|
|
42
|
+
y: z.number(),
|
|
43
|
+
width: z.number(),
|
|
44
|
+
height: z.number(),
|
|
45
|
+
desktopIndex: z.number(),
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
const windowListSchema = z.array(windowInfoSchema)
|
|
49
|
+
|
|
17
50
|
const unavailableError =
|
|
18
51
|
'Native backend is unavailable. Build it with `pnpm build:native` or `zig build` in usecomputer/.'
|
|
19
52
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
command
|
|
23
|
-
|
|
53
|
+
class NativeBridgeError extends Error {
|
|
54
|
+
readonly code?: string
|
|
55
|
+
readonly command?: string
|
|
56
|
+
|
|
57
|
+
constructor({
|
|
58
|
+
message,
|
|
59
|
+
code,
|
|
60
|
+
command,
|
|
61
|
+
}: {
|
|
62
|
+
message: string
|
|
63
|
+
code?: string
|
|
64
|
+
command?: string
|
|
65
|
+
}) {
|
|
66
|
+
super(message)
|
|
67
|
+
this.name = 'NativeBridgeError'
|
|
68
|
+
this.code = code
|
|
69
|
+
this.command = command
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function unwrapCommand({
|
|
74
|
+
result,
|
|
75
|
+
fallbackCommand,
|
|
76
|
+
}: {
|
|
77
|
+
result: NativeCommandResult
|
|
78
|
+
fallbackCommand: string
|
|
79
|
+
}): Error | null {
|
|
80
|
+
if (result.ok) {
|
|
81
|
+
return null
|
|
82
|
+
}
|
|
83
|
+
const message = result.error?.message || `Native command failed: ${fallbackCommand}`
|
|
84
|
+
return new NativeBridgeError({
|
|
85
|
+
message,
|
|
86
|
+
code: result.error?.code,
|
|
87
|
+
command: result.error?.command || fallbackCommand,
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function unwrapData<T>({
|
|
92
|
+
result,
|
|
93
|
+
fallbackCommand,
|
|
24
94
|
}: {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
payload: unknown
|
|
95
|
+
result: NativeDataResult<T>
|
|
96
|
+
fallbackCommand: string
|
|
28
97
|
}): Error | T {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
98
|
+
if (result.ok) {
|
|
99
|
+
if (result.data === undefined) {
|
|
100
|
+
return new NativeBridgeError({
|
|
101
|
+
message: `Native command returned no data: ${fallbackCommand}`,
|
|
102
|
+
command: fallbackCommand,
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
return result.data
|
|
33
106
|
}
|
|
34
|
-
return
|
|
107
|
+
return new NativeBridgeError({
|
|
108
|
+
message: result.error?.message || `Native command failed: ${fallbackCommand}`,
|
|
109
|
+
code: result.error?.code,
|
|
110
|
+
command: result.error?.command || fallbackCommand,
|
|
111
|
+
})
|
|
35
112
|
}
|
|
36
113
|
|
|
37
114
|
function unavailableBridge(): UseComputerBridge {
|
|
@@ -52,6 +129,7 @@ function unavailableBridge(): UseComputerBridge {
|
|
|
52
129
|
mouseUp: fail,
|
|
53
130
|
mousePosition: fail,
|
|
54
131
|
displayList: fail,
|
|
132
|
+
windowList: fail,
|
|
55
133
|
clipboardGet: fail,
|
|
56
134
|
clipboardSet: fail,
|
|
57
135
|
}
|
|
@@ -64,91 +142,253 @@ export function createBridgeFromNative({ nativeModule }: { nativeModule: NativeM
|
|
|
64
142
|
|
|
65
143
|
return {
|
|
66
144
|
async screenshot(input: ScreenshotInput): Promise<ScreenshotResult> {
|
|
67
|
-
const
|
|
145
|
+
const nativeInput: {
|
|
146
|
+
path: string | null
|
|
147
|
+
display: number | null
|
|
148
|
+
window: number | null
|
|
149
|
+
region: Region | null
|
|
150
|
+
annotate: boolean | null
|
|
151
|
+
} = {
|
|
152
|
+
path: input.path ?? null,
|
|
153
|
+
display: input.display ?? null,
|
|
154
|
+
window: input.window ?? null,
|
|
155
|
+
region: input.region ?? null,
|
|
156
|
+
annotate: input.annotate ?? null,
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const result = unwrapData({
|
|
160
|
+
result: nativeModule.screenshot(nativeInput),
|
|
161
|
+
fallbackCommand: 'screenshot',
|
|
162
|
+
})
|
|
68
163
|
if (result instanceof Error) {
|
|
69
164
|
throw result
|
|
70
165
|
}
|
|
71
|
-
|
|
166
|
+
const coordMap = [
|
|
167
|
+
result.captureX,
|
|
168
|
+
result.captureY,
|
|
169
|
+
result.captureWidth,
|
|
170
|
+
result.captureHeight,
|
|
171
|
+
result.imageWidth,
|
|
172
|
+
result.imageHeight,
|
|
173
|
+
].join(',')
|
|
174
|
+
const hint = [
|
|
175
|
+
'ALWAYS pass this exact coord map to click, hover, drag, and mouse move when using coordinates from this screenshot:',
|
|
176
|
+
`--coord-map "${coordMap}"`,
|
|
177
|
+
'',
|
|
178
|
+
'Example:',
|
|
179
|
+
`usecomputer click -x 400 -y 220 --coord-map "${coordMap}"`,
|
|
180
|
+
].join('\n')
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
path: result.path,
|
|
184
|
+
desktopIndex: result.desktopIndex,
|
|
185
|
+
captureX: result.captureX,
|
|
186
|
+
captureY: result.captureY,
|
|
187
|
+
captureWidth: result.captureWidth,
|
|
188
|
+
captureHeight: result.captureHeight,
|
|
189
|
+
imageWidth: result.imageWidth,
|
|
190
|
+
imageHeight: result.imageHeight,
|
|
191
|
+
coordMap,
|
|
192
|
+
hint,
|
|
193
|
+
}
|
|
72
194
|
},
|
|
73
195
|
async click(input: ClickInput): Promise<void> {
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
196
|
+
const nativeInput: { point: Point; button: 'left' | 'right' | 'middle' | null; count: number | null } = {
|
|
197
|
+
point: input.point,
|
|
198
|
+
button: input.button ?? null,
|
|
199
|
+
count: input.count ?? null,
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const result = nativeModule.click(nativeInput)
|
|
203
|
+
const maybeError = unwrapCommand({ result, fallbackCommand: 'click' })
|
|
204
|
+
if (maybeError instanceof Error) {
|
|
205
|
+
throw maybeError
|
|
77
206
|
}
|
|
78
207
|
},
|
|
79
208
|
async typeText(input: TypeInput): Promise<void> {
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
209
|
+
const nativeInput: { text: string; delayMs: number | null } = {
|
|
210
|
+
text: input.text,
|
|
211
|
+
delayMs: input.delayMs ?? null,
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const result = nativeModule.typeText(nativeInput)
|
|
215
|
+
const maybeError = unwrapCommand({ result, fallbackCommand: 'typeText' })
|
|
216
|
+
if (maybeError instanceof Error) {
|
|
217
|
+
throw maybeError
|
|
83
218
|
}
|
|
84
219
|
},
|
|
85
220
|
async press(input: PressInput): Promise<void> {
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
221
|
+
const nativeInput: { key: string; count: number | null; delayMs: number | null } = {
|
|
222
|
+
key: input.key,
|
|
223
|
+
count: input.count ?? null,
|
|
224
|
+
delayMs: input.delayMs ?? null,
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const result = nativeModule.press(nativeInput)
|
|
228
|
+
const maybeError = unwrapCommand({ result, fallbackCommand: 'press' })
|
|
229
|
+
if (maybeError instanceof Error) {
|
|
230
|
+
throw maybeError
|
|
89
231
|
}
|
|
90
232
|
},
|
|
91
233
|
async scroll(input: ScrollInput): Promise<void> {
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
234
|
+
const nativeInput: { direction: string; amount: number; at: Point | null } = {
|
|
235
|
+
direction: input.direction,
|
|
236
|
+
amount: input.amount,
|
|
237
|
+
at: input.at ?? null,
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const result = nativeModule.scroll(nativeInput)
|
|
241
|
+
const maybeError = unwrapCommand({ result, fallbackCommand: 'scroll' })
|
|
242
|
+
if (maybeError instanceof Error) {
|
|
243
|
+
throw maybeError
|
|
95
244
|
}
|
|
96
245
|
},
|
|
97
246
|
async drag(input: DragInput): Promise<void> {
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
247
|
+
const nativeInput: {
|
|
248
|
+
from: Point
|
|
249
|
+
to: Point
|
|
250
|
+
durationMs: number | null
|
|
251
|
+
button: 'left' | 'right' | 'middle' | null
|
|
252
|
+
} = {
|
|
253
|
+
from: input.from,
|
|
254
|
+
to: input.to,
|
|
255
|
+
durationMs: input.durationMs ?? null,
|
|
256
|
+
button: input.button ?? null,
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const result = nativeModule.drag(nativeInput)
|
|
260
|
+
const maybeError = unwrapCommand({ result, fallbackCommand: 'drag' })
|
|
261
|
+
if (maybeError instanceof Error) {
|
|
262
|
+
throw maybeError
|
|
101
263
|
}
|
|
102
264
|
},
|
|
103
265
|
async hover(input: Point): Promise<void> {
|
|
104
|
-
const result =
|
|
105
|
-
|
|
106
|
-
|
|
266
|
+
const result = nativeModule.hover(input)
|
|
267
|
+
const maybeError = unwrapCommand({ result, fallbackCommand: 'hover' })
|
|
268
|
+
if (maybeError instanceof Error) {
|
|
269
|
+
throw maybeError
|
|
107
270
|
}
|
|
108
271
|
},
|
|
109
272
|
async mouseMove(input: Point): Promise<void> {
|
|
110
|
-
const result =
|
|
111
|
-
|
|
112
|
-
|
|
273
|
+
const result = nativeModule.mouseMove(input)
|
|
274
|
+
const maybeError = unwrapCommand({ result, fallbackCommand: 'mouseMove' })
|
|
275
|
+
if (maybeError instanceof Error) {
|
|
276
|
+
throw maybeError
|
|
113
277
|
}
|
|
114
278
|
},
|
|
115
279
|
async mouseDown(input: { button: 'left' | 'right' | 'middle' }): Promise<void> {
|
|
116
|
-
const result =
|
|
117
|
-
|
|
118
|
-
|
|
280
|
+
const result = nativeModule.mouseDown({ button: input.button ?? null })
|
|
281
|
+
const maybeError = unwrapCommand({ result, fallbackCommand: 'mouseDown' })
|
|
282
|
+
if (maybeError instanceof Error) {
|
|
283
|
+
throw maybeError
|
|
119
284
|
}
|
|
120
285
|
},
|
|
121
286
|
async mouseUp(input: { button: 'left' | 'right' | 'middle' }): Promise<void> {
|
|
122
|
-
const result =
|
|
123
|
-
|
|
124
|
-
|
|
287
|
+
const result = nativeModule.mouseUp({ button: input.button ?? null })
|
|
288
|
+
const maybeError = unwrapCommand({ result, fallbackCommand: 'mouseUp' })
|
|
289
|
+
if (maybeError instanceof Error) {
|
|
290
|
+
throw maybeError
|
|
125
291
|
}
|
|
126
292
|
},
|
|
127
293
|
async mousePosition(): Promise<Point> {
|
|
128
|
-
const result =
|
|
294
|
+
const result = unwrapData({
|
|
295
|
+
result: nativeModule.mousePosition(),
|
|
296
|
+
fallbackCommand: 'mousePosition',
|
|
297
|
+
})
|
|
129
298
|
if (result instanceof Error) {
|
|
130
299
|
throw result
|
|
131
300
|
}
|
|
132
301
|
return result
|
|
133
302
|
},
|
|
134
303
|
async displayList(): Promise<DisplayInfo[]> {
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
304
|
+
const payload = unwrapData({
|
|
305
|
+
result: nativeModule.displayList(),
|
|
306
|
+
fallbackCommand: 'displayList',
|
|
307
|
+
})
|
|
308
|
+
if (payload instanceof Error) {
|
|
309
|
+
throw payload
|
|
138
310
|
}
|
|
139
|
-
|
|
311
|
+
|
|
312
|
+
let parsedJson: unknown
|
|
313
|
+
try {
|
|
314
|
+
parsedJson = JSON.parse(payload)
|
|
315
|
+
} catch (e) {
|
|
316
|
+
throw new NativeBridgeError({
|
|
317
|
+
message: 'Native displayList returned invalid JSON',
|
|
318
|
+
command: 'displayList',
|
|
319
|
+
code: 'INVALID_NATIVE_JSON',
|
|
320
|
+
})
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const parsed = displayListSchema.safeParse(parsedJson)
|
|
324
|
+
if (!parsed.success) {
|
|
325
|
+
throw new NativeBridgeError({
|
|
326
|
+
message: 'Native displayList returned invalid payload shape',
|
|
327
|
+
command: 'displayList',
|
|
328
|
+
code: 'INVALID_NATIVE_PAYLOAD',
|
|
329
|
+
})
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
return parsed.data.map((display) => {
|
|
333
|
+
return {
|
|
334
|
+
id: display.id,
|
|
335
|
+
index: display.index,
|
|
336
|
+
name: display.name,
|
|
337
|
+
x: display.x,
|
|
338
|
+
y: display.y,
|
|
339
|
+
width: display.width,
|
|
340
|
+
height: display.height,
|
|
341
|
+
scale: display.scale,
|
|
342
|
+
isPrimary: display.isPrimary,
|
|
343
|
+
}
|
|
344
|
+
})
|
|
345
|
+
},
|
|
346
|
+
async windowList(): Promise<WindowInfo[]> {
|
|
347
|
+
const payload = unwrapData({
|
|
348
|
+
result: nativeModule.windowList(),
|
|
349
|
+
fallbackCommand: 'windowList',
|
|
350
|
+
})
|
|
351
|
+
if (payload instanceof Error) {
|
|
352
|
+
throw payload
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
let parsedJson: unknown
|
|
356
|
+
try {
|
|
357
|
+
parsedJson = JSON.parse(payload)
|
|
358
|
+
} catch {
|
|
359
|
+
throw new NativeBridgeError({
|
|
360
|
+
message: 'Native windowList returned invalid JSON',
|
|
361
|
+
command: 'windowList',
|
|
362
|
+
code: 'INVALID_NATIVE_JSON',
|
|
363
|
+
})
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const parsed = windowListSchema.safeParse(parsedJson)
|
|
367
|
+
if (!parsed.success) {
|
|
368
|
+
throw new NativeBridgeError({
|
|
369
|
+
message: 'Native windowList returned invalid payload shape',
|
|
370
|
+
command: 'windowList',
|
|
371
|
+
code: 'INVALID_NATIVE_PAYLOAD',
|
|
372
|
+
})
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return parsed.data
|
|
140
376
|
},
|
|
141
377
|
async clipboardGet(): Promise<string> {
|
|
142
|
-
const result =
|
|
378
|
+
const result = unwrapData({
|
|
379
|
+
result: nativeModule.clipboardGet(),
|
|
380
|
+
fallbackCommand: 'clipboardGet',
|
|
381
|
+
})
|
|
143
382
|
if (result instanceof Error) {
|
|
144
383
|
throw result
|
|
145
384
|
}
|
|
146
|
-
return result
|
|
385
|
+
return result
|
|
147
386
|
},
|
|
148
387
|
async clipboardSet(input: { text: string }): Promise<void> {
|
|
149
|
-
const result =
|
|
150
|
-
|
|
151
|
-
|
|
388
|
+
const result = nativeModule.clipboardSet(input)
|
|
389
|
+
const maybeError = unwrapCommand({ result, fallbackCommand: 'clipboardSet' })
|
|
390
|
+
if (maybeError instanceof Error) {
|
|
391
|
+
throw maybeError
|
|
152
392
|
}
|
|
153
393
|
},
|
|
154
394
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Parser tests for goke CLI options and flags.
|
|
2
|
+
|
|
3
|
+
import { describe, expect, test } from 'vitest'
|
|
4
|
+
import { createCli } from './cli.js'
|
|
5
|
+
|
|
6
|
+
describe('usecomputer cli parsing', () => {
|
|
7
|
+
test('parses click options with typed defaults', () => {
|
|
8
|
+
const cli = createCli()
|
|
9
|
+
const parsed = cli.parse(['node', 'usecomputer', 'click', '100,200', '--count', '2'], { run: false })
|
|
10
|
+
expect(parsed.args[0]).toBe('100,200')
|
|
11
|
+
expect(parsed.options.count).toBe(2)
|
|
12
|
+
expect(parsed.options.button).toBe('left')
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
test('parses screenshot options', () => {
|
|
16
|
+
const cli = createCli()
|
|
17
|
+
const parsed = cli.parse(['node', 'usecomputer', 'screenshot', './shot.png', '--display', '2', '--region', '0,0,120,80'], {
|
|
18
|
+
run: false,
|
|
19
|
+
})
|
|
20
|
+
expect(parsed.args[0]).toBe('./shot.png')
|
|
21
|
+
expect(parsed.options.display).toBe(2)
|
|
22
|
+
expect(parsed.options.region).toBe('0,0,120,80')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test('parses coord-map option for click and mouse move', () => {
|
|
26
|
+
const clickCli = createCli()
|
|
27
|
+
const clickParsed = clickCli.parse(['node', 'usecomputer', 'click', '-x', '100', '-y', '200', '--coord-map', '0,0,1600,900,1568,882'], {
|
|
28
|
+
run: false,
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const moveCli = createCli()
|
|
32
|
+
const moveParsed = moveCli.parse(['node', 'usecomputer', 'mouse', 'move', '-x', '100', '-y', '200', '--coord-map', '0,0,1600,900,1568,882'], {
|
|
33
|
+
run: false,
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
expect(clickParsed.options.coordMap).toBe('0,0,1600,900,1568,882')
|
|
37
|
+
expect(moveParsed.options.coordMap).toBe('0,0,1600,900,1568,882')
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('parses debug-point options', () => {
|
|
41
|
+
const cli = createCli()
|
|
42
|
+
const parsed = cli.parse([
|
|
43
|
+
'node',
|
|
44
|
+
'usecomputer',
|
|
45
|
+
'debug-point',
|
|
46
|
+
'-x',
|
|
47
|
+
'210',
|
|
48
|
+
'-y',
|
|
49
|
+
'560',
|
|
50
|
+
'--coord-map',
|
|
51
|
+
'0,0,1720,1440,1568,1313',
|
|
52
|
+
'--output',
|
|
53
|
+
'./tmp/debug-point.png',
|
|
54
|
+
], { run: false })
|
|
55
|
+
|
|
56
|
+
expect(parsed.options.coordMap).toBe('0,0,1720,1440,1568,1313')
|
|
57
|
+
expect(parsed.options.output).toBe('./tmp/debug-point.png')
|
|
58
|
+
expect(parsed.options.x).toBe(210)
|
|
59
|
+
expect(parsed.options.y).toBe(560)
|
|
60
|
+
})
|
|
61
|
+
})
|