testdriverai 5.7.37 → 5.7.39

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.
@@ -1,5 +1,8 @@
1
+ # Ensure affected code follows standards and is formatted correctly. Otherwise, automatic formatting in future changes will cause larger diffs.
1
2
  name: Lint + Prettier
3
+
2
4
  on: push
5
+
3
6
  jobs:
4
7
  lint:
5
8
  runs-on: ubuntu-latest
@@ -1,4 +1,5 @@
1
- name: TestDriver.ai
1
+ # CLI Acceptance Tests that validate & document E2E behavior with the CLI & TestDriver.ai API
2
+ name: Acceptance Tests
2
3
 
3
4
  permissions:
4
5
  contents: write
@@ -7,13 +8,30 @@ permissions:
7
8
  statuses: write
8
9
 
9
10
  on:
10
- push:
11
- branches: ["main"]
11
+ # Run in Merge Queue rather than individual PRs
12
+ merge_group:
13
+ # Through the GitHub UI
12
14
  workflow_dispatch:
15
+ # Run every day at midnight to ensure CLI -> API works
13
16
  schedule:
14
17
  - cron: "0 0 * * *"
15
18
 
16
19
  jobs:
20
+ publish-beta:
21
+ name: Publish testdriverai@beta
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ with:
26
+ ref: ${{ github.ref }}
27
+ - uses: actions/setup-node@v3
28
+ with:
29
+ node-version: "20"
30
+ - uses: JS-DevTools/npm-publish@v3
31
+ with:
32
+ tag: "beta"
33
+ token: ${{ secrets.NPM_AUTH_TOKEN }}
34
+
17
35
  gather-test-files:
18
36
  name: Gather Test Files
19
37
  runs-on: ubuntu-latest
@@ -48,6 +66,7 @@ jobs:
48
66
  id: testdriver
49
67
  uses: testdriverai/action@main
50
68
  with:
69
+ version: "beta"
51
70
  os: ${{ contains(matrix.os, 'windows') && 'windows' || 'linux' }}
52
71
  prerun: |
53
72
  exit
@@ -89,13 +108,14 @@ jobs:
89
108
  name: snippets-${{ matrix.os }}-${{ matrix.test }}
90
109
  path: snippets/
91
110
  retention-days: 1
111
+
92
112
  create-snippets-commit:
93
113
  name: Commit Snippets
94
114
  needs: run-tests
95
115
  runs-on: ubuntu-latest
96
116
  if: ${{ always() }}
97
117
  env:
98
- BASE_BRANCH: ${{ github.event.pull_request.base.ref || github.ref_name }}
118
+ BASE_BRANCH: ${{ github.ref_name }}
99
119
  steps:
100
120
  - name: Check out current branch
101
121
  uses: actions/checkout@v3
@@ -1,9 +1,11 @@
1
+ # `main` is always published to `testdriverai@latest`. Checks are performed in PRs and the Merge Queue to ensure a healthy `main` branch."
2
+ name: Publish to NPM
3
+
1
4
  on:
2
5
  push:
3
6
  branches:
4
7
  - main
5
8
 
6
- name: Publish to NPM
7
9
  jobs:
8
10
  bump_version:
9
11
  name: "Bump Version"
@@ -30,10 +32,10 @@ jobs:
30
32
  run: |
31
33
  git push https://${{ secrets.GH_TOKEN }}@github.com/testdriverai/testdriverai.git HEAD:main --force
32
34
 
33
- publish:
34
- name: Publish
35
- runs-on: ubuntu-latest
35
+ publish-latest:
36
+ name: Publish testdriverai@latest
36
37
  needs: bump_version
38
+ runs-on: ubuntu-latest
37
39
  steps:
38
40
  - uses: actions/checkout@v4
39
41
  with:
@@ -1,15 +1,11 @@
1
+ # Ensure that the published `testdriverai` package is installable on multiple version of Node.js across multiple operating systems.
1
2
  name: Test TestDriverAI Installation
2
3
 
3
4
  on:
4
5
  schedule:
5
6
  - cron: "0 * * * *" # Runs every hour
6
7
  workflow_dispatch:
7
- push:
8
- branches:
9
- - main
10
- pull_request:
11
- branches:
12
- - main
8
+ merge_group:
13
9
 
14
10
  jobs:
15
11
  install-testdriverai:
@@ -33,4 +29,4 @@ jobs:
33
29
  run: npm install -g testdriverai
34
30
 
35
31
  - name: Verify Installation
36
- run: testdriverai --help || echo "TestDriverAI not found"
32
+ run: testdriverai --help
@@ -1,377 +1,358 @@
1
1
  <!doctype html>
2
2
  <html>
3
+ <head>
4
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
5
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
6
+ <link
7
+ href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&display=swap"
8
+ rel="stylesheet"
9
+ />
10
+ <title>TestDriver</title>
11
+ <style>
12
+ * {
13
+ margin: 0;
14
+ padding: 0;
15
+ overflow: hidden;
16
+ box-sizing: border-box;
17
+ font-family: "IBM Plex Mono", monospace;
18
+ font-weight: 400;
19
+ font-style: normal;
20
+ font-size: 14px;
21
+ scrollbar-width: none; /* Hide scrollbars for Firefox */
22
+ pointer-events: none;
23
+ }
3
24
 
4
- <head>
5
- <link rel="preconnect" href="https://fonts.googleapis.com">
6
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
7
- <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&display=swap" rel="stylesheet">
8
- <title>TestDriver</title>
9
- <style>
10
- * {
11
- margin: 0;
12
- padding: 0;
13
- overflow: hidden;
14
- box-sizing: border-box;
15
- font-family: "IBM Plex Mono", monospace;
16
- font-weight: 400;
17
- font-style: normal;
18
- font-size: 14px;
19
- scrollbar-width: none; /* Hide scrollbars for Firefox */
20
- pointer-events: none;
21
- }
22
-
23
- *::-webkit-scrollbar {
24
- display: none; /* Hide scrollbars for WebKit browsers */
25
- }
26
-
27
- @keyframes animate-glow {
28
- 0% {
29
- opacity: 0;
30
- filter: brightness(3) saturate(3);
31
- transform: scale(0.8, 0.8);
25
+ *::-webkit-scrollbar {
26
+ display: none; /* Hide scrollbars for WebKit browsers */
32
27
  }
33
28
 
34
- 30% {
35
- opacity: 1;
36
- filter: brightness(1) saturate(1);
37
- transform: scale(1, 1);
29
+ @keyframes animate-glow {
30
+ 0% {
31
+ opacity: 0;
32
+ filter: brightness(3) saturate(3);
33
+ transform: scale(0.8, 0.8);
34
+ }
35
+
36
+ 30% {
37
+ opacity: 1;
38
+ filter: brightness(1) saturate(1);
39
+ transform: scale(1, 1);
40
+ }
41
+
42
+ 100% {
43
+ /* opacity: 0; */
44
+ opacity: 1;
45
+ transform: scale(1, 1);
46
+ }
38
47
  }
39
48
 
40
- 100% {
41
- /* opacity: 0; */
42
- opacity: 1;
43
- transform: scale(1, 1);
49
+ @keyframes animate-screenshot {
50
+ 0% {
51
+ opacity: 0;
52
+ transform: scale(1, 1);
53
+ }
54
+
55
+ 30% {
56
+ opacity: 1;
57
+ filter: brightness(3) saturate(3);
58
+ }
59
+
60
+ 50% {
61
+ opacity: 1;
62
+ transform: scale(0.99, 0.99);
63
+ filter: brightness(3) saturate(3);
64
+ }
65
+
66
+ 70% {
67
+ opacity: 1;
68
+ filter: brightness(3) saturate(3);
69
+ }
70
+
71
+ 100% {
72
+ opacity: 0;
73
+ transform: scale(1, 1);
74
+ }
44
75
  }
45
- }
46
76
 
47
- @keyframes animate-screenshot {
48
- 0% {
49
- opacity: 0;
50
- transform: scale(1, 1);
77
+ body {
78
+ width: 100vw;
79
+ height: 100vh;
80
+ position: relative;
51
81
  }
52
82
 
53
- 30% {
54
- opacity: 1;
55
- filter: brightness(3) saturate(3);
83
+ .screenshot {
84
+ position: absolute;
85
+ inset: 0;
86
+ z-index: 1;
87
+ opacity: 0;
88
+ animation-duration: 0.3s;
89
+ animation-delay: 0;
90
+ animation-timing-function: cubic-bezier(0.26, 0.53, 0.74, 1.48);
91
+ animation-fill-mode: backwards;
92
+ animation-name: animate-screenshot;
93
+ animation-timing-function: ease;
94
+ animation-fill-mode: forwards;
95
+ background-color: white;
56
96
  }
57
97
 
58
- 50% {
59
- opacity: 1;
60
- transform: scale(.99, .99);
61
- filter: brightness(3) saturate(3);
98
+ .box {
99
+ border: 1px solid #b0cf34;
100
+ position: absolute;
101
+ border-radius: 5px;
102
+ animation-duration: 5s;
103
+ animation-delay: 0s;
104
+ animation-timing-function: cubic-bezier(0.26, 0.53, 0.74, 1.48);
105
+ animation-fill-mode: backwards;
106
+ animation-name: animate-glow;
107
+ animation-timing-function: ease;
108
+ animation-fill-mode: forwards;
109
+ border-radius: 5px;
62
110
  }
63
111
 
64
- 70% {
65
- opacity: 1;
66
- filter: brightness(3) saturate(3);
112
+ .container {
113
+ inset: 0;
114
+ position: absolute;
67
115
  }
68
116
 
69
- 100% {
117
+ #mouse {
118
+ margin-left: -100px;
119
+ margin-top: -100px;
120
+ width: 50px;
121
+ height: 50px;
70
122
  opacity: 0;
71
- transform: scale(1, 1);
123
+ position: absolute;
124
+ transform: translate(-50%, -50%);
125
+ border-radius: 70%;
126
+ background: #b0cf34;
72
127
  }
73
- }
74
-
75
- body {
76
- width: 100vw;
77
- height: 100vh;
78
- position: relative;
79
- }
80
-
81
- .screenshot {
82
- position: absolute;
83
- inset: 0;
84
- z-index: 1;
85
- opacity: 0;
86
- animation-duration: 0.3s;
87
- animation-delay: 0;
88
- animation-timing-function: cubic-bezier(0.26, 0.53, 0.74, 1.48);
89
- animation-fill-mode: backwards;
90
- animation-name: animate-screenshot;
91
- animation-timing-function: ease;
92
- animation-fill-mode: forwards;
93
- background-color: white;
94
- }
95
-
96
- .box {
97
- border: 1px solid #B0CF34;
98
- position: absolute;
99
- border-radius: 5px;
100
- animation-duration: 5s;
101
- animation-delay: 0s;
102
- animation-timing-function: cubic-bezier(0.26, 0.53, 0.74, 1.48);
103
- animation-fill-mode: backwards;
104
- animation-name: animate-glow;
105
- animation-timing-function: ease;
106
- animation-fill-mode: forwards;
107
- border-radius: 5px;
108
- }
109
-
110
- .container {
111
- inset: 0;
112
- position: absolute;
113
- }
114
-
115
- #mouse {
116
- margin-left: -100px;
117
- margin-top: -100px;
118
- width: 50px;
119
- height: 50px;
120
- opacity: 50%;
121
- position: absolute;
122
- transform: translate(-50%, -50%);
123
- border-radius: 70%;
124
- background: #FFD700;
125
- }
126
-
127
- #mouse #dot {
128
- width: 7px;
129
- height: 7px;
130
- position: absolute;
131
- top: 50%;
132
- left: 50%;
133
- transform: translate(-50%, -50%);
134
- border-radius: 50%;
135
- background-color: black;
136
- }
137
-
138
- #pointer {
139
- width: 25px;
140
- height: 25px;
141
- opacity: 0;
142
- position: absolute;
143
- transform: translate(-50%, -50%);
144
- border-radius: 50%;
145
- background-color: #B0CF34;
146
- }
147
-
148
- .single-click {
149
- animation: singleClick 0.7s ease-in-out forwards;
150
- }
151
-
152
- .double-click {
153
- animation: doubleClick 0.7s ease-in-out forwards;
154
- }
155
-
156
- @keyframes singleClick {
157
- 0% {
158
- opacity: 1;
159
- transform: translate(-50%, -50%) scale(1);
128
+
129
+ #mouse #dot {
130
+ width: 7px;
131
+ height: 7px;
132
+ position: absolute;
133
+ top: 50%;
134
+ left: 50%;
135
+ transform: translate(-50%, -50%);
136
+ border-radius: 50%;
137
+ background-color: black;
160
138
  }
161
139
 
162
- 100% {
163
- opacity: 0;
164
- transform: translate(-50%, -50%) scale(2);
140
+ .single-click {
141
+ animation: singleClick 0.7s ease-in-out forwards;
165
142
  }
166
- }
167
143
 
168
- @keyframes doubleClick {
169
- 0% {
170
- opacity: 1;
171
- transform: translate(-50%, -50%) scale(1);
144
+ .double-click {
145
+ animation: doubleClick 0.7s ease-in-out forwards;
172
146
  }
173
147
 
174
- 45% {
175
- opacity: 0;
176
- transform: translate(-50%, -50%) scale(1.2);
148
+ @keyframes singleClick {
149
+ 0% {
150
+ opacity: 1;
151
+ transform: translate(-50%, -50%) scale(1);
152
+ }
153
+
154
+ 100% {
155
+ opacity: 0;
156
+ transform: translate(-50%, -50%) scale(2);
157
+ }
177
158
  }
178
159
 
179
- 55% {
180
- opacity: 1;
181
- transform: translate(-50%, -50%) scale(1);
160
+ @keyframes doubleClick {
161
+ 0% {
162
+ opacity: 1;
163
+ transform: translate(-50%, -50%) scale(1);
164
+ }
165
+
166
+ 45% {
167
+ opacity: 0;
168
+ transform: translate(-50%, -50%) scale(1.2);
169
+ }
170
+
171
+ 55% {
172
+ opacity: 1;
173
+ transform: translate(-50%, -50%) scale(1);
174
+ }
175
+
176
+ 100% {
177
+ opacity: 0;
178
+ transform: scale(2);
179
+ }
182
180
  }
183
181
 
184
- 100% {
182
+ #terminal-wrapper {
183
+ position: absolute;
184
+ right: calc(100vw - 600px);
185
+ top: 0px;
186
+ height: 100vh;
187
+ width: 600px;
188
+ background: black;
185
189
  opacity: 0;
186
- transform: scale(2);
190
+ z-index: -1;
191
+ overflow-y: auto;
192
+ padding: 20px;
187
193
  }
188
- }
189
-
190
- #terminal-wrapper {
191
- position: absolute;
192
- right: calc(100vw - 600px);
193
- top: 0px;
194
- height: 100vh;
195
- width: 600px;
196
- background: black;
197
- opacity: 0;
198
- z-index: -1;
199
- overflow-y: auto;
200
- padding: 20px;
201
- }
202
-
203
- #terminal {
204
- width: 100%;
205
- height: 100%;
206
- overflow-y: auto;
207
- }
208
-
209
- #boxes {
210
- position: absolute;
211
- top: 0;
212
- left: 0;
213
- right: 0;
214
- bottom: 0;
215
- z-index: 2;
216
- }
217
-
218
- #vm-iframe {
219
- position: absolute;
220
- display: none;
221
- top: 0;
222
- left: 0;
223
- width: 100%;
224
- height: 100%;
225
- border: none;
226
- pointer-events: auto;
227
- }
228
- </style>
229
- <link rel="stylesheet" href="terminal/xterm.css" />
230
- <script src="terminal/xterm.js" type="text/javascript"></script>
231
- <script src="terminal/xterm-fit.js" type="text/javascript"></script>
232
- </head>
233
-
234
- <body>
235
-
236
- <div id="screenshot"></div>
237
- <div id="main" class="container">
238
- <div id="boxes">
239
- <div id="pointer"></div>
240
- <div id="mouse"><div id="dot"></div></div>
241
- </div>
242
- <div id="terminal-wrapper">
243
- <div id="terminal"></div>
244
- </div>
245
- </div>
246
- <iframe id="vm-iframe" frameborder="0"></iframe>
247
-
248
- <script>
249
194
 
250
- const { ipcRenderer } = require("electron");
251
- const { events } = require("../lib/events.js");
252
-
253
- const mouse = document.querySelector("#mouse");
254
- const pointer = document.querySelector("#pointer");
255
- const container = document.querySelector("#main");
256
- const screenshotElement = document.querySelector("#screenshot");
257
- const terminalElement = document.querySelector("#terminal");
195
+ #terminal {
196
+ width: 100%;
197
+ height: 100%;
198
+ overflow-y: auto;
199
+ }
258
200
 
259
- let boundingBoxesTimeout = null
201
+ #boxes {
202
+ position: absolute;
203
+ top: 0;
204
+ left: 0;
205
+ right: 0;
206
+ bottom: 0;
207
+ z-index: 2;
208
+ }
260
209
 
261
- let drawBoxes = (boxes) => {
210
+ #vm-iframe {
211
+ position: absolute;
212
+ display: none;
213
+ top: 0;
214
+ left: 0;
215
+ width: 100%;
216
+ height: 100%;
217
+ border: none;
218
+ pointer-events: auto;
219
+ }
220
+ </style>
221
+ <link rel="stylesheet" href="terminal/xterm.css" />
222
+ <script src="terminal/xterm.js" type="text/javascript"></script>
223
+ <script src="terminal/xterm-fit.js" type="text/javascript"></script>
224
+ </head>
225
+
226
+ <body>
227
+ <div id="screenshot"></div>
228
+ <div id="main" class="container">
229
+ <div id="boxes">
230
+ <div id="mouse"><div id="dot"></div></div>
231
+ </div>
232
+ <div id="terminal-wrapper">
233
+ <div id="terminal"></div>
234
+ </div>
235
+ </div>
236
+ <iframe id="vm-iframe" frameborder="0"></iframe>
237
+
238
+ <script>
239
+ const { ipcRenderer } = require("electron");
240
+ const { events } = require("../lib/events.js");
241
+
242
+ const mouse = document.querySelector("#mouse");
243
+ const container = document.querySelector("#main");
244
+ const screenshotElement = document.querySelector("#screenshot");
245
+ const terminalElement = document.querySelector("#terminal");
246
+
247
+ let boundingBoxesTimeout = null;
248
+
249
+ let drawBoxes = (boxes) => {
250
+ // Remove old boxes
251
+ document.querySelectorAll(".box").forEach((box) => {
252
+ box.remove();
253
+ });
254
+
255
+ // Update or Create boxes
256
+ boxes.forEach(({ x, y, width, height, color }) => {
257
+ const boxElement = document.createElement("div");
258
+ boxElement.setAttribute("class", "box");
259
+ boxElement.style.position = "absolute";
260
+ boxElement.style.top = toCss(y);
261
+ boxElement.style.left = toCss(x);
262
+ boxElement.style.width = toCss(width);
263
+ boxElement.style.height = toCss(height);
264
+ boxElement.style.borderRadius = "1px";
265
+ document.querySelector("#boxes").appendChild(boxElement);
266
+ });
267
+ };
268
+
269
+ ipcRenderer.on(events.screenCapture.start, (event, data) => {
270
+ if (data?.silent) return;
271
+ // Hide everything whlie the app takes the screenshot
272
+ container.style.opacity = 0;
273
+ });
262
274
 
263
- // Remove old boxes
264
- document.querySelectorAll(".box").forEach((box) => {
265
- box.remove()
275
+ ipcRenderer.on(events.screenCapture.error, (event, data) => {
276
+ if (data?.silent) return;
277
+ container.style.opacity = 1;
266
278
  });
267
279
 
268
- // Update or Create boxes
269
- boxes.forEach(({ x, y, width, height, color }) => {
280
+ ipcRenderer.on(events.screenCapture.end, (event, data) => {
281
+ if (data?.silent) return;
282
+ screenshotElement.classList.remove("screenshot");
283
+ // Force reflow
284
+ void screenshotElement.offsetWidth;
285
+ screenshotElement.classList.add("screenshot");
286
+ setTimeout(() => {
287
+ container.style.opacity = 1;
288
+ }, 2000);
289
+ });
290
+ ipcRenderer.on(events.mouseMove, (event, { x, y } = {}) => {
291
+ mouse.style.marginLeft = toCss(x);
292
+ mouse.style.marginTop = toCss(y);
293
+ });
270
294
 
271
- const boxElement = document.createElement("div");
272
- boxElement.setAttribute("class", "box");
273
- boxElement.style.position = "absolute";
274
- boxElement.style.top = toCss(y);
275
- boxElement.style.left = toCss(x);
276
- boxElement.style.width = toCss(width);
277
- boxElement.style.height = toCss(height);
278
- boxElement.style.borderRadius = "1px";
279
- document.querySelector("#boxes").appendChild(boxElement);
295
+ ipcRenderer.on(
296
+ events.mouseClick,
297
+ (event, { x, y, click = "single" } = {}) => {
298
+ mouse.style.marginLeft = toCss(x);
299
+ mouse.style.marginTop = toCss(y);
300
+ // Reset class so animation can restart
301
+ mouse.setAttribute("class", "");
302
+ // Force reflow
303
+ void mouse.offsetWidth;
304
+ mouse.classList.add(`${click}-click`);
305
+ },
306
+ );
307
+
308
+ ipcRenderer.on(events.matches.show, (event, closeMatches = []) => {
309
+ if (boundingBoxesTimeout) clearTimeout(boundingBoxesTimeout);
310
+ drawBoxes(closeMatches);
311
+ boundingBoxesTimeout = setTimeout(() => drawBoxes([]), 10000);
312
+ });
280
313
 
314
+ const toCss = (size) => {
315
+ if (typeof size === "number") {
316
+ return `${size}px`;
317
+ }
318
+ return size;
319
+ };
320
+
321
+ // Terminal
322
+ const terminal = new Terminal({
323
+ convertEol: true,
324
+ cursorInactiveStyle: "none",
325
+ scrollback: 9999999,
326
+ allowProposedApi: true,
327
+ fontSize: 14,
281
328
  });
282
- }
283
-
284
- ipcRenderer.on(events.screenCapture.start, (event, data) => {
285
- if (data?.silent) return
286
- // Hide everything whlie the app takes the screenshot
287
- container.style.opacity = 0;
288
- });
289
-
290
- ipcRenderer.on(events.screenCapture.error, (event, data) => {
291
- if (data?.silent) return
292
- container.style.opacity = 1
293
- });
294
-
295
- ipcRenderer.on(events.screenCapture.end, (event, data) => {
296
- if (data?.silent) return
297
- screenshotElement.classList.remove('screenshot');
298
- // Force reflow
299
- void screenshotElement.offsetWidth;
300
- screenshotElement.classList.add('screenshot');
301
- setTimeout(() => {
302
- container.style.opacity = 1
303
- }, 2000)
304
- });
305
- ipcRenderer.on(events.mouseMove,
306
- (event, { x, y } = {}) => {
307
329
 
308
- mouse.style.marginLeft = toCss(x);
309
- mouse.style.marginTop = toCss(y);
330
+ const fitAddon = new FitAddon.FitAddon();
331
+ terminal.loadAddon(fitAddon);
332
+ terminal.open(terminalElement);
333
+ fitAddon.fit();
310
334
 
311
- },
312
- );
335
+ ipcRenderer.on(events.vm.show, (event, data) => {
336
+ const iframe = document.querySelector("#vm-iframe");
337
+ iframe.style.display = "block";
338
+ iframe.src = data.url;
339
+ });
313
340
 
314
- ipcRenderer.on(events.mouseClick,
315
- (event, { x, y, click = "single" } = {}) => {
341
+ ipcRenderer.on(events.terminal.stdout, (event, data) =>
342
+ terminal.write(data),
343
+ );
316
344
 
317
- pointer.style.marginLeft = toCss(x);
318
- pointer.style.marginTop = toCss(y);
319
- pointer.setAttribute("class", "");
320
- // Force reflow
321
- void pointer.offsetWidth;
322
- pointer.classList.add(`${click}-click`);
323
- },
324
- );
325
-
326
- ipcRenderer.on(events.matches.show, (event, closeMatches = []) => {
327
- if (boundingBoxesTimeout) clearTimeout(boundingBoxesTimeout)
328
- drawBoxes(closeMatches)
329
- boundingBoxesTimeout = setTimeout(() => drawBoxes([]), 10000)
330
- });
331
-
332
- const toCss = (size) => {
333
- if (typeof size === "number") {
334
- return `${size}px`;
335
- }
336
- return size;
337
- };
338
-
339
- // Terminal
340
- const terminal = new Terminal({
341
- convertEol: true,
342
- cursorInactiveStyle: "none",
343
- scrollback: 9999999,
344
- allowProposedApi: true,
345
- fontSize: 14
346
- });
347
-
348
- const fitAddon = new FitAddon.FitAddon();
349
- terminal.loadAddon(fitAddon);
350
- terminal.open(terminalElement);
351
- fitAddon.fit();
352
-
353
- ipcRenderer.on(events.vm.show, (event, data) => {
354
- const iframe = document.querySelector("#vm-iframe");
355
- iframe.style.display = "block";
356
- iframe.src = data.url;
357
- });
358
-
359
- ipcRenderer.on(events.terminal.stdout, (event, data) =>
360
- terminal.write(data),
361
- );
362
-
363
- ipcRenderer.on(events.terminal.stderr, (event, data) =>
364
- terminal.write(data),
365
- );
366
-
367
- ipcRenderer.on(events.interactive, (event, data) => {
368
- if (data) {
369
- terminalElement.parentElement.style.opacity = "0"
370
- } else {
371
- terminalElement.parentElement.style.opacity = "0.8"
372
- }
373
- });
374
- </script>
375
- </body>
345
+ ipcRenderer.on(events.terminal.stderr, (event, data) =>
346
+ terminal.write(data),
347
+ );
376
348
 
349
+ ipcRenderer.on(events.interactive, (event, data) => {
350
+ if (data) {
351
+ terminalElement.parentElement.style.opacity = "0";
352
+ } else {
353
+ terminalElement.parentElement.style.opacity = "0.8";
354
+ }
355
+ });
356
+ </script>
357
+ </body>
377
358
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testdriverai",
3
- "version": "5.7.37",
3
+ "version": "5.7.39",
4
4
  "description": "Next generation autonomous AI agent for end-to-end testing of web & desktop",
5
5
  "main": "index.js",
6
6
  "bin": {