@intuned/runtime-dev 1.3.15-hook.0 → 1.3.15-ts-helpers
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/dist/commands/intuned-cli/commands/run_authsession.command.d.ts +6 -6
- package/dist/commands/intuned-cli/commands/types.d.ts +2 -2
- package/dist/commands/intuned-cli/controller/authSession.d.ts +6 -6
- package/dist/commands/intuned-cli/helpers/auth.d.ts +1 -1
- package/dist/common/{extensionsHelpers.d.ts → extension/extensionsHelpers.d.ts} +1 -1
- package/dist/common/{extensionsHelpers.js → extension/extensionsHelpers.js} +47 -6
- package/dist/common/extension/intunedExtensionServer.d.ts +27 -0
- package/dist/common/extension/intunedExtensionServer.js +181 -0
- package/dist/common/extension/types.d.ts +212 -0
- package/dist/common/extension/types.js +51 -0
- package/dist/common/launchBrowser.js +3 -1
- package/dist/common/playwrightContext.js +1 -1
- package/dist/common/runApi/types.d.ts +20 -20
- package/dist/common/settingsSchema.d.ts +15 -1
- package/dist/common/settingsSchema.js +1 -0
- package/dist/common/setupContextHook.d.ts +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +50 -1
- package/dist/runtime/captcha.d.ts +15 -0
- package/dist/runtime/captcha.js +177 -0
- package/dist/runtime/captcha.test.js +821 -0
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.js +43 -0
- package/package.json +2 -1
- package/WebTemplate.zip +0 -0
|
@@ -0,0 +1,821 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _vitest = require("vitest");
|
|
4
|
+
var _intunedExtensionServer = require("../common/extension/intunedExtensionServer");
|
|
5
|
+
var _captcha = require("./captcha");
|
|
6
|
+
_vitest.vi.mock("fastify", () => {
|
|
7
|
+
const fastify = () => ({
|
|
8
|
+
post: _vitest.vi.fn(),
|
|
9
|
+
setNotFoundHandler: _vitest.vi.fn(),
|
|
10
|
+
listen: _vitest.vi.fn(async () => undefined),
|
|
11
|
+
close: _vitest.vi.fn(async () => undefined)
|
|
12
|
+
});
|
|
13
|
+
return {
|
|
14
|
+
default: fastify
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
let server;
|
|
18
|
+
_vitest.vi.mock("../common/extension/intunedExtensionServer", async importOriginal => {
|
|
19
|
+
const actual = await importOriginal();
|
|
20
|
+
return {
|
|
21
|
+
...actual,
|
|
22
|
+
getIntunedExtensionServer: () => server,
|
|
23
|
+
getTabId: _vitest.vi.fn(async () => 0)
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
function makeMockPage() {
|
|
27
|
+
return {
|
|
28
|
+
waitForLoadState: _vitest.vi.fn().mockResolvedValue(undefined),
|
|
29
|
+
waitForFunction: _vitest.vi.fn().mockResolvedValue(undefined),
|
|
30
|
+
evaluate: _vitest.vi.fn().mockResolvedValue(0)
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
async function runCaptchaTestScenario({
|
|
34
|
+
page,
|
|
35
|
+
mockStates,
|
|
36
|
+
timeoutMs = 10000,
|
|
37
|
+
settleDurationMs = 100,
|
|
38
|
+
expectErrorCode,
|
|
39
|
+
expectTimeout = false
|
|
40
|
+
}) {
|
|
41
|
+
for (const state of mockStates) {
|
|
42
|
+
await server.handleUpsertCaptcha(state.initial);
|
|
43
|
+
}
|
|
44
|
+
const allTransitions = [];
|
|
45
|
+
for (const state of mockStates) {
|
|
46
|
+
for (const transition of state.transitions) {
|
|
47
|
+
allTransitions.push({
|
|
48
|
+
timeMs: transition.timeMs,
|
|
49
|
+
captchaId: state.initial.id,
|
|
50
|
+
type: state.initial.type,
|
|
51
|
+
status: transition.status,
|
|
52
|
+
errorCode: transition.errorCode
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
allTransitions.sort((a, b) => a.timeMs - b.timeMs);
|
|
57
|
+
const p = (0, _captcha.waitForCaptchaSolve)(page, {
|
|
58
|
+
timeoutInMs: timeoutMs,
|
|
59
|
+
settleDurationMs
|
|
60
|
+
});
|
|
61
|
+
let assertion;
|
|
62
|
+
if (expectErrorCode) {
|
|
63
|
+
assertion = (0, _vitest.expect)(p).rejects.toThrow(`CAPTCHA Solve Error: ${expectErrorCode}`);
|
|
64
|
+
} else if (expectTimeout) {
|
|
65
|
+
assertion = (0, _vitest.expect)(p).rejects.toThrow("CAPTCHA Solve timed out with pending captchas.");
|
|
66
|
+
}
|
|
67
|
+
await _vitest.vi.advanceTimersByTimeAsync(0);
|
|
68
|
+
let currentTimeMs = 0;
|
|
69
|
+
for (const transition of allTransitions) {
|
|
70
|
+
const deltaMs = transition.timeMs - currentTimeMs;
|
|
71
|
+
if (deltaMs > 0) {
|
|
72
|
+
await _vitest.vi.advanceTimersByTimeAsync(deltaMs);
|
|
73
|
+
currentTimeMs = transition.timeMs;
|
|
74
|
+
}
|
|
75
|
+
const captcha = transition.status === "error" && transition.errorCode ? {
|
|
76
|
+
id: transition.captchaId,
|
|
77
|
+
tabId: 0,
|
|
78
|
+
type: transition.type,
|
|
79
|
+
status: "error",
|
|
80
|
+
error: {
|
|
81
|
+
code: transition.errorCode
|
|
82
|
+
}
|
|
83
|
+
} : {
|
|
84
|
+
id: transition.captchaId,
|
|
85
|
+
tabId: 0,
|
|
86
|
+
type: transition.type,
|
|
87
|
+
status: transition.status
|
|
88
|
+
};
|
|
89
|
+
await server.handleUpsertCaptcha(captcha);
|
|
90
|
+
}
|
|
91
|
+
await _vitest.vi.advanceTimersByTimeAsync(settleDurationMs + 10);
|
|
92
|
+
if (expectTimeout || expectErrorCode) {
|
|
93
|
+
await _vitest.vi.advanceTimersByTimeAsync(timeoutMs + settleDurationMs);
|
|
94
|
+
}
|
|
95
|
+
if (assertion) {
|
|
96
|
+
await assertion;
|
|
97
|
+
} else {
|
|
98
|
+
await (0, _vitest.expect)(p).resolves.toBeUndefined();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
(0, _vitest.beforeEach)(() => {
|
|
102
|
+
_vitest.vi.useFakeTimers();
|
|
103
|
+
server = new _intunedExtensionServer.ExtensionServer();
|
|
104
|
+
});
|
|
105
|
+
(0, _vitest.afterEach)(() => {
|
|
106
|
+
_vitest.vi.useRealTimers();
|
|
107
|
+
_vitest.vi.restoreAllMocks();
|
|
108
|
+
});
|
|
109
|
+
(0, _vitest.describe)("runtime/captcha", () => {
|
|
110
|
+
(0, _vitest.it)("waitForCaptchaSolve: resolves after settle period when no captchas are present", async () => {
|
|
111
|
+
const page = makeMockPage();
|
|
112
|
+
const p = (0, _captcha.waitForCaptchaSolve)(page, {
|
|
113
|
+
timeoutInMs: 1000,
|
|
114
|
+
settleDurationMs: 10
|
|
115
|
+
});
|
|
116
|
+
await _vitest.vi.advanceTimersByTimeAsync(10);
|
|
117
|
+
await p;
|
|
118
|
+
(0, _vitest.expect)(page.waitForLoadState).not.toHaveBeenCalled();
|
|
119
|
+
});
|
|
120
|
+
(0, _vitest.it)("withWaitForCaptchaSolve: preserves return value and waits for networkidle by default", async () => {
|
|
121
|
+
const page = makeMockPage();
|
|
122
|
+
const p = (0, _captcha.withWaitForCaptchaSolve)(async () => "ok", {
|
|
123
|
+
page,
|
|
124
|
+
timeoutInMs: 1000,
|
|
125
|
+
settleDurationMs: 10
|
|
126
|
+
});
|
|
127
|
+
await _vitest.vi.advanceTimersByTimeAsync(10);
|
|
128
|
+
await (0, _vitest.expect)(p).resolves.toBe("ok");
|
|
129
|
+
(0, _vitest.expect)(page.waitForLoadState).toHaveBeenCalledWith("networkidle");
|
|
130
|
+
});
|
|
131
|
+
(0, _vitest.it)("withWaitForCaptchaSolve: skips networkidle when disabled", async () => {
|
|
132
|
+
const page = makeMockPage();
|
|
133
|
+
const p = (0, _captcha.withWaitForCaptchaSolve)(async () => "ok", {
|
|
134
|
+
page,
|
|
135
|
+
timeoutInMs: 1000,
|
|
136
|
+
settleDurationMs: 10,
|
|
137
|
+
waitForNetworkSettled: false
|
|
138
|
+
});
|
|
139
|
+
await _vitest.vi.advanceTimersByTimeAsync(10);
|
|
140
|
+
await (0, _vitest.expect)(p).resolves.toBe("ok");
|
|
141
|
+
(0, _vitest.expect)(page.waitForLoadState).not.toHaveBeenCalled();
|
|
142
|
+
});
|
|
143
|
+
(0, _vitest.it)("waitForCaptchaSolve: completes when a solving captcha becomes solved", async () => {
|
|
144
|
+
const page = makeMockPage();
|
|
145
|
+
await server.handleUpsertCaptcha({
|
|
146
|
+
id: "c1",
|
|
147
|
+
tabId: 0,
|
|
148
|
+
type: "recaptcha",
|
|
149
|
+
status: "solving",
|
|
150
|
+
retryCount: 0
|
|
151
|
+
});
|
|
152
|
+
const p = (0, _captcha.waitForCaptchaSolve)(page, {
|
|
153
|
+
timeoutInMs: 1000,
|
|
154
|
+
settleDurationMs: 10
|
|
155
|
+
});
|
|
156
|
+
await Promise.resolve();
|
|
157
|
+
await server.handleUpsertCaptcha({
|
|
158
|
+
id: "c1",
|
|
159
|
+
tabId: 0,
|
|
160
|
+
type: "recaptcha",
|
|
161
|
+
status: "solved",
|
|
162
|
+
retryCount: 0
|
|
163
|
+
});
|
|
164
|
+
await _vitest.vi.advanceTimersByTimeAsync(10);
|
|
165
|
+
await (0, _vitest.expect)(p).resolves.toBeUndefined();
|
|
166
|
+
});
|
|
167
|
+
(0, _vitest.it)("waitForCaptchaSolve: throws on captcha error", async () => {
|
|
168
|
+
const page = makeMockPage();
|
|
169
|
+
await server.handleUpsertCaptcha({
|
|
170
|
+
id: "c1",
|
|
171
|
+
tabId: 0,
|
|
172
|
+
type: "recaptcha",
|
|
173
|
+
status: "solving",
|
|
174
|
+
retryCount: 0
|
|
175
|
+
});
|
|
176
|
+
const p = (0, _captcha.waitForCaptchaSolve)(page, {
|
|
177
|
+
timeoutInMs: 1000,
|
|
178
|
+
settleDurationMs: 10
|
|
179
|
+
});
|
|
180
|
+
const assertion = (0, _vitest.expect)(p).rejects.toThrow("CAPTCHA Solve Error: UNEXPECTED_ERROR");
|
|
181
|
+
await _vitest.vi.advanceTimersByTimeAsync(0);
|
|
182
|
+
await server.handleUpsertCaptcha({
|
|
183
|
+
id: "c1",
|
|
184
|
+
tabId: 0,
|
|
185
|
+
type: "recaptcha",
|
|
186
|
+
status: "error",
|
|
187
|
+
retryCount: 0,
|
|
188
|
+
error: {
|
|
189
|
+
code: "UNEXPECTED_ERROR"
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
await _vitest.vi.advanceTimersByTimeAsync(10);
|
|
193
|
+
await assertion;
|
|
194
|
+
});
|
|
195
|
+
(0, _vitest.it)("waitForCaptchaSolve: times out if captchas are still pending", async () => {
|
|
196
|
+
const page = makeMockPage();
|
|
197
|
+
await server.handleUpsertCaptcha({
|
|
198
|
+
id: "c1",
|
|
199
|
+
tabId: 0,
|
|
200
|
+
type: "recaptcha",
|
|
201
|
+
status: "solving",
|
|
202
|
+
retryCount: 0
|
|
203
|
+
});
|
|
204
|
+
const p = (0, _captcha.waitForCaptchaSolve)(page, {
|
|
205
|
+
timeoutInMs: 5,
|
|
206
|
+
settleDurationMs: 1
|
|
207
|
+
});
|
|
208
|
+
const assertion = (0, _vitest.expect)(p).rejects.toThrow("CAPTCHA Solve timed out with pending captchas.");
|
|
209
|
+
await Promise.resolve();
|
|
210
|
+
await _vitest.vi.advanceTimersByTimeAsync(6);
|
|
211
|
+
await _vitest.vi.advanceTimersByTimeAsync(1);
|
|
212
|
+
await assertion;
|
|
213
|
+
});
|
|
214
|
+
(0, _vitest.it)("waitForCaptchaSolve: waits for all captchas to resolve", async () => {
|
|
215
|
+
const page = makeMockPage();
|
|
216
|
+
await server.handleUpsertCaptcha({
|
|
217
|
+
id: "c1",
|
|
218
|
+
tabId: 0,
|
|
219
|
+
type: "recaptcha",
|
|
220
|
+
status: "solving",
|
|
221
|
+
retryCount: 0
|
|
222
|
+
});
|
|
223
|
+
await server.handleUpsertCaptcha({
|
|
224
|
+
id: "c2",
|
|
225
|
+
tabId: 0,
|
|
226
|
+
type: "hcaptcha",
|
|
227
|
+
status: "solving",
|
|
228
|
+
retryCount: 0
|
|
229
|
+
});
|
|
230
|
+
const p = (0, _captcha.waitForCaptchaSolve)(page, {
|
|
231
|
+
timeoutInMs: 1000,
|
|
232
|
+
settleDurationMs: 10
|
|
233
|
+
});
|
|
234
|
+
await Promise.resolve();
|
|
235
|
+
await server.handleUpsertCaptcha({
|
|
236
|
+
id: "c1",
|
|
237
|
+
tabId: 0,
|
|
238
|
+
type: "recaptcha",
|
|
239
|
+
status: "solved",
|
|
240
|
+
retryCount: 0
|
|
241
|
+
});
|
|
242
|
+
await _vitest.vi.advanceTimersByTimeAsync(10);
|
|
243
|
+
let settled = false;
|
|
244
|
+
p.then(() => settled = true).catch(() => settled = true);
|
|
245
|
+
await Promise.resolve();
|
|
246
|
+
(0, _vitest.expect)(settled).toBe(false);
|
|
247
|
+
await server.handleUpsertCaptcha({
|
|
248
|
+
id: "c2",
|
|
249
|
+
tabId: 0,
|
|
250
|
+
type: "hcaptcha",
|
|
251
|
+
status: "detached",
|
|
252
|
+
retryCount: 0
|
|
253
|
+
});
|
|
254
|
+
await _vitest.vi.advanceTimersByTimeAsync(10);
|
|
255
|
+
await (0, _vitest.expect)(p).resolves.toBeUndefined();
|
|
256
|
+
});
|
|
257
|
+
(0, _vitest.describe)("captchaStateTransitions", () => {
|
|
258
|
+
(0, _vitest.it)("captcha detached completes successfully", async () => {
|
|
259
|
+
const page = makeMockPage();
|
|
260
|
+
await runCaptchaTestScenario({
|
|
261
|
+
page,
|
|
262
|
+
mockStates: [{
|
|
263
|
+
initial: {
|
|
264
|
+
id: "test1",
|
|
265
|
+
tabId: 0,
|
|
266
|
+
type: "recaptcha",
|
|
267
|
+
status: "solving"
|
|
268
|
+
},
|
|
269
|
+
transitions: [{
|
|
270
|
+
timeMs: 100,
|
|
271
|
+
status: "detached"
|
|
272
|
+
}]
|
|
273
|
+
}],
|
|
274
|
+
settleDurationMs: 100
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
(0, _vitest.it)("attached to solving to solved", async () => {
|
|
278
|
+
const page = makeMockPage();
|
|
279
|
+
await runCaptchaTestScenario({
|
|
280
|
+
page,
|
|
281
|
+
mockStates: [{
|
|
282
|
+
initial: {
|
|
283
|
+
id: "captcha1",
|
|
284
|
+
tabId: 0,
|
|
285
|
+
type: "recaptcha",
|
|
286
|
+
status: "attached"
|
|
287
|
+
},
|
|
288
|
+
transitions: [{
|
|
289
|
+
timeMs: 50,
|
|
290
|
+
status: "solving"
|
|
291
|
+
}, {
|
|
292
|
+
timeMs: 350,
|
|
293
|
+
status: "solved"
|
|
294
|
+
}]
|
|
295
|
+
}],
|
|
296
|
+
settleDurationMs: 100
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
(0, _vitest.it)("attached to detached", async () => {
|
|
300
|
+
const page = makeMockPage();
|
|
301
|
+
await runCaptchaTestScenario({
|
|
302
|
+
page,
|
|
303
|
+
mockStates: [{
|
|
304
|
+
initial: {
|
|
305
|
+
id: "captcha1",
|
|
306
|
+
tabId: 0,
|
|
307
|
+
type: "recaptcha",
|
|
308
|
+
status: "attached"
|
|
309
|
+
},
|
|
310
|
+
transitions: [{
|
|
311
|
+
timeMs: 100,
|
|
312
|
+
status: "detached"
|
|
313
|
+
}]
|
|
314
|
+
}],
|
|
315
|
+
settleDurationMs: 100
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
(0, _vitest.it)("attached to solving to error", async () => {
|
|
319
|
+
const page = makeMockPage();
|
|
320
|
+
await runCaptchaTestScenario({
|
|
321
|
+
page,
|
|
322
|
+
mockStates: [{
|
|
323
|
+
initial: {
|
|
324
|
+
id: "captcha1",
|
|
325
|
+
tabId: 0,
|
|
326
|
+
type: "recaptcha",
|
|
327
|
+
status: "attached"
|
|
328
|
+
},
|
|
329
|
+
transitions: [{
|
|
330
|
+
timeMs: 50,
|
|
331
|
+
status: "solving"
|
|
332
|
+
}, {
|
|
333
|
+
timeMs: 550,
|
|
334
|
+
status: "error",
|
|
335
|
+
errorCode: "UNEXPECTED_ERROR"
|
|
336
|
+
}]
|
|
337
|
+
}],
|
|
338
|
+
settleDurationMs: 100,
|
|
339
|
+
expectErrorCode: "UNEXPECTED_ERROR"
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
(0, _vitest.it)("attached to solving to detached", async () => {
|
|
343
|
+
const page = makeMockPage();
|
|
344
|
+
await runCaptchaTestScenario({
|
|
345
|
+
page,
|
|
346
|
+
mockStates: [{
|
|
347
|
+
initial: {
|
|
348
|
+
id: "captcha1",
|
|
349
|
+
tabId: 0,
|
|
350
|
+
type: "recaptcha",
|
|
351
|
+
status: "attached"
|
|
352
|
+
},
|
|
353
|
+
transitions: [{
|
|
354
|
+
timeMs: 50,
|
|
355
|
+
status: "solving"
|
|
356
|
+
}, {
|
|
357
|
+
timeMs: 200,
|
|
358
|
+
status: "detached"
|
|
359
|
+
}]
|
|
360
|
+
}],
|
|
361
|
+
settleDurationMs: 100
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
(0, _vitest.it)("visibility toggle then solved", async () => {
|
|
365
|
+
const page = makeMockPage();
|
|
366
|
+
await runCaptchaTestScenario({
|
|
367
|
+
page,
|
|
368
|
+
mockStates: [{
|
|
369
|
+
initial: {
|
|
370
|
+
id: "captcha1",
|
|
371
|
+
tabId: 0,
|
|
372
|
+
type: "recaptcha",
|
|
373
|
+
status: "attached"
|
|
374
|
+
},
|
|
375
|
+
transitions: [{
|
|
376
|
+
timeMs: 50,
|
|
377
|
+
status: "solving"
|
|
378
|
+
}, {
|
|
379
|
+
timeMs: 100,
|
|
380
|
+
status: "attached"
|
|
381
|
+
}, {
|
|
382
|
+
timeMs: 120,
|
|
383
|
+
status: "solving"
|
|
384
|
+
}, {
|
|
385
|
+
timeMs: 420,
|
|
386
|
+
status: "solved"
|
|
387
|
+
}]
|
|
388
|
+
}],
|
|
389
|
+
settleDurationMs: 100
|
|
390
|
+
});
|
|
391
|
+
});
|
|
392
|
+
(0, _vitest.it)("visibility toggle then error", async () => {
|
|
393
|
+
const page = makeMockPage();
|
|
394
|
+
await runCaptchaTestScenario({
|
|
395
|
+
page,
|
|
396
|
+
mockStates: [{
|
|
397
|
+
initial: {
|
|
398
|
+
id: "captcha1",
|
|
399
|
+
tabId: 0,
|
|
400
|
+
type: "recaptcha",
|
|
401
|
+
status: "attached"
|
|
402
|
+
},
|
|
403
|
+
transitions: [{
|
|
404
|
+
timeMs: 50,
|
|
405
|
+
status: "solving"
|
|
406
|
+
}, {
|
|
407
|
+
timeMs: 100,
|
|
408
|
+
status: "attached"
|
|
409
|
+
}, {
|
|
410
|
+
timeMs: 120,
|
|
411
|
+
status: "solving"
|
|
412
|
+
}, {
|
|
413
|
+
timeMs: 620,
|
|
414
|
+
status: "error",
|
|
415
|
+
errorCode: "MAX_RETRIES"
|
|
416
|
+
}]
|
|
417
|
+
}],
|
|
418
|
+
settleDurationMs: 100,
|
|
419
|
+
expectErrorCode: "MAX_RETRIES"
|
|
420
|
+
});
|
|
421
|
+
});
|
|
422
|
+
(0, _vitest.it)("visibility toggle then detached", async () => {
|
|
423
|
+
const page = makeMockPage();
|
|
424
|
+
await runCaptchaTestScenario({
|
|
425
|
+
page,
|
|
426
|
+
mockStates: [{
|
|
427
|
+
initial: {
|
|
428
|
+
id: "captcha1",
|
|
429
|
+
tabId: 0,
|
|
430
|
+
type: "recaptcha",
|
|
431
|
+
status: "attached"
|
|
432
|
+
},
|
|
433
|
+
transitions: [{
|
|
434
|
+
timeMs: 50,
|
|
435
|
+
status: "solving"
|
|
436
|
+
}, {
|
|
437
|
+
timeMs: 100,
|
|
438
|
+
status: "attached"
|
|
439
|
+
}, {
|
|
440
|
+
timeMs: 110,
|
|
441
|
+
status: "detached"
|
|
442
|
+
}]
|
|
443
|
+
}],
|
|
444
|
+
settleDurationMs: 100
|
|
445
|
+
});
|
|
446
|
+
});
|
|
447
|
+
(0, _vitest.it)("visibility toggle solving then detached", async () => {
|
|
448
|
+
const page = makeMockPage();
|
|
449
|
+
await runCaptchaTestScenario({
|
|
450
|
+
page,
|
|
451
|
+
mockStates: [{
|
|
452
|
+
initial: {
|
|
453
|
+
id: "captcha1",
|
|
454
|
+
tabId: 0,
|
|
455
|
+
type: "recaptcha",
|
|
456
|
+
status: "attached"
|
|
457
|
+
},
|
|
458
|
+
transitions: [{
|
|
459
|
+
timeMs: 50,
|
|
460
|
+
status: "solving"
|
|
461
|
+
}, {
|
|
462
|
+
timeMs: 100,
|
|
463
|
+
status: "attached"
|
|
464
|
+
}, {
|
|
465
|
+
timeMs: 120,
|
|
466
|
+
status: "solving"
|
|
467
|
+
}, {
|
|
468
|
+
timeMs: 270,
|
|
469
|
+
status: "detached"
|
|
470
|
+
}]
|
|
471
|
+
}],
|
|
472
|
+
settleDurationMs: 100
|
|
473
|
+
});
|
|
474
|
+
});
|
|
475
|
+
(0, _vitest.it)("rapid visibility toggle then solved", async () => {
|
|
476
|
+
const page = makeMockPage();
|
|
477
|
+
await runCaptchaTestScenario({
|
|
478
|
+
page,
|
|
479
|
+
mockStates: [{
|
|
480
|
+
initial: {
|
|
481
|
+
id: "captcha1",
|
|
482
|
+
tabId: 0,
|
|
483
|
+
type: "recaptcha",
|
|
484
|
+
status: "attached"
|
|
485
|
+
},
|
|
486
|
+
transitions: [{
|
|
487
|
+
timeMs: 50,
|
|
488
|
+
status: "solving"
|
|
489
|
+
}, {
|
|
490
|
+
timeMs: 60,
|
|
491
|
+
status: "attached"
|
|
492
|
+
}, {
|
|
493
|
+
timeMs: 65,
|
|
494
|
+
status: "solving"
|
|
495
|
+
}, {
|
|
496
|
+
timeMs: 75,
|
|
497
|
+
status: "attached"
|
|
498
|
+
}, {
|
|
499
|
+
timeMs: 80,
|
|
500
|
+
status: "solving"
|
|
501
|
+
}, {
|
|
502
|
+
timeMs: 380,
|
|
503
|
+
status: "solved"
|
|
504
|
+
}]
|
|
505
|
+
}],
|
|
506
|
+
settleDurationMs: 100
|
|
507
|
+
});
|
|
508
|
+
});
|
|
509
|
+
(0, _vitest.it)("rapid visibility toggle then detached", async () => {
|
|
510
|
+
const page = makeMockPage();
|
|
511
|
+
await runCaptchaTestScenario({
|
|
512
|
+
page,
|
|
513
|
+
mockStates: [{
|
|
514
|
+
initial: {
|
|
515
|
+
id: "captcha1",
|
|
516
|
+
tabId: 0,
|
|
517
|
+
type: "recaptcha",
|
|
518
|
+
status: "attached"
|
|
519
|
+
},
|
|
520
|
+
transitions: [{
|
|
521
|
+
timeMs: 50,
|
|
522
|
+
status: "solving"
|
|
523
|
+
}, {
|
|
524
|
+
timeMs: 60,
|
|
525
|
+
status: "attached"
|
|
526
|
+
}, {
|
|
527
|
+
timeMs: 65,
|
|
528
|
+
status: "solving"
|
|
529
|
+
}, {
|
|
530
|
+
timeMs: 75,
|
|
531
|
+
status: "attached"
|
|
532
|
+
}, {
|
|
533
|
+
timeMs: 80,
|
|
534
|
+
status: "detached"
|
|
535
|
+
}]
|
|
536
|
+
}],
|
|
537
|
+
settleDurationMs: 100
|
|
538
|
+
});
|
|
539
|
+
});
|
|
540
|
+
(0, _vitest.it)("instant toggles then solved", async () => {
|
|
541
|
+
const page = makeMockPage();
|
|
542
|
+
await runCaptchaTestScenario({
|
|
543
|
+
page,
|
|
544
|
+
mockStates: [{
|
|
545
|
+
initial: {
|
|
546
|
+
id: "captcha1",
|
|
547
|
+
tabId: 0,
|
|
548
|
+
type: "recaptcha",
|
|
549
|
+
status: "attached"
|
|
550
|
+
},
|
|
551
|
+
transitions: [{
|
|
552
|
+
timeMs: 1,
|
|
553
|
+
status: "solving"
|
|
554
|
+
}, {
|
|
555
|
+
timeMs: 2,
|
|
556
|
+
status: "attached"
|
|
557
|
+
}, {
|
|
558
|
+
timeMs: 3,
|
|
559
|
+
status: "solving"
|
|
560
|
+
}, {
|
|
561
|
+
timeMs: 300,
|
|
562
|
+
status: "solved"
|
|
563
|
+
}]
|
|
564
|
+
}],
|
|
565
|
+
settleDurationMs: 100
|
|
566
|
+
});
|
|
567
|
+
});
|
|
568
|
+
(0, _vitest.it)("long solving timeout", async () => {
|
|
569
|
+
const page = makeMockPage();
|
|
570
|
+
await runCaptchaTestScenario({
|
|
571
|
+
page,
|
|
572
|
+
mockStates: [{
|
|
573
|
+
initial: {
|
|
574
|
+
id: "captcha1",
|
|
575
|
+
tabId: 0,
|
|
576
|
+
type: "recaptcha",
|
|
577
|
+
status: "attached"
|
|
578
|
+
},
|
|
579
|
+
transitions: [{
|
|
580
|
+
timeMs: 10,
|
|
581
|
+
status: "solving"
|
|
582
|
+
}, {
|
|
583
|
+
timeMs: 30000,
|
|
584
|
+
status: "error",
|
|
585
|
+
errorCode: "UNEXPECTED_ERROR"
|
|
586
|
+
}]
|
|
587
|
+
}],
|
|
588
|
+
timeoutMs: 10000,
|
|
589
|
+
settleDurationMs: 3000,
|
|
590
|
+
expectTimeout: true
|
|
591
|
+
});
|
|
592
|
+
});
|
|
593
|
+
(0, _vitest.it)("multiple captchas both solve", async () => {
|
|
594
|
+
const page = makeMockPage();
|
|
595
|
+
await runCaptchaTestScenario({
|
|
596
|
+
page,
|
|
597
|
+
mockStates: [{
|
|
598
|
+
initial: {
|
|
599
|
+
id: "captcha1",
|
|
600
|
+
tabId: 0,
|
|
601
|
+
type: "recaptcha",
|
|
602
|
+
status: "solving"
|
|
603
|
+
},
|
|
604
|
+
transitions: [{
|
|
605
|
+
timeMs: 100,
|
|
606
|
+
status: "solved"
|
|
607
|
+
}]
|
|
608
|
+
}, {
|
|
609
|
+
initial: {
|
|
610
|
+
id: "captcha2",
|
|
611
|
+
tabId: 0,
|
|
612
|
+
type: "hcaptcha",
|
|
613
|
+
status: "solving"
|
|
614
|
+
},
|
|
615
|
+
transitions: [{
|
|
616
|
+
timeMs: 200,
|
|
617
|
+
status: "solved"
|
|
618
|
+
}]
|
|
619
|
+
}],
|
|
620
|
+
settleDurationMs: 100
|
|
621
|
+
});
|
|
622
|
+
});
|
|
623
|
+
(0, _vitest.it)("multiple captchas one errors", async () => {
|
|
624
|
+
const page = makeMockPage();
|
|
625
|
+
await runCaptchaTestScenario({
|
|
626
|
+
page,
|
|
627
|
+
mockStates: [{
|
|
628
|
+
initial: {
|
|
629
|
+
id: "captcha1",
|
|
630
|
+
tabId: 0,
|
|
631
|
+
type: "recaptcha",
|
|
632
|
+
status: "solving"
|
|
633
|
+
},
|
|
634
|
+
transitions: []
|
|
635
|
+
}, {
|
|
636
|
+
initial: {
|
|
637
|
+
id: "captcha2",
|
|
638
|
+
tabId: 0,
|
|
639
|
+
type: "hcaptcha",
|
|
640
|
+
status: "solving"
|
|
641
|
+
},
|
|
642
|
+
transitions: [{
|
|
643
|
+
timeMs: 100,
|
|
644
|
+
status: "error",
|
|
645
|
+
errorCode: "HIT_LIMIT"
|
|
646
|
+
}]
|
|
647
|
+
}],
|
|
648
|
+
settleDurationMs: 100,
|
|
649
|
+
expectErrorCode: "HIT_LIMIT"
|
|
650
|
+
});
|
|
651
|
+
});
|
|
652
|
+
(0, _vitest.it)("staggered captcha resolution", async () => {
|
|
653
|
+
const page = makeMockPage();
|
|
654
|
+
await runCaptchaTestScenario({
|
|
655
|
+
page,
|
|
656
|
+
mockStates: [{
|
|
657
|
+
initial: {
|
|
658
|
+
id: "captcha1",
|
|
659
|
+
tabId: 0,
|
|
660
|
+
type: "recaptcha",
|
|
661
|
+
status: "solving"
|
|
662
|
+
},
|
|
663
|
+
transitions: [{
|
|
664
|
+
timeMs: 100,
|
|
665
|
+
status: "solved"
|
|
666
|
+
}]
|
|
667
|
+
}, {
|
|
668
|
+
initial: {
|
|
669
|
+
id: "captcha2",
|
|
670
|
+
tabId: 0,
|
|
671
|
+
type: "hcaptcha",
|
|
672
|
+
status: "solving"
|
|
673
|
+
},
|
|
674
|
+
transitions: [{
|
|
675
|
+
timeMs: 200,
|
|
676
|
+
status: "detached"
|
|
677
|
+
}]
|
|
678
|
+
}, {
|
|
679
|
+
initial: {
|
|
680
|
+
id: "captcha3",
|
|
681
|
+
tabId: 0,
|
|
682
|
+
type: "funcaptcha",
|
|
683
|
+
status: "solving"
|
|
684
|
+
},
|
|
685
|
+
transitions: [{
|
|
686
|
+
timeMs: 300,
|
|
687
|
+
status: "solved"
|
|
688
|
+
}]
|
|
689
|
+
}],
|
|
690
|
+
settleDurationMs: 100
|
|
691
|
+
});
|
|
692
|
+
});
|
|
693
|
+
});
|
|
694
|
+
(0, _vitest.describe)("onCaptchaEvent", () => {
|
|
695
|
+
(0, _vitest.it)("calls callback for matching status", async () => {
|
|
696
|
+
const page = makeMockPage();
|
|
697
|
+
const receivedCaptchas = [];
|
|
698
|
+
await (0, _captcha.onCaptchaEvent)(page, "solved", async captcha => {
|
|
699
|
+
receivedCaptchas.push(captcha);
|
|
700
|
+
});
|
|
701
|
+
await server.handleUpsertCaptcha({
|
|
702
|
+
id: "c1",
|
|
703
|
+
tabId: 0,
|
|
704
|
+
type: "recaptcha",
|
|
705
|
+
status: "solved"
|
|
706
|
+
});
|
|
707
|
+
(0, _vitest.expect)(receivedCaptchas).toHaveLength(1);
|
|
708
|
+
(0, _vitest.expect)(receivedCaptchas[0].id).toBe("c1");
|
|
709
|
+
(0, _vitest.expect)(receivedCaptchas[0].status).toBe("solved");
|
|
710
|
+
});
|
|
711
|
+
(0, _vitest.it)("ignores non-matching status", async () => {
|
|
712
|
+
const page = makeMockPage();
|
|
713
|
+
const receivedCaptchas = [];
|
|
714
|
+
await (0, _captcha.onCaptchaEvent)(page, "solved", async captcha => {
|
|
715
|
+
receivedCaptchas.push(captcha);
|
|
716
|
+
});
|
|
717
|
+
await server.handleUpsertCaptcha({
|
|
718
|
+
id: "c1",
|
|
719
|
+
tabId: 0,
|
|
720
|
+
type: "recaptcha",
|
|
721
|
+
status: "solving"
|
|
722
|
+
});
|
|
723
|
+
(0, _vitest.expect)(receivedCaptchas).toHaveLength(0);
|
|
724
|
+
});
|
|
725
|
+
(0, _vitest.it)("calls callback multiple times for multiple matching events", async () => {
|
|
726
|
+
const page = makeMockPage();
|
|
727
|
+
const receivedCaptchas = [];
|
|
728
|
+
await (0, _captcha.onCaptchaEvent)(page, "solved", async captcha => {
|
|
729
|
+
receivedCaptchas.push(captcha);
|
|
730
|
+
});
|
|
731
|
+
await server.handleUpsertCaptcha({
|
|
732
|
+
id: "c1",
|
|
733
|
+
tabId: 0,
|
|
734
|
+
type: "recaptcha",
|
|
735
|
+
status: "solved"
|
|
736
|
+
});
|
|
737
|
+
await server.handleUpsertCaptcha({
|
|
738
|
+
id: "c2",
|
|
739
|
+
tabId: 0,
|
|
740
|
+
type: "hcaptcha",
|
|
741
|
+
status: "solved"
|
|
742
|
+
});
|
|
743
|
+
(0, _vitest.expect)(receivedCaptchas).toHaveLength(2);
|
|
744
|
+
(0, _vitest.expect)(receivedCaptchas[0].id).toBe("c1");
|
|
745
|
+
(0, _vitest.expect)(receivedCaptchas[1].id).toBe("c2");
|
|
746
|
+
});
|
|
747
|
+
});
|
|
748
|
+
(0, _vitest.describe)("onceCaptchaEvent", () => {
|
|
749
|
+
(0, _vitest.it)("calls callback only once for first matching event", async () => {
|
|
750
|
+
const page = makeMockPage();
|
|
751
|
+
const receivedCaptchas = [];
|
|
752
|
+
await (0, _captcha.onceCaptchaEvent)(page, "solved", async captcha => {
|
|
753
|
+
receivedCaptchas.push(captcha);
|
|
754
|
+
});
|
|
755
|
+
await server.handleUpsertCaptcha({
|
|
756
|
+
id: "c1",
|
|
757
|
+
tabId: 0,
|
|
758
|
+
type: "recaptcha",
|
|
759
|
+
status: "solved"
|
|
760
|
+
});
|
|
761
|
+
await server.handleUpsertCaptcha({
|
|
762
|
+
id: "c2",
|
|
763
|
+
tabId: 0,
|
|
764
|
+
type: "hcaptcha",
|
|
765
|
+
status: "solved"
|
|
766
|
+
});
|
|
767
|
+
(0, _vitest.expect)(receivedCaptchas).toHaveLength(1);
|
|
768
|
+
(0, _vitest.expect)(receivedCaptchas[0].id).toBe("c1");
|
|
769
|
+
});
|
|
770
|
+
(0, _vitest.it)("receives all events until first match, then unsubscribes", async () => {
|
|
771
|
+
const page = makeMockPage();
|
|
772
|
+
const receivedCaptchas = [];
|
|
773
|
+
await (0, _captcha.onceCaptchaEvent)(page, "solved", async captcha => {
|
|
774
|
+
receivedCaptchas.push(captcha);
|
|
775
|
+
});
|
|
776
|
+
await server.handleUpsertCaptcha({
|
|
777
|
+
id: "c1",
|
|
778
|
+
tabId: 0,
|
|
779
|
+
type: "recaptcha",
|
|
780
|
+
status: "solving"
|
|
781
|
+
});
|
|
782
|
+
(0, _vitest.expect)(receivedCaptchas).toHaveLength(0);
|
|
783
|
+
await server.handleUpsertCaptcha({
|
|
784
|
+
id: "c2",
|
|
785
|
+
tabId: 0,
|
|
786
|
+
type: "recaptcha",
|
|
787
|
+
status: "solved"
|
|
788
|
+
});
|
|
789
|
+
(0, _vitest.expect)(receivedCaptchas).toHaveLength(1);
|
|
790
|
+
(0, _vitest.expect)(receivedCaptchas[0].id).toBe("c2");
|
|
791
|
+
await server.handleUpsertCaptcha({
|
|
792
|
+
id: "c3",
|
|
793
|
+
tabId: 0,
|
|
794
|
+
type: "recaptcha",
|
|
795
|
+
status: "solved"
|
|
796
|
+
});
|
|
797
|
+
(0, _vitest.expect)(receivedCaptchas).toHaveLength(1);
|
|
798
|
+
});
|
|
799
|
+
(0, _vitest.it)("unsubscribes after first matching event", async () => {
|
|
800
|
+
const page = makeMockPage();
|
|
801
|
+
let callCount = 0;
|
|
802
|
+
await (0, _captcha.onceCaptchaEvent)(page, "solved", async () => {
|
|
803
|
+
callCount++;
|
|
804
|
+
});
|
|
805
|
+
await server.handleUpsertCaptcha({
|
|
806
|
+
id: "c1",
|
|
807
|
+
tabId: 0,
|
|
808
|
+
type: "recaptcha",
|
|
809
|
+
status: "solved"
|
|
810
|
+
});
|
|
811
|
+
(0, _vitest.expect)(callCount).toBe(1);
|
|
812
|
+
await server.handleUpsertCaptcha({
|
|
813
|
+
id: "c2",
|
|
814
|
+
tabId: 0,
|
|
815
|
+
type: "recaptcha",
|
|
816
|
+
status: "solved"
|
|
817
|
+
});
|
|
818
|
+
(0, _vitest.expect)(callCount).toBe(1);
|
|
819
|
+
});
|
|
820
|
+
});
|
|
821
|
+
});
|