cdp-skill 1.0.14 → 1.0.16
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/SKILL.md +8 -4
- package/package.json +1 -1
- package/src/aria.js +14 -7
- package/src/cdp-skill.js +2 -1
- package/src/dom/LazyResolver.js +634 -0
- package/src/dom/click-executor.js +162 -54
- package/src/dom/fill-executor.js +32 -27
- package/src/dom/index.js +3 -0
- package/src/page/page-controller.js +46 -0
- package/src/runner/execute-interaction.js +6 -6
- package/src/runner/execute-navigation.js +3 -3
- package/src/runner/execute-query.js +9 -6
- package/src/runner/step-registry.js +4 -4
- package/src/tests/Aria.test.js +5 -5
- package/src/tests/ClickExecutor.test.js +170 -50
- package/src/tests/ContextHelpers.test.js +2 -2
- package/src/tests/ExecuteInteraction.test.js +2 -2
- package/src/tests/ExecuteQuery.test.js +33 -33
- package/src/tests/FillExecutor.test.js +87 -35
- package/src/tests/LazyResolver.test.js +383 -0
- package/src/tests/StepValidator.test.js +2 -2
- package/src/tests/TestRunner.test.js +2 -2
|
@@ -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
|
});
|
|
@@ -133,8 +133,8 @@ describe('ContextHelpers', () => {
|
|
|
133
133
|
});
|
|
134
134
|
|
|
135
135
|
it('should describe click with ref', () => {
|
|
136
|
-
const result = buildActionContext('click', { ref: '
|
|
137
|
-
assert.strictEqual(result, 'Clicked [ref=
|
|
136
|
+
const result = buildActionContext('click', { ref: 'f0s1e1' }, {});
|
|
137
|
+
assert.strictEqual(result, 'Clicked [ref=f0s1e1]');
|
|
138
138
|
});
|
|
139
139
|
|
|
140
140
|
it('should describe click with text', () => {
|
|
@@ -184,7 +184,7 @@ describe('executeHover', () => {
|
|
|
184
184
|
const snapshot = createMockAriaSnapshot();
|
|
185
185
|
|
|
186
186
|
const result = await executeHover(locator, emulator, snapshot, {
|
|
187
|
-
ref: '
|
|
187
|
+
ref: 'f0s1e1'
|
|
188
188
|
});
|
|
189
189
|
|
|
190
190
|
assert.strictEqual(result.hovered, true);
|
|
@@ -295,7 +295,7 @@ describe('executeDrag', () => {
|
|
|
295
295
|
|
|
296
296
|
await assert.rejects(
|
|
297
297
|
executeDrag(locator, emulator, pc, snapshot, {
|
|
298
|
-
source: '
|
|
298
|
+
source: 'f0s1e1',
|
|
299
299
|
target: { x: 200, y: 200 }
|
|
300
300
|
}),
|
|
301
301
|
{ message: /no longer attached/i }
|
|
@@ -33,7 +33,7 @@ function createMockAriaSnapshot(opts = {}) {
|
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
35
|
const yaml = opts.yaml || '- button "Submit"';
|
|
36
|
-
const refs = opts.refs || { '
|
|
36
|
+
const refs = opts.refs || { 'f0s1e1': 'ref-data' };
|
|
37
37
|
|
|
38
38
|
// For snapshotSearch, return tree structure
|
|
39
39
|
if (opts.searchTree) {
|
|
@@ -41,8 +41,8 @@ function createMockAriaSnapshot(opts = {}) {
|
|
|
41
41
|
tree: {
|
|
42
42
|
role: 'document',
|
|
43
43
|
children: [
|
|
44
|
-
{ role: 'button', name: 'Submit', ref: '
|
|
45
|
-
{ role: 'button', name: 'Cancel', ref: '
|
|
44
|
+
{ role: 'button', name: 'Submit', ref: 'f0s1e1', box: { x: 10, y: 10, width: 80, height: 40 } },
|
|
45
|
+
{ role: 'button', name: 'Cancel', ref: 'f0s1e2', box: { x: 100, y: 10, width: 80, height: 40 } }
|
|
46
46
|
]
|
|
47
47
|
},
|
|
48
48
|
yaml,
|
|
@@ -60,13 +60,13 @@ function createMockAriaSnapshot(opts = {}) {
|
|
|
60
60
|
};
|
|
61
61
|
}),
|
|
62
62
|
getElementByRef: mock.fn(async (ref) => {
|
|
63
|
-
if (opts.refNotFound || ref === '
|
|
63
|
+
if (opts.refNotFound || ref === 'f0s1e999') {
|
|
64
64
|
return null;
|
|
65
65
|
}
|
|
66
|
-
if (opts.refStale || ref === '
|
|
66
|
+
if (opts.refStale || ref === 'f0s1e998') {
|
|
67
67
|
return { stale: true };
|
|
68
68
|
}
|
|
69
|
-
if (opts.refHidden || ref === '
|
|
69
|
+
if (opts.refHidden || ref === 'f0s1e997') {
|
|
70
70
|
return {
|
|
71
71
|
isVisible: false,
|
|
72
72
|
box: { x: 0, y: 0, width: 0, height: 0 }
|
|
@@ -122,7 +122,7 @@ function createMockPageController(opts = {}) {
|
|
|
122
122
|
return {
|
|
123
123
|
result: {
|
|
124
124
|
value: {
|
|
125
|
-
ref: '
|
|
125
|
+
ref: 'f0s1e1',
|
|
126
126
|
existing: false,
|
|
127
127
|
tag: 'BUTTON',
|
|
128
128
|
selector: 'button.submit',
|
|
@@ -146,8 +146,8 @@ function createMockPageController(opts = {}) {
|
|
|
146
146
|
result: {
|
|
147
147
|
value: {
|
|
148
148
|
results: [
|
|
149
|
-
{ x: 100, y: 100, ref: '
|
|
150
|
-
{ x: 200, y: 200, ref: '
|
|
149
|
+
{ x: 100, y: 100, ref: 'f0s1e1', tag: 'BUTTON' },
|
|
150
|
+
{ x: 200, y: 200, ref: 'f0s1e2', tag: 'A' }
|
|
151
151
|
]
|
|
152
152
|
}
|
|
153
153
|
}
|
|
@@ -158,8 +158,8 @@ function createMockPageController(opts = {}) {
|
|
|
158
158
|
result: {
|
|
159
159
|
value: {
|
|
160
160
|
elements: [
|
|
161
|
-
{ ref: '
|
|
162
|
-
{ ref: '
|
|
161
|
+
{ ref: 'f0s1e1', tag: 'BUTTON', distance: 10 },
|
|
162
|
+
{ ref: 'f0s1e2', tag: 'A', distance: 25 }
|
|
163
163
|
],
|
|
164
164
|
searchCenter: { x: 100, y: 100 },
|
|
165
165
|
searchRadius: 50
|
|
@@ -249,7 +249,7 @@ describe('executeSnapshot', () => {
|
|
|
249
249
|
const result = await executeSnapshot(ariaSnapshot, true);
|
|
250
250
|
|
|
251
251
|
assert.strictEqual(result.yaml, '- button "Submit"');
|
|
252
|
-
assert.deepStrictEqual(result.refs, { '
|
|
252
|
+
assert.deepStrictEqual(result.refs, { 'f0s1e1': 'ref-data' });
|
|
253
253
|
assert.strictEqual(result.snapshotId, 1);
|
|
254
254
|
assert.ok(result.stats);
|
|
255
255
|
});
|
|
@@ -403,14 +403,14 @@ describe('executeGetDom', () => {
|
|
|
403
403
|
describe('executeGetBox', () => {
|
|
404
404
|
it('should throw if ariaSnapshot is null', async () => {
|
|
405
405
|
await assert.rejects(
|
|
406
|
-
async () => executeGetBox(null, '
|
|
406
|
+
async () => executeGetBox(null, 'f0s1e1'),
|
|
407
407
|
/ariaSnapshot is required/
|
|
408
408
|
);
|
|
409
409
|
});
|
|
410
410
|
|
|
411
411
|
it('should get box for single ref string', async () => {
|
|
412
412
|
const ariaSnapshot = createMockAriaSnapshot();
|
|
413
|
-
const result = await executeGetBox(ariaSnapshot, '
|
|
413
|
+
const result = await executeGetBox(ariaSnapshot, 'f0s1e1');
|
|
414
414
|
|
|
415
415
|
assert.strictEqual(result.x, 100);
|
|
416
416
|
assert.strictEqual(result.y, 200);
|
|
@@ -422,40 +422,40 @@ describe('executeGetBox', () => {
|
|
|
422
422
|
|
|
423
423
|
it('should get boxes for array of refs', async () => {
|
|
424
424
|
const ariaSnapshot = createMockAriaSnapshot();
|
|
425
|
-
const result = await executeGetBox(ariaSnapshot, ['
|
|
425
|
+
const result = await executeGetBox(ariaSnapshot, ['f0s1e1', 'f0s1e2']);
|
|
426
426
|
|
|
427
|
-
assert.ok(result.
|
|
428
|
-
assert.ok(result.
|
|
429
|
-
assert.strictEqual(result.
|
|
430
|
-
assert.strictEqual(result.
|
|
427
|
+
assert.ok(result.f0s1e1);
|
|
428
|
+
assert.ok(result.f0s1e2);
|
|
429
|
+
assert.strictEqual(result.f0s1e1.x, 100);
|
|
430
|
+
assert.strictEqual(result.f0s1e2.x, 100);
|
|
431
431
|
});
|
|
432
432
|
|
|
433
433
|
it('should handle ref object with refs array', async () => {
|
|
434
434
|
const ariaSnapshot = createMockAriaSnapshot();
|
|
435
|
-
const result = await executeGetBox(ariaSnapshot, { refs: ['
|
|
435
|
+
const result = await executeGetBox(ariaSnapshot, { refs: ['f0s1e1', 'f0s1e2'] });
|
|
436
436
|
|
|
437
437
|
// When multiple refs, returns object with ref keys
|
|
438
|
-
assert.ok(result.
|
|
439
|
-
assert.strictEqual(result.
|
|
438
|
+
assert.ok(result.f0s1e1);
|
|
439
|
+
assert.strictEqual(result.f0s1e1.x, 100);
|
|
440
440
|
});
|
|
441
441
|
|
|
442
442
|
it('should handle ref object with single ref', async () => {
|
|
443
443
|
const ariaSnapshot = createMockAriaSnapshot();
|
|
444
|
-
const result = await executeGetBox(ariaSnapshot, { ref: '
|
|
444
|
+
const result = await executeGetBox(ariaSnapshot, { ref: 'f0s1e1' });
|
|
445
445
|
|
|
446
446
|
assert.strictEqual(result.x, 100);
|
|
447
447
|
});
|
|
448
448
|
|
|
449
449
|
it('should return error for not found ref', async () => {
|
|
450
450
|
const ariaSnapshot = createMockAriaSnapshot({ refNotFound: true });
|
|
451
|
-
const result = await executeGetBox(ariaSnapshot, '
|
|
451
|
+
const result = await executeGetBox(ariaSnapshot, 'f0s1e999');
|
|
452
452
|
|
|
453
453
|
assert.strictEqual(result.error, 'not found');
|
|
454
454
|
});
|
|
455
455
|
|
|
456
456
|
it('should return stale error for stale ref', async () => {
|
|
457
457
|
const ariaSnapshot = createMockAriaSnapshot({ refStale: true });
|
|
458
|
-
const result = await executeGetBox(ariaSnapshot, '
|
|
458
|
+
const result = await executeGetBox(ariaSnapshot, 'f0s1e998');
|
|
459
459
|
|
|
460
460
|
assert.strictEqual(result.error, 'stale');
|
|
461
461
|
assert.ok(result.message.includes('no longer in DOM'));
|
|
@@ -463,7 +463,7 @@ describe('executeGetBox', () => {
|
|
|
463
463
|
|
|
464
464
|
it('should return hidden error for hidden element', async () => {
|
|
465
465
|
const ariaSnapshot = createMockAriaSnapshot({ refHidden: true });
|
|
466
|
-
const result = await executeGetBox(ariaSnapshot, '
|
|
466
|
+
const result = await executeGetBox(ariaSnapshot, 'f0s1e997');
|
|
467
467
|
|
|
468
468
|
assert.strictEqual(result.error, 'hidden');
|
|
469
469
|
assert.ok(result.box);
|
|
@@ -487,11 +487,11 @@ describe('executeGetBox', () => {
|
|
|
487
487
|
|
|
488
488
|
it('should handle mixed results for multiple refs', async () => {
|
|
489
489
|
const ariaSnapshot = createMockAriaSnapshot();
|
|
490
|
-
const result = await executeGetBox(ariaSnapshot, ['
|
|
490
|
+
const result = await executeGetBox(ariaSnapshot, ['f0s1e1', 'f0s1e999', 'f0s1e998']);
|
|
491
491
|
|
|
492
|
-
assert.ok(result.
|
|
493
|
-
assert.strictEqual(result.
|
|
494
|
-
assert.strictEqual(result.
|
|
492
|
+
assert.ok(result.f0s1e1.x);
|
|
493
|
+
assert.strictEqual(result.f0s1e999.error, 'not found');
|
|
494
|
+
assert.strictEqual(result.f0s1e998.error, 'stale');
|
|
495
495
|
});
|
|
496
496
|
});
|
|
497
497
|
|
|
@@ -504,7 +504,7 @@ describe('executeRefAt', () => {
|
|
|
504
504
|
const session = createMockPageController({ refAt: true }).session;
|
|
505
505
|
const result = await executeRefAt(session, { x: 100, y: 200 });
|
|
506
506
|
|
|
507
|
-
assert.strictEqual(result.ref, '
|
|
507
|
+
assert.strictEqual(result.ref, 'f0s1e1');
|
|
508
508
|
assert.strictEqual(result.tag, 'BUTTON');
|
|
509
509
|
assert.strictEqual(result.clickable, true);
|
|
510
510
|
assert.strictEqual(result.existing, false);
|
|
@@ -553,8 +553,8 @@ describe('executeElementsAt', () => {
|
|
|
553
553
|
|
|
554
554
|
assert.ok(result.results);
|
|
555
555
|
assert.strictEqual(result.results.length, 2);
|
|
556
|
-
assert.strictEqual(result.results[0].ref, '
|
|
557
|
-
assert.strictEqual(result.results[1].ref, '
|
|
556
|
+
assert.strictEqual(result.results[0].ref, 'f0s1e1');
|
|
557
|
+
assert.strictEqual(result.results[1].ref, 'f0s1e2');
|
|
558
558
|
});
|
|
559
559
|
|
|
560
560
|
it('should handle empty coordinates array', async () => {
|