cdp-skill 1.0.8 → 1.0.15
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 +80 -35
- package/SKILL.md +157 -241
- package/install.js +1 -0
- package/package.json +1 -1
- package/src/aria/index.js +8 -0
- package/src/aria/output-processor.js +173 -0
- package/src/aria/role-query.js +1229 -0
- package/src/aria/snapshot.js +459 -0
- package/src/aria.js +251 -50
- package/src/cdp/browser.js +22 -4
- package/src/cdp-skill.js +246 -69
- package/src/dom/LazyResolver.js +634 -0
- package/src/dom/click-executor.js +366 -94
- package/src/dom/element-locator.js +34 -25
- package/src/dom/fill-executor.js +83 -50
- package/src/dom/index.js +3 -0
- package/src/page/dialog-handler.js +119 -0
- package/src/page/page-controller.js +236 -3
- package/src/runner/context-helpers.js +33 -55
- package/src/runner/execute-dynamic.js +8 -7
- package/src/runner/execute-form.js +11 -11
- package/src/runner/execute-input.js +2 -2
- package/src/runner/execute-interaction.js +105 -126
- package/src/runner/execute-navigation.js +14 -29
- package/src/runner/execute-query.js +17 -11
- package/src/runner/step-executors.js +225 -84
- package/src/runner/step-registry.js +1064 -0
- package/src/runner/step-validator.js +16 -754
- package/src/tests/Aria.test.js +1025 -0
- package/src/tests/ClickExecutor.test.js +170 -50
- package/src/tests/ContextHelpers.test.js +41 -30
- package/src/tests/ExecuteBrowser.test.js +572 -0
- package/src/tests/ExecuteDynamic.test.js +2 -457
- package/src/tests/ExecuteForm.test.js +700 -0
- package/src/tests/ExecuteInput.test.js +540 -0
- package/src/tests/ExecuteInteraction.test.js +319 -0
- package/src/tests/ExecuteQuery.test.js +820 -0
- package/src/tests/FillExecutor.test.js +89 -37
- package/src/tests/LazyResolver.test.js +383 -0
- package/src/tests/StepValidator.test.js +224 -78
- package/src/tests/TestRunner.test.js +38 -27
- package/src/tests/integration.test.js +2 -1
- package/src/types.js +9 -9
- package/src/utils/backoff.js +118 -0
- package/src/utils/cdp-helpers.js +130 -0
- package/src/utils/devices.js +140 -0
- package/src/utils/errors.js +242 -0
- package/src/utils/index.js +65 -0
- package/src/utils/temp.js +75 -0
- package/src/utils/validators.js +433 -0
- package/src/utils.js +14 -1142
|
@@ -120,17 +120,48 @@ describe('ClickExecutor', () => {
|
|
|
120
120
|
if (params?.expression?.includes('location.href')) {
|
|
121
121
|
return { result: { value: 'https://example.com' } };
|
|
122
122
|
}
|
|
123
|
-
|
|
123
|
+
// LazyResolver: first queries __ariaRefMeta for metadata
|
|
124
|
+
if (params?.expression?.includes('__ariaRefMeta') && params?.expression?.includes('get') && !params?.expression?.includes('lazyResolveRef')) {
|
|
125
|
+
return { result: { value: { selector: '#btn', role: 'button', name: 'Submit' } } };
|
|
126
|
+
}
|
|
127
|
+
// LazyResolver: then resolves element by selector
|
|
128
|
+
if (params?.expression?.includes('found') && params?.expression?.includes('box')) {
|
|
129
|
+
return { result: { value: { found: true, box: { x: 50, y: 50, width: 100, height: 40 } } } };
|
|
130
|
+
}
|
|
131
|
+
// LazyResolver: gets objectId
|
|
132
|
+
if (params?.expression?.includes('querySelector') && !params?.expression?.includes('lazyResolveRef')) {
|
|
133
|
+
return { result: { objectId: 'obj-123' } };
|
|
134
|
+
}
|
|
135
|
+
// Browser-side lazy resolution for click verification/execution - return success
|
|
136
|
+
if (params?.expression?.includes('lazyResolveRef') && params?.expression?.includes('click')) {
|
|
137
|
+
return { result: { value: { success: true } } };
|
|
138
|
+
}
|
|
139
|
+
// Browser-side lazy resolution for event setup
|
|
140
|
+
if (params?.expression?.includes('lazyResolveRef')) {
|
|
141
|
+
return { result: { value: null } };
|
|
142
|
+
}
|
|
143
|
+
// Verification check
|
|
144
|
+
if (params?.expression?.includes('__clickVerifyEl') || params?.expression?.includes('targetReceived')) {
|
|
124
145
|
return { result: { value: { targetReceived: true } } };
|
|
125
146
|
}
|
|
126
147
|
return { result: { objectId: 'obj-123' } };
|
|
127
148
|
}
|
|
149
|
+
if (method === 'Runtime.callFunctionOn') {
|
|
150
|
+
// Visibility check after lazy resolution
|
|
151
|
+
if (params?.functionDeclaration?.includes('getComputedStyle') && params?.functionDeclaration?.includes('isVisible')) {
|
|
152
|
+
return { result: { value: { isVisible: true, box: { x: 50, y: 50, width: 100, height: 40 } } } };
|
|
153
|
+
}
|
|
154
|
+
if (params?.functionDeclaration?.includes('__clickReceived')) {
|
|
155
|
+
return { result: { value: true } };
|
|
156
|
+
}
|
|
157
|
+
return { result: { value: { success: true, targetReceived: true } } };
|
|
158
|
+
}
|
|
128
159
|
return {};
|
|
129
160
|
});
|
|
130
161
|
|
|
131
|
-
const result = await executor.execute({ ref: '
|
|
162
|
+
const result = await executor.execute({ ref: 'f0s1e1' });
|
|
132
163
|
assert.strictEqual(result.clicked, true);
|
|
133
|
-
assert.strictEqual(result.ref, '
|
|
164
|
+
assert.strictEqual(result.ref, 'f0s1e1');
|
|
134
165
|
});
|
|
135
166
|
|
|
136
167
|
it('should detect ref from string selector pattern', async () => {
|
|
@@ -139,17 +170,44 @@ describe('ClickExecutor', () => {
|
|
|
139
170
|
if (params?.expression?.includes('location.href')) {
|
|
140
171
|
return { result: { value: 'https://example.com' } };
|
|
141
172
|
}
|
|
142
|
-
|
|
173
|
+
// LazyResolver: queries __ariaRefMeta for metadata
|
|
174
|
+
if (params?.expression?.includes('__ariaRefMeta') && params?.expression?.includes('get') && !params?.expression?.includes('lazyResolveRef')) {
|
|
175
|
+
return { result: { value: { selector: '#btn', role: 'button', name: 'Submit' } } };
|
|
176
|
+
}
|
|
177
|
+
// LazyResolver: resolves element
|
|
178
|
+
if (params?.expression?.includes('found') && params?.expression?.includes('box')) {
|
|
179
|
+
return { result: { value: { found: true, box: { x: 50, y: 50, width: 100, height: 40 } } } };
|
|
180
|
+
}
|
|
181
|
+
if (params?.expression?.includes('querySelector') && !params?.expression?.includes('lazyResolveRef')) {
|
|
182
|
+
return { result: { objectId: 'obj-123' } };
|
|
183
|
+
}
|
|
184
|
+
// Browser-side lazy resolution for click - return success
|
|
185
|
+
if (params?.expression?.includes('lazyResolveRef') && params?.expression?.includes('click')) {
|
|
186
|
+
return { result: { value: { success: true } } };
|
|
187
|
+
}
|
|
188
|
+
if (params?.expression?.includes('lazyResolveRef')) {
|
|
189
|
+
return { result: { value: null } };
|
|
190
|
+
}
|
|
191
|
+
if (params?.expression?.includes('__clickVerifyEl') || params?.expression?.includes('targetReceived')) {
|
|
143
192
|
return { result: { value: { targetReceived: true } } };
|
|
144
193
|
}
|
|
145
194
|
return { result: { objectId: 'obj-123' } };
|
|
146
195
|
}
|
|
196
|
+
if (method === 'Runtime.callFunctionOn') {
|
|
197
|
+
if (params?.functionDeclaration?.includes('getComputedStyle') && params?.functionDeclaration?.includes('isVisible')) {
|
|
198
|
+
return { result: { value: { isVisible: true, box: { x: 50, y: 50, width: 100, height: 40 } } } };
|
|
199
|
+
}
|
|
200
|
+
if (params?.functionDeclaration?.includes('__clickReceived')) {
|
|
201
|
+
return { result: { value: true } };
|
|
202
|
+
}
|
|
203
|
+
return { result: { value: { success: true, targetReceived: true } } };
|
|
204
|
+
}
|
|
147
205
|
return {};
|
|
148
206
|
});
|
|
149
207
|
|
|
150
|
-
const result = await executor.execute('
|
|
208
|
+
const result = await executor.execute('f0s1e12');
|
|
151
209
|
assert.strictEqual(result.clicked, true);
|
|
152
|
-
assert.strictEqual(result.ref, '
|
|
210
|
+
assert.strictEqual(result.ref, 'f0s1e12');
|
|
153
211
|
});
|
|
154
212
|
|
|
155
213
|
it('should handle text-based click', async () => {
|
|
@@ -392,7 +450,7 @@ describe('ClickExecutor', () => {
|
|
|
392
450
|
const noAriaExecutor = createClickExecutor(mockSession, mockElementLocator, mockInputEmulator);
|
|
393
451
|
|
|
394
452
|
// Without ariaSnapshot, the executor falls back to selector-based click
|
|
395
|
-
// which will fail to find the element "
|
|
453
|
+
// which will fail to find the element "f0s1e1" (since it's not a valid CSS selector)
|
|
396
454
|
mockSession.send = mock.fn(async (method, params) => {
|
|
397
455
|
if (method === 'Runtime.evaluate') {
|
|
398
456
|
if (params?.expression?.includes('location.href')) {
|
|
@@ -404,100 +462,162 @@ describe('ClickExecutor', () => {
|
|
|
404
462
|
});
|
|
405
463
|
|
|
406
464
|
await assert.rejects(
|
|
407
|
-
() => noAriaExecutor.execute({ ref: '
|
|
465
|
+
() => noAriaExecutor.execute({ ref: 'f0s1e1' }),
|
|
408
466
|
(err) => {
|
|
409
|
-
// Without ariaSnapshot, the ref '
|
|
467
|
+
// Without ariaSnapshot, the ref 'f0s1e1' is treated as selector, failing to find
|
|
410
468
|
return err.message.includes('not found') || err.message.includes('ariaSnapshot');
|
|
411
469
|
}
|
|
412
470
|
);
|
|
413
471
|
});
|
|
414
472
|
|
|
415
|
-
it('should
|
|
416
|
-
|
|
417
|
-
box: { x: 50, y: 50, width: 100, height: 40 },
|
|
418
|
-
isVisible: true,
|
|
419
|
-
stale: true
|
|
420
|
-
}));
|
|
421
|
-
|
|
473
|
+
it('should throw when ref element cannot be resolved (lazy resolution)', async () => {
|
|
474
|
+
// LazyResolver returns null when metadata not found or element can't be resolved
|
|
422
475
|
mockSession.send = mock.fn(async (method, params) => {
|
|
423
|
-
if (method === 'Runtime.evaluate'
|
|
424
|
-
|
|
476
|
+
if (method === 'Runtime.evaluate') {
|
|
477
|
+
if (params?.expression?.includes('location.href')) {
|
|
478
|
+
return { result: { value: 'https://example.com' } };
|
|
479
|
+
}
|
|
480
|
+
// LazyResolver: no metadata found
|
|
481
|
+
if (params?.expression?.includes('__ariaRefMeta')) {
|
|
482
|
+
return { result: { value: null } };
|
|
483
|
+
}
|
|
484
|
+
return { result: { value: null } };
|
|
425
485
|
}
|
|
426
486
|
return {};
|
|
427
487
|
});
|
|
428
488
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
489
|
+
await assert.rejects(
|
|
490
|
+
async () => await executor.execute({ ref: 'f0s1e1' }),
|
|
491
|
+
(err) => err.message.includes('not found')
|
|
492
|
+
);
|
|
433
493
|
});
|
|
434
494
|
|
|
435
495
|
it('should return warning when ref element is not visible', async () => {
|
|
436
|
-
mockAriaSnapshot.getElementByRef = mock.fn(async () => ({
|
|
437
|
-
box: { x: 50, y: 50, width: 100, height: 40 },
|
|
438
|
-
isVisible: false,
|
|
439
|
-
stale: false
|
|
440
|
-
}));
|
|
441
|
-
|
|
442
496
|
mockSession.send = mock.fn(async (method, params) => {
|
|
443
|
-
if (method === 'Runtime.evaluate'
|
|
444
|
-
|
|
497
|
+
if (method === 'Runtime.evaluate') {
|
|
498
|
+
if (params?.expression?.includes('location.href')) {
|
|
499
|
+
return { result: { value: 'https://example.com' } };
|
|
500
|
+
}
|
|
501
|
+
// LazyResolver: metadata found
|
|
502
|
+
if (params?.expression?.includes('__ariaRefMeta') && params?.expression?.includes('get')) {
|
|
503
|
+
return { result: { value: { selector: '#btn', role: 'button', name: 'Submit' } } };
|
|
504
|
+
}
|
|
505
|
+
// LazyResolver: element found
|
|
506
|
+
if (params?.expression?.includes('found') && params?.expression?.includes('box')) {
|
|
507
|
+
return { result: { value: { found: true, box: { x: 50, y: 50, width: 100, height: 40 } } } };
|
|
508
|
+
}
|
|
509
|
+
if (params?.expression?.includes('querySelector')) {
|
|
510
|
+
return { result: { objectId: 'obj-123' } };
|
|
511
|
+
}
|
|
512
|
+
if (params?.expression?.includes('lazyResolveRef')) {
|
|
513
|
+
return { result: { value: null } };
|
|
514
|
+
}
|
|
515
|
+
return { result: { objectId: 'obj-123' } };
|
|
516
|
+
}
|
|
517
|
+
if (method === 'Runtime.callFunctionOn') {
|
|
518
|
+
// Visibility check returns not visible
|
|
519
|
+
if (params?.functionDeclaration?.includes('getComputedStyle') && params?.functionDeclaration?.includes('isVisible')) {
|
|
520
|
+
return { result: { value: { isVisible: false, box: { x: 50, y: 50, width: 100, height: 40 } } } };
|
|
521
|
+
}
|
|
522
|
+
return { result: { value: { found: false } } };
|
|
445
523
|
}
|
|
446
524
|
return {};
|
|
447
525
|
});
|
|
448
526
|
|
|
449
|
-
const result = await executor.execute({ ref: '
|
|
527
|
+
const result = await executor.execute({ ref: 'f0s1e1' });
|
|
450
528
|
assert.strictEqual(result.clicked, false);
|
|
451
529
|
assert.ok(result.warning.includes('not visible'));
|
|
452
530
|
});
|
|
453
531
|
|
|
454
|
-
it('should succeed when ref element is
|
|
455
|
-
mockAriaSnapshot.getElementByRef = mock.fn(async () => ({
|
|
456
|
-
box: { x: 50, y: 50, width: 100, height: 40 },
|
|
457
|
-
isVisible: true,
|
|
458
|
-
stale: false,
|
|
459
|
-
reResolved: true
|
|
460
|
-
}));
|
|
461
|
-
|
|
532
|
+
it('should succeed when ref element is resolved via lazy resolution', async () => {
|
|
462
533
|
mockSession.send = mock.fn(async (method, params) => {
|
|
463
534
|
if (method === 'Runtime.evaluate') {
|
|
464
535
|
if (params?.expression?.includes('location.href')) {
|
|
465
536
|
return { result: { value: 'https://example.com' } };
|
|
466
537
|
}
|
|
467
|
-
|
|
538
|
+
// LazyResolver: metadata found
|
|
539
|
+
if (params?.expression?.includes('__ariaRefMeta') && params?.expression?.includes('get') && !params?.expression?.includes('lazyResolveRef')) {
|
|
540
|
+
return { result: { value: { selector: '#btn', role: 'button', name: 'Submit' } } };
|
|
541
|
+
}
|
|
542
|
+
// LazyResolver: element found
|
|
543
|
+
if (params?.expression?.includes('found') && params?.expression?.includes('box')) {
|
|
544
|
+
return { result: { value: { found: true, box: { x: 50, y: 50, width: 100, height: 40 } } } };
|
|
545
|
+
}
|
|
546
|
+
if (params?.expression?.includes('querySelector') && !params?.expression?.includes('lazyResolveRef')) {
|
|
547
|
+
return { result: { objectId: 'obj-123' } };
|
|
548
|
+
}
|
|
549
|
+
// Browser-side lazy resolution for click - return success
|
|
550
|
+
if (params?.expression?.includes('lazyResolveRef') && params?.expression?.includes('click')) {
|
|
551
|
+
return { result: { value: { success: true } } };
|
|
552
|
+
}
|
|
553
|
+
if (params?.expression?.includes('lazyResolveRef')) {
|
|
554
|
+
return { result: { value: null } };
|
|
555
|
+
}
|
|
556
|
+
if (params?.expression?.includes('__clickVerifyEl') || params?.expression?.includes('targetReceived')) {
|
|
468
557
|
return { result: { value: { targetReceived: true } } };
|
|
469
558
|
}
|
|
470
559
|
return { result: { objectId: 'obj-123' } };
|
|
471
560
|
}
|
|
561
|
+
if (method === 'Runtime.callFunctionOn') {
|
|
562
|
+
if (params?.functionDeclaration?.includes('getComputedStyle') && params?.functionDeclaration?.includes('isVisible')) {
|
|
563
|
+
return { result: { value: { isVisible: true, box: { x: 50, y: 50, width: 100, height: 40 } } } };
|
|
564
|
+
}
|
|
565
|
+
if (params?.functionDeclaration?.includes('__clickReceived')) {
|
|
566
|
+
return { result: { value: true } };
|
|
567
|
+
}
|
|
568
|
+
return { result: { value: { success: true, targetReceived: true } } };
|
|
569
|
+
}
|
|
472
570
|
return {};
|
|
473
571
|
});
|
|
474
572
|
|
|
475
|
-
const result = await executor.execute({ ref: '
|
|
573
|
+
const result = await executor.execute({ ref: 'f0s1e1' });
|
|
476
574
|
assert.strictEqual(result.clicked, true);
|
|
477
|
-
assert.strictEqual(result.ref, '
|
|
575
|
+
assert.strictEqual(result.ref, 'f0s1e1');
|
|
478
576
|
});
|
|
479
577
|
|
|
480
578
|
it('should click non-visible element with force option', async () => {
|
|
481
|
-
mockAriaSnapshot.getElementByRef = mock.fn(async () => ({
|
|
482
|
-
box: { x: 50, y: 50, width: 100, height: 40 },
|
|
483
|
-
isVisible: false,
|
|
484
|
-
stale: false
|
|
485
|
-
}));
|
|
486
|
-
|
|
487
579
|
mockSession.send = mock.fn(async (method, params) => {
|
|
488
580
|
if (method === 'Runtime.evaluate') {
|
|
489
581
|
if (params?.expression?.includes('location.href')) {
|
|
490
582
|
return { result: { value: 'https://example.com' } };
|
|
491
583
|
}
|
|
492
|
-
|
|
584
|
+
// LazyResolver: metadata found
|
|
585
|
+
if (params?.expression?.includes('__ariaRefMeta') && params?.expression?.includes('get') && !params?.expression?.includes('lazyResolveRef')) {
|
|
586
|
+
return { result: { value: { selector: '#btn', role: 'button', name: 'Submit' } } };
|
|
587
|
+
}
|
|
588
|
+
// LazyResolver: element found
|
|
589
|
+
if (params?.expression?.includes('found') && params?.expression?.includes('box')) {
|
|
590
|
+
return { result: { value: { found: true, box: { x: 50, y: 50, width: 100, height: 40 } } } };
|
|
591
|
+
}
|
|
592
|
+
if (params?.expression?.includes('querySelector') && !params?.expression?.includes('lazyResolveRef')) {
|
|
593
|
+
return { result: { objectId: 'obj-123' } };
|
|
594
|
+
}
|
|
595
|
+
// Browser-side lazy resolution for click - return success
|
|
596
|
+
if (params?.expression?.includes('lazyResolveRef') && params?.expression?.includes('click')) {
|
|
597
|
+
return { result: { value: { success: true } } };
|
|
598
|
+
}
|
|
599
|
+
if (params?.expression?.includes('lazyResolveRef')) {
|
|
600
|
+
return { result: { value: null } };
|
|
601
|
+
}
|
|
602
|
+
if (params?.expression?.includes('__clickVerifyEl') || params?.expression?.includes('targetReceived')) {
|
|
493
603
|
return { result: { value: { targetReceived: true } } };
|
|
494
604
|
}
|
|
495
605
|
return { result: { objectId: 'obj-123' } };
|
|
496
606
|
}
|
|
607
|
+
if (method === 'Runtime.callFunctionOn') {
|
|
608
|
+
// Visibility check returns not visible, but force=true will proceed
|
|
609
|
+
if (params?.functionDeclaration?.includes('getComputedStyle') && params?.functionDeclaration?.includes('isVisible')) {
|
|
610
|
+
return { result: { value: { isVisible: false, box: { x: 50, y: 50, width: 100, height: 40 } } } };
|
|
611
|
+
}
|
|
612
|
+
if (params?.functionDeclaration?.includes('__clickReceived')) {
|
|
613
|
+
return { result: { value: true } };
|
|
614
|
+
}
|
|
615
|
+
return { result: { value: { success: true, targetReceived: true } } };
|
|
616
|
+
}
|
|
497
617
|
return {};
|
|
498
618
|
});
|
|
499
619
|
|
|
500
|
-
const result = await executor.execute({ ref: '
|
|
620
|
+
const result = await executor.execute({ ref: 'f0s1e1', force: true });
|
|
501
621
|
assert.strictEqual(result.clicked, true);
|
|
502
622
|
});
|
|
503
623
|
});
|
|
@@ -30,9 +30,7 @@ describe('ContextHelpers', () => {
|
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
it('should contain form step types', () => {
|
|
33
|
-
assert.ok(STEP_TYPES.includes('
|
|
34
|
-
assert.ok(STEP_TYPES.includes('type'));
|
|
35
|
-
assert.ok(STEP_TYPES.includes('select'));
|
|
33
|
+
assert.ok(STEP_TYPES.includes('selectText'));
|
|
36
34
|
assert.ok(STEP_TYPES.includes('selectOption'));
|
|
37
35
|
assert.ok(STEP_TYPES.includes('submit'));
|
|
38
36
|
});
|
|
@@ -40,19 +38,31 @@ describe('ContextHelpers', () => {
|
|
|
40
38
|
it('should contain tab step types', () => {
|
|
41
39
|
assert.ok(STEP_TYPES.includes('listTabs'));
|
|
42
40
|
assert.ok(STEP_TYPES.includes('closeTab'));
|
|
43
|
-
assert.ok(STEP_TYPES.includes('
|
|
41
|
+
assert.ok(STEP_TYPES.includes('newTab'));
|
|
42
|
+
assert.ok(STEP_TYPES.includes('switchTab'));
|
|
44
43
|
});
|
|
45
44
|
|
|
46
|
-
it('should contain
|
|
47
|
-
assert.ok(STEP_TYPES.includes('
|
|
48
|
-
assert.ok(STEP_TYPES.includes('
|
|
49
|
-
assert.ok(STEP_TYPES.includes('
|
|
45
|
+
it('should contain unified frame step', () => {
|
|
46
|
+
assert.ok(STEP_TYPES.includes('frame'));
|
|
47
|
+
assert.ok(!STEP_TYPES.includes('switchToFrame'));
|
|
48
|
+
assert.ok(!STEP_TYPES.includes('switchToMainFrame'));
|
|
49
|
+
assert.ok(!STEP_TYPES.includes('listFrames'));
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
it('should contain
|
|
53
|
-
assert.ok(STEP_TYPES.includes('refAt'));
|
|
52
|
+
it('should contain unified elementsAt step', () => {
|
|
54
53
|
assert.ok(STEP_TYPES.includes('elementsAt'));
|
|
55
|
-
assert.ok(STEP_TYPES.includes('
|
|
54
|
+
assert.ok(!STEP_TYPES.includes('refAt'));
|
|
55
|
+
assert.ok(!STEP_TYPES.includes('elementsNear'));
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should contain sleep step', () => {
|
|
59
|
+
assert.ok(STEP_TYPES.includes('sleep'));
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should not contain removed steps', () => {
|
|
63
|
+
assert.ok(!STEP_TYPES.includes('fillForm'));
|
|
64
|
+
assert.ok(!STEP_TYPES.includes('fillActive'));
|
|
65
|
+
assert.ok(!STEP_TYPES.includes('eval'));
|
|
56
66
|
});
|
|
57
67
|
});
|
|
58
68
|
|
|
@@ -65,7 +75,6 @@ describe('ContextHelpers', () => {
|
|
|
65
75
|
assert.ok(VISUAL_ACTIONS.includes('goto'));
|
|
66
76
|
assert.ok(VISUAL_ACTIONS.includes('click'));
|
|
67
77
|
assert.ok(VISUAL_ACTIONS.includes('fill'));
|
|
68
|
-
assert.ok(VISUAL_ACTIONS.includes('type'));
|
|
69
78
|
assert.ok(VISUAL_ACTIONS.includes('hover'));
|
|
70
79
|
assert.ok(VISUAL_ACTIONS.includes('press'));
|
|
71
80
|
assert.ok(VISUAL_ACTIONS.includes('scroll'));
|
|
@@ -76,14 +85,16 @@ describe('ContextHelpers', () => {
|
|
|
76
85
|
assert.ok(VISUAL_ACTIONS.includes('query'));
|
|
77
86
|
assert.ok(VISUAL_ACTIONS.includes('queryAll'));
|
|
78
87
|
assert.ok(VISUAL_ACTIONS.includes('inspect'));
|
|
79
|
-
assert.ok(VISUAL_ACTIONS.includes('
|
|
80
|
-
assert.ok(VISUAL_ACTIONS.includes('
|
|
88
|
+
assert.ok(VISUAL_ACTIONS.includes('pageFunction'));
|
|
89
|
+
assert.ok(VISUAL_ACTIONS.includes('get'));
|
|
81
90
|
});
|
|
82
91
|
|
|
83
92
|
it('should not contain non-visual actions', () => {
|
|
84
93
|
assert.ok(!VISUAL_ACTIONS.includes('cookies'));
|
|
85
94
|
assert.ok(!VISUAL_ACTIONS.includes('listTabs'));
|
|
86
95
|
assert.ok(!VISUAL_ACTIONS.includes('closeTab'));
|
|
96
|
+
assert.ok(!VISUAL_ACTIONS.includes('eval'));
|
|
97
|
+
assert.ok(!VISUAL_ACTIONS.includes('fillForm'));
|
|
87
98
|
});
|
|
88
99
|
});
|
|
89
100
|
|
|
@@ -122,8 +133,8 @@ describe('ContextHelpers', () => {
|
|
|
122
133
|
});
|
|
123
134
|
|
|
124
135
|
it('should describe click with ref', () => {
|
|
125
|
-
const result = buildActionContext('click', { ref: '
|
|
126
|
-
assert.strictEqual(result, 'Clicked [ref=
|
|
136
|
+
const result = buildActionContext('click', { ref: 'f0s1e1' }, {});
|
|
137
|
+
assert.strictEqual(result, 'Clicked [ref=f0s1e1]');
|
|
127
138
|
});
|
|
128
139
|
|
|
129
140
|
it('should describe click with text', () => {
|
|
@@ -165,11 +176,6 @@ describe('ContextHelpers', () => {
|
|
|
165
176
|
assert.strictEqual(result, 'Typed in "Email"');
|
|
166
177
|
});
|
|
167
178
|
|
|
168
|
-
it('should describe type with selector', () => {
|
|
169
|
-
const result = buildActionContext('type', { selector: '#search' }, {});
|
|
170
|
-
assert.strictEqual(result, 'Typed in #search');
|
|
171
|
-
});
|
|
172
|
-
|
|
173
179
|
it('should return generic for no params', () => {
|
|
174
180
|
const result = buildActionContext('fill', {}, {});
|
|
175
181
|
assert.strictEqual(result, 'Typed in input');
|
|
@@ -222,10 +228,6 @@ describe('ContextHelpers', () => {
|
|
|
222
228
|
assert.strictEqual(result, 'Typed');
|
|
223
229
|
});
|
|
224
230
|
|
|
225
|
-
it('should return Typed for type step', () => {
|
|
226
|
-
const result = buildCommandContext([{ type: { selector: '#input', text: 'test' } }]);
|
|
227
|
-
assert.strictEqual(result, 'Typed');
|
|
228
|
-
});
|
|
229
231
|
|
|
230
232
|
it('should return Pressed key for press step', () => {
|
|
231
233
|
const result = buildCommandContext([{ press: 'Enter' }]);
|
|
@@ -237,13 +239,13 @@ describe('ContextHelpers', () => {
|
|
|
237
239
|
assert.strictEqual(result, 'Navigated');
|
|
238
240
|
});
|
|
239
241
|
|
|
240
|
-
it('should return Navigated for
|
|
241
|
-
const result = buildCommandContext([{
|
|
242
|
+
it('should return Navigated for newTab step', () => {
|
|
243
|
+
const result = buildCommandContext([{ newTab: 'https://example.com' }]);
|
|
242
244
|
assert.strictEqual(result, 'Navigated');
|
|
243
245
|
});
|
|
244
246
|
|
|
245
|
-
it('should return Selected for
|
|
246
|
-
const result = buildCommandContext([{
|
|
247
|
+
it('should return Selected for selectText step', () => {
|
|
248
|
+
const result = buildCommandContext([{ selectText: '#dropdown' }]);
|
|
247
249
|
assert.strictEqual(result, 'Selected');
|
|
248
250
|
});
|
|
249
251
|
|
|
@@ -282,7 +284,16 @@ describe('ContextHelpers', () => {
|
|
|
282
284
|
mockPageController = {
|
|
283
285
|
session: {
|
|
284
286
|
send: mock.fn(async () => ({ result: { value: '' } }))
|
|
285
|
-
}
|
|
287
|
+
},
|
|
288
|
+
evaluateInFrame: mock.fn(async (expression, options = {}) => {
|
|
289
|
+
const params = {
|
|
290
|
+
expression,
|
|
291
|
+
returnByValue: options.returnByValue !== false,
|
|
292
|
+
awaitPromise: options.awaitPromise || false
|
|
293
|
+
};
|
|
294
|
+
return mockPageController.session.send('Runtime.evaluate', params);
|
|
295
|
+
}),
|
|
296
|
+
getFrameContext: mock.fn(() => null)
|
|
286
297
|
};
|
|
287
298
|
});
|
|
288
299
|
|