testdriverai 4.0.42 → 4.0.44
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/.github/workflows/format.yml +17 -0
- package/.github/workflows/npm-publish.yml +1 -1
- package/.prettierignore +2 -0
- package/.prettierrc +1 -0
- package/README.md +9 -10
- package/eslint.config.js +21 -0
- package/index.js +403 -394
- package/lib/analytics.js +8 -10
- package/lib/commander.js +120 -90
- package/lib/commands.js +259 -217
- package/lib/config.js +18 -18
- package/lib/focus-application.js +12 -15
- package/lib/generator.js +35 -35
- package/lib/history.js +10 -10
- package/lib/init.js +125 -120
- package/lib/keymap.js +114 -115
- package/lib/logger.js +42 -45
- package/lib/notify.js +1 -5
- package/lib/parser.js +28 -42
- package/lib/redraw.js +19 -23
- package/lib/sdk.js +46 -47
- package/lib/session.js +1 -1
- package/lib/speak.js +5 -7
- package/lib/subimage/index.js +9 -8
- package/lib/subimage/opencv.js +1 -0
- package/lib/system.js +38 -34
- package/lib/valid-version.js +10 -8
- package/package.json +7 -4
- package/postinstall.js +5 -5
package/lib/analytics.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
const sdk = require(
|
|
2
|
-
const config = require(
|
|
1
|
+
const sdk = require("./sdk");
|
|
2
|
+
const config = require("./config");
|
|
3
3
|
|
|
4
4
|
module.exports = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
sdk.req('analytics', { event, data });
|
|
11
|
-
}
|
|
12
|
-
|
|
5
|
+
track: async (event, data) => {
|
|
6
|
+
if (config["TD_ANALYTICS"]) {
|
|
7
|
+
return;
|
|
8
|
+
} else {
|
|
9
|
+
sdk.req("analytics", { event, data });
|
|
13
10
|
}
|
|
11
|
+
},
|
|
14
12
|
};
|
package/lib/commander.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
// translates the yml into commands that can be executed by the system.
|
|
2
|
-
const {commands} = require(
|
|
3
|
-
const {log} = require(
|
|
4
|
-
const generator = require(
|
|
5
|
-
const yaml = require(
|
|
6
|
-
const speak = require(
|
|
7
|
-
const notify = require(
|
|
8
|
-
const analytics = require(
|
|
2
|
+
const { commands } = require("./commands");
|
|
3
|
+
const { log } = require("./logger");
|
|
4
|
+
const generator = require("./generator");
|
|
5
|
+
const yaml = require("js-yaml");
|
|
6
|
+
const speak = require("./speak");
|
|
7
|
+
const notify = require("./notify");
|
|
8
|
+
const analytics = require("./analytics");
|
|
9
9
|
|
|
10
10
|
// object is a json representation of the individual yml command
|
|
11
11
|
// the process turns markdown -> yml -> json -> js function execution
|
|
12
|
-
const run = async(object, depth) => {
|
|
13
|
-
|
|
12
|
+
const run = async (object, depth) => {
|
|
14
13
|
// success returns null
|
|
15
14
|
// if this is set, it means that we need to take more action and a new thread is spawned
|
|
16
15
|
let response = null;
|
|
@@ -32,121 +31,152 @@ Here is a simple example:
|
|
|
32
31
|
commands:
|
|
33
32
|
- command: press-keys
|
|
34
33
|
keys: [command, space]
|
|
35
|
-
|
|
36
|
-
}else {
|
|
37
|
-
|
|
38
|
-
let image;
|
|
39
|
-
let copy = JSON.parse(JSON.stringify(object))
|
|
34
|
+
\`\`\``;
|
|
35
|
+
} else {
|
|
36
|
+
let copy = JSON.parse(JSON.stringify(object));
|
|
40
37
|
|
|
41
|
-
analytics.track(
|
|
38
|
+
analytics.track("command", { data: object, depth });
|
|
42
39
|
|
|
43
40
|
// we speak, log, and take images here because we want to be careful not to render a notification containing the text we're looking for
|
|
44
41
|
// or to cover the screen of some item we might want
|
|
45
42
|
|
|
46
43
|
// this will actually interpret the command and execute it
|
|
47
|
-
switch(object.command) {
|
|
48
|
-
case
|
|
44
|
+
switch (object.command) {
|
|
45
|
+
case "type":
|
|
49
46
|
speak(`typing ${object.text}`);
|
|
50
|
-
log(
|
|
51
|
-
notify(generator.jsonToManual(object, false))
|
|
47
|
+
log("info", generator.jsonToManual(object));
|
|
48
|
+
notify(generator.jsonToManual(object, false));
|
|
52
49
|
response = await commands.type(object.text);
|
|
53
50
|
break;
|
|
54
|
-
case
|
|
55
|
-
speak(`pressing keys ${object.keys.join(
|
|
56
|
-
log(
|
|
57
|
-
notify(generator.jsonToManual(object, false))
|
|
58
|
-
response = await commands[
|
|
51
|
+
case "press-keys":
|
|
52
|
+
speak(`pressing keys ${object.keys.join(",")}`);
|
|
53
|
+
log("info", generator.jsonToManual(object));
|
|
54
|
+
notify(generator.jsonToManual(object, false));
|
|
55
|
+
response = await commands["press-keys"](object.keys);
|
|
59
56
|
break;
|
|
60
|
-
case
|
|
57
|
+
case "scroll":
|
|
61
58
|
speak(`scrolling ${object.direction}`);
|
|
62
|
-
log(
|
|
63
|
-
notify(generator.jsonToManual(object, false))
|
|
59
|
+
log("info", generator.jsonToManual(object));
|
|
60
|
+
notify(generator.jsonToManual(object, false));
|
|
64
61
|
response = await commands.scroll(object.direction, object.amount);
|
|
65
62
|
break;
|
|
66
|
-
case
|
|
63
|
+
case "wait":
|
|
67
64
|
speak(`waiting ${object.timeout} seconds`);
|
|
68
|
-
log(
|
|
69
|
-
notify(generator.jsonToManual(object, false))
|
|
65
|
+
log("info", generator.jsonToManual(object));
|
|
66
|
+
notify(generator.jsonToManual(object, false));
|
|
70
67
|
response = await commands.wait(object.timeout);
|
|
71
68
|
break;
|
|
72
|
-
case
|
|
69
|
+
case "click":
|
|
73
70
|
speak(`${object.button} ${object.click} click`);
|
|
74
|
-
log(
|
|
75
|
-
notify(generator.jsonToManual(object, false))
|
|
76
|
-
response = await commands[
|
|
77
|
-
|
|
78
|
-
|
|
71
|
+
log("info", generator.jsonToManual(object));
|
|
72
|
+
notify(generator.jsonToManual(object, false));
|
|
73
|
+
response = await commands["click"](
|
|
74
|
+
object.x,
|
|
75
|
+
object.y,
|
|
76
|
+
object.button,
|
|
77
|
+
object.click,
|
|
78
|
+
);
|
|
79
|
+
break;
|
|
80
|
+
case "hover":
|
|
79
81
|
speak(`moving mouse`);
|
|
80
|
-
log(
|
|
81
|
-
notify(generator.jsonToManual(object, false))
|
|
82
|
-
response = await commands[
|
|
82
|
+
log("info", generator.jsonToManual(object));
|
|
83
|
+
notify(generator.jsonToManual(object, false));
|
|
84
|
+
response = await commands["hover"](object.x, object.y);
|
|
83
85
|
break;
|
|
84
|
-
case
|
|
86
|
+
case "hover-text":
|
|
85
87
|
speak(`searching for ${object.description}`);
|
|
86
|
-
log(
|
|
87
|
-
notify(generator.jsonToManual(object, false))
|
|
88
|
-
response = await commands[
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
log("info", generator.jsonToManual(object));
|
|
89
|
+
notify(generator.jsonToManual(object, false));
|
|
90
|
+
response = await commands["hover-text"](
|
|
91
|
+
object.text,
|
|
92
|
+
object.description,
|
|
93
|
+
object.action,
|
|
94
|
+
object.method,
|
|
95
|
+
);
|
|
96
|
+
break;
|
|
97
|
+
case "hover-image":
|
|
91
98
|
speak(`searching for image of ${object.description}`);
|
|
92
|
-
log(
|
|
93
|
-
response = await commands[
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
log("info", generator.jsonToManual(object));
|
|
100
|
+
response = await commands["hover-image"](
|
|
101
|
+
object.description,
|
|
102
|
+
object.action,
|
|
103
|
+
);
|
|
104
|
+
break;
|
|
105
|
+
case "match-image":
|
|
106
|
+
log("info", generator.jsonToManual(object));
|
|
107
|
+
notify(generator.jsonToManual(object, false));
|
|
108
|
+
response = await commands["match-image"](
|
|
109
|
+
object.path,
|
|
110
|
+
object.action,
|
|
111
|
+
object.button,
|
|
112
|
+
object.click,
|
|
113
|
+
);
|
|
114
|
+
break;
|
|
115
|
+
case "wait-for-image":
|
|
101
116
|
speak(`waiting for ${object.description}`);
|
|
102
|
-
log(
|
|
103
|
-
notify(generator.jsonToManual(object, false))
|
|
104
|
-
response = await commands[
|
|
105
|
-
|
|
106
|
-
|
|
117
|
+
log("info", generator.jsonToManual(object));
|
|
118
|
+
notify(generator.jsonToManual(object, false));
|
|
119
|
+
response = await commands["wait-for-image"](
|
|
120
|
+
object.description,
|
|
121
|
+
object.timeout,
|
|
122
|
+
);
|
|
123
|
+
break;
|
|
124
|
+
case "wait-for-text":
|
|
107
125
|
speak(`waiting for ${object.text}`);
|
|
108
|
-
log(
|
|
109
|
-
copy.text =
|
|
110
|
-
notify(generator.jsonToManual(copy, false))
|
|
111
|
-
response = await commands[
|
|
112
|
-
|
|
113
|
-
|
|
126
|
+
log("info", generator.jsonToManual(object));
|
|
127
|
+
copy.text = "*****";
|
|
128
|
+
notify(generator.jsonToManual(copy, false));
|
|
129
|
+
response = await commands["wait-for-text"](
|
|
130
|
+
object.text,
|
|
131
|
+
object.timeout,
|
|
132
|
+
object.method,
|
|
133
|
+
);
|
|
134
|
+
break;
|
|
135
|
+
case "scroll-until-text":
|
|
114
136
|
speak(`scrolling until ${object.text}`);
|
|
115
|
-
log(
|
|
116
|
-
copy.text =
|
|
117
|
-
notify(generator.jsonToManual(copy, false))
|
|
118
|
-
response = await commands[
|
|
119
|
-
|
|
120
|
-
|
|
137
|
+
log("info", generator.jsonToManual(object));
|
|
138
|
+
copy.text = "*****";
|
|
139
|
+
notify(generator.jsonToManual(copy, false));
|
|
140
|
+
response = await commands["scroll-until-text"](
|
|
141
|
+
object.text,
|
|
142
|
+
object.direction,
|
|
143
|
+
object.distance,
|
|
144
|
+
object.method,
|
|
145
|
+
);
|
|
146
|
+
break;
|
|
147
|
+
case "scroll-until-image":
|
|
121
148
|
speak(`scrolling until ${object.description}`);
|
|
122
|
-
log(
|
|
123
|
-
notify(generator.jsonToManual(object, false))
|
|
124
|
-
response = await commands[
|
|
125
|
-
|
|
126
|
-
|
|
149
|
+
log("info", generator.jsonToManual(object));
|
|
150
|
+
notify(generator.jsonToManual(object, false));
|
|
151
|
+
response = await commands["scroll-until-image"](
|
|
152
|
+
object.description,
|
|
153
|
+
object.direction,
|
|
154
|
+
object.distance,
|
|
155
|
+
);
|
|
156
|
+
break;
|
|
157
|
+
case "focus-application":
|
|
127
158
|
speak(`focusing ${object.name}`);
|
|
128
|
-
log(
|
|
129
|
-
notify(generator.jsonToManual(object, false))
|
|
130
|
-
response = await commands[
|
|
159
|
+
log("info", generator.jsonToManual(object));
|
|
160
|
+
notify(generator.jsonToManual(object, false));
|
|
161
|
+
response = await commands["focus-application"](object.name);
|
|
131
162
|
break;
|
|
132
|
-
case
|
|
133
|
-
log(
|
|
134
|
-
notify(generator.jsonToManual(object, false))
|
|
135
|
-
response = await commands[
|
|
163
|
+
case "remember":
|
|
164
|
+
log("info", generator.jsonToManual(object));
|
|
165
|
+
notify(generator.jsonToManual(object, false));
|
|
166
|
+
response = await commands["remember"](object.description, object.value);
|
|
136
167
|
break;
|
|
137
|
-
case
|
|
168
|
+
case "assert":
|
|
138
169
|
speak(`asserting ${object.expect}`);
|
|
139
|
-
log(
|
|
140
|
-
notify(generator.jsonToManual(object, false))
|
|
170
|
+
log("info", generator.jsonToManual(object));
|
|
171
|
+
notify(generator.jsonToManual(object, false));
|
|
141
172
|
response = await commands.assert(object.expect, object.async);
|
|
142
173
|
break;
|
|
143
|
-
default:
|
|
174
|
+
default:
|
|
144
175
|
throw new Error(`Command not found: ${object.command}`);
|
|
145
176
|
}
|
|
146
177
|
}
|
|
147
178
|
|
|
148
179
|
return response;
|
|
180
|
+
};
|
|
149
181
|
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
module.exports = { run }
|
|
182
|
+
module.exports = { run };
|