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.
- package/.github/workflows/{format.yml → lint.yml} +3 -0
- package/.github/workflows/{testdriver.yml → publish-acceptance-tests.yml} +24 -4
- package/.github/workflows/{npm-publish.yml → publish-latest.yml} +6 -4
- package/.github/workflows/test-install.yml +3 -7
- package/electron/overlay.html +312 -331
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
11
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
|
32
|
+
run: testdriverai --help
|
package/electron/overlay.html
CHANGED
|
@@ -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
|
-
|
|
5
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
77
|
+
body {
|
|
78
|
+
width: 100vw;
|
|
79
|
+
height: 100vh;
|
|
80
|
+
position: relative;
|
|
51
81
|
}
|
|
52
82
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
|
|
112
|
+
.container {
|
|
113
|
+
inset: 0;
|
|
114
|
+
position: absolute;
|
|
67
115
|
}
|
|
68
116
|
|
|
69
|
-
|
|
117
|
+
#mouse {
|
|
118
|
+
margin-left: -100px;
|
|
119
|
+
margin-top: -100px;
|
|
120
|
+
width: 50px;
|
|
121
|
+
height: 50px;
|
|
70
122
|
opacity: 0;
|
|
71
|
-
|
|
123
|
+
position: absolute;
|
|
124
|
+
transform: translate(-50%, -50%);
|
|
125
|
+
border-radius: 70%;
|
|
126
|
+
background: #b0cf34;
|
|
72
127
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
-
|
|
163
|
-
|
|
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
|
-
|
|
169
|
-
|
|
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
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
264
|
-
|
|
265
|
-
|
|
275
|
+
ipcRenderer.on(events.screenCapture.error, (event, data) => {
|
|
276
|
+
if (data?.silent) return;
|
|
277
|
+
container.style.opacity = 1;
|
|
266
278
|
});
|
|
267
279
|
|
|
268
|
-
|
|
269
|
-
|
|
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
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
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
|
-
|
|
309
|
-
|
|
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
|
-
|
|
315
|
-
|
|
341
|
+
ipcRenderer.on(events.terminal.stdout, (event, data) =>
|
|
342
|
+
terminal.write(data),
|
|
343
|
+
);
|
|
316
344
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
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>
|