cdp-skill 1.0.16 → 1.0.17
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 +4 -4
- package/SKILL.md +276 -170
- package/package.json +9 -8
- package/{src → scripts}/aria/index.js +1 -1
- package/scripts/aria/role-query.js +295 -0
- package/{src → scripts}/aria.js +11 -5
- package/{src → scripts}/capture/console-capture.js +11 -9
- package/{src → scripts}/capture/screenshot-capture.js +8 -9
- package/{src → scripts}/cdp/connection.js +30 -6
- package/{src → scripts}/cdp-skill.js +7 -6
- package/{src → scripts}/diff.js +7 -6
- package/{src → scripts}/dom/LazyResolver.js +23 -12
- package/{src → scripts}/dom/actionability.js +39 -22
- package/{src → scripts}/dom/click-executor.js +90 -53
- package/{src → scripts}/dom/element-locator.js +4 -4
- package/{src → scripts}/dom/fill-executor.js +8 -4
- package/{src → scripts}/dom/input-emulator.js +47 -9
- package/{src → scripts}/dom/react-filler.js +11 -3
- package/{src → scripts}/dom/wait-executor.js +10 -2
- package/{src → scripts}/page/dialog-handler.js +7 -3
- package/{src → scripts}/page/dom-stability.js +17 -10
- package/{src → scripts}/page/page-controller.js +41 -34
- package/{src → scripts}/runner/context-helpers.js +7 -0
- package/{src → scripts}/runner/execute-browser.js +3 -118
- package/{src → scripts}/runner/execute-dynamic.js +46 -11
- package/{src → scripts}/runner/execute-form.js +6 -4
- package/{src → scripts}/runner/execute-input.js +127 -100
- package/{src → scripts}/runner/execute-interaction.js +31 -46
- package/{src → scripts}/runner/execute-navigation.js +14 -12
- package/{src → scripts}/runner/step-executors.js +28 -9
- package/{src → scripts}/runner/step-registry.js +57 -8
- package/{src → scripts}/runner/step-validator.js +13 -3
- package/{src → scripts}/tests/ExecuteInput.test.js +58 -188
- package/src/aria/role-query.js +0 -1229
- package/src/aria/snapshot.js +0 -459
- /package/{src → scripts}/aria/output-processor.js +0 -0
- /package/{src → scripts}/capture/debug-capture.js +0 -0
- /package/{src → scripts}/capture/error-aggregator.js +0 -0
- /package/{src → scripts}/capture/eval-serializer.js +0 -0
- /package/{src → scripts}/capture/index.js +0 -0
- /package/{src → scripts}/capture/network-capture.js +0 -0
- /package/{src → scripts}/capture/pdf-capture.js +0 -0
- /package/{src → scripts}/cdp/browser.js +0 -0
- /package/{src → scripts}/cdp/discovery.js +0 -0
- /package/{src → scripts}/cdp/index.js +0 -0
- /package/{src → scripts}/cdp/target-and-session.js +0 -0
- /package/{src → scripts}/constants.js +0 -0
- /package/{src → scripts}/dom/element-handle.js +0 -0
- /package/{src → scripts}/dom/element-validator.js +0 -0
- /package/{src → scripts}/dom/index.js +0 -0
- /package/{src → scripts}/dom/keyboard-executor.js +0 -0
- /package/{src → scripts}/dom/quad-helpers.js +0 -0
- /package/{src → scripts}/index.js +0 -0
- /package/{src → scripts}/page/cookie-manager.js +0 -0
- /package/{src → scripts}/page/index.js +0 -0
- /package/{src → scripts}/page/wait-utilities.js +0 -0
- /package/{src → scripts}/page/web-storage-manager.js +0 -0
- /package/{src → scripts}/runner/execute-query.js +0 -0
- /package/{src → scripts}/runner/index.js +0 -0
- /package/{src → scripts}/tests/Actionability.test.js +0 -0
- /package/{src → scripts}/tests/Aria.test.js +0 -0
- /package/{src → scripts}/tests/BrowserClient.test.js +0 -0
- /package/{src → scripts}/tests/CDPConnection.test.js +0 -0
- /package/{src → scripts}/tests/ChromeDiscovery.test.js +0 -0
- /package/{src → scripts}/tests/ClickExecutor.test.js +0 -0
- /package/{src → scripts}/tests/ConsoleCapture.test.js +0 -0
- /package/{src → scripts}/tests/ContextHelpers.test.js +0 -0
- /package/{src → scripts}/tests/CookieManager.test.js +0 -0
- /package/{src → scripts}/tests/DebugCapture.test.js +0 -0
- /package/{src → scripts}/tests/ElementHandle.test.js +0 -0
- /package/{src → scripts}/tests/ElementLocator.test.js +0 -0
- /package/{src → scripts}/tests/ErrorAggregator.test.js +0 -0
- /package/{src → scripts}/tests/EvalSerializer.test.js +0 -0
- /package/{src → scripts}/tests/ExecuteBrowser.test.js +0 -0
- /package/{src → scripts}/tests/ExecuteDynamic.test.js +0 -0
- /package/{src → scripts}/tests/ExecuteForm.test.js +0 -0
- /package/{src → scripts}/tests/ExecuteInteraction.test.js +0 -0
- /package/{src → scripts}/tests/ExecuteQuery.test.js +0 -0
- /package/{src → scripts}/tests/FillExecutor.test.js +0 -0
- /package/{src → scripts}/tests/InputEmulator.test.js +0 -0
- /package/{src → scripts}/tests/KeyboardExecutor.test.js +0 -0
- /package/{src → scripts}/tests/LazyResolver.test.js +0 -0
- /package/{src → scripts}/tests/NetworkErrorCapture.test.js +0 -0
- /package/{src → scripts}/tests/PageController.test.js +0 -0
- /package/{src → scripts}/tests/PdfCapture.test.js +0 -0
- /package/{src → scripts}/tests/ScreenshotCapture.test.js +0 -0
- /package/{src → scripts}/tests/SessionRegistry.test.js +0 -0
- /package/{src → scripts}/tests/StepValidator.test.js +0 -0
- /package/{src → scripts}/tests/TargetManager.test.js +0 -0
- /package/{src → scripts}/tests/TestRunner.test.js +0 -0
- /package/{src → scripts}/tests/WaitStrategy.test.js +0 -0
- /package/{src → scripts}/tests/WaitUtilities.test.js +0 -0
- /package/{src → scripts}/tests/WebStorageManager.test.js +0 -0
- /package/{src → scripts}/tests/integration.test.js +0 -0
- /package/{src → scripts}/types.js +0 -0
- /package/{src → scripts}/utils/backoff.js +0 -0
- /package/{src → scripts}/utils/cdp-helpers.js +0 -0
- /package/{src → scripts}/utils/devices.js +0 -0
- /package/{src → scripts}/utils/errors.js +0 -0
- /package/{src → scripts}/utils/index.js +0 -0
- /package/{src → scripts}/utils/temp.js +0 -0
- /package/{src → scripts}/utils/validators.js +0 -0
- /package/{src → scripts}/utils.js +0 -0
|
@@ -2,7 +2,6 @@ import { describe, it, mock, beforeEach, afterEach } from 'node:test';
|
|
|
2
2
|
import assert from 'node:assert';
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
|
-
executeFill,
|
|
6
5
|
executeFillActive,
|
|
7
6
|
executeSelectOption
|
|
8
7
|
} from '../runner/execute-input.js';
|
|
@@ -103,203 +102,74 @@ function createMockInputEmulator() {
|
|
|
103
102
|
}
|
|
104
103
|
|
|
105
104
|
function createMockPageController(opts = {}) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
result: {
|
|
113
|
-
value: {
|
|
114
|
-
error: 'No element is focused'
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
if (opts.notEditable) {
|
|
120
|
-
return Promise.resolve({
|
|
121
|
-
result: {
|
|
122
|
-
value: {
|
|
123
|
-
error: 'Focused element is not editable',
|
|
124
|
-
tag: 'DIV'
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
});
|
|
105
|
+
const evaluateResult = () => {
|
|
106
|
+
if (opts.noFocus) {
|
|
107
|
+
return Promise.resolve({
|
|
108
|
+
result: {
|
|
109
|
+
value: {
|
|
110
|
+
error: 'No element is focused'
|
|
128
111
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
if (opts.notEditable) {
|
|
116
|
+
return Promise.resolve({
|
|
117
|
+
result: {
|
|
118
|
+
value: {
|
|
119
|
+
error: 'Focused element is not editable',
|
|
120
|
+
tag: 'DIV'
|
|
138
121
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
if (opts.disabled) {
|
|
126
|
+
return Promise.resolve({
|
|
127
|
+
result: {
|
|
128
|
+
value: {
|
|
129
|
+
error: 'Focused element is disabled',
|
|
130
|
+
tag: 'INPUT'
|
|
148
131
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
if (opts.readonly) {
|
|
136
|
+
return Promise.resolve({
|
|
137
|
+
result: {
|
|
138
|
+
value: {
|
|
139
|
+
error: 'Focused element is readonly',
|
|
140
|
+
tag: 'INPUT'
|
|
156
141
|
}
|
|
157
|
-
return Promise.resolve({
|
|
158
|
-
result: {
|
|
159
|
-
value: {
|
|
160
|
-
editable: true,
|
|
161
|
-
tag: 'INPUT',
|
|
162
|
-
type: 'text',
|
|
163
|
-
selector: '#username',
|
|
164
|
-
valueBefore: ''
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
142
|
}
|
|
169
|
-
|
|
170
|
-
})
|
|
143
|
+
});
|
|
171
144
|
}
|
|
172
|
-
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// ---------------------------------------------------------------------------
|
|
176
|
-
// Tests: executeFill
|
|
177
|
-
// ---------------------------------------------------------------------------
|
|
178
|
-
|
|
179
|
-
describe('executeFill', () => {
|
|
180
|
-
afterEach(() => { mock.reset(); });
|
|
181
|
-
|
|
182
|
-
it('should throw if selector is missing', async () => {
|
|
183
|
-
const locator = createMockElementLocator();
|
|
184
|
-
const emulator = createMockInputEmulator();
|
|
185
|
-
|
|
186
|
-
await assert.rejects(
|
|
187
|
-
executeFill(locator, emulator, { value: 'test' }),
|
|
188
|
-
{ message: 'Fill requires selector and value' }
|
|
189
|
-
);
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it('should throw if value is missing', async () => {
|
|
193
|
-
const locator = createMockElementLocator();
|
|
194
|
-
const emulator = createMockInputEmulator();
|
|
195
|
-
|
|
196
|
-
await assert.rejects(
|
|
197
|
-
executeFill(locator, emulator, { selector: '#input' }),
|
|
198
|
-
{ message: 'Fill requires selector and value' }
|
|
199
|
-
);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
it('should throw if element not found', async () => {
|
|
203
|
-
const locator = createMockElementLocator({ notFound: true });
|
|
204
|
-
const emulator = createMockInputEmulator();
|
|
205
|
-
|
|
206
|
-
await assert.rejects(
|
|
207
|
-
executeFill(locator, emulator, { selector: '#missing', value: 'test' }),
|
|
208
|
-
{ message: /element not found/i }
|
|
209
|
-
);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
it('should throw if element is not editable', async () => {
|
|
213
|
-
const locator = createMockElementLocator({ notEditable: true });
|
|
214
|
-
const emulator = createMockInputEmulator();
|
|
215
|
-
|
|
216
|
-
await assert.rejects(
|
|
217
|
-
executeFill(locator, emulator, { selector: '#disabled', value: 'test' }),
|
|
218
|
-
{ message: /not editable/i }
|
|
219
|
-
);
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
it('should throw if element is not actionable after all scroll strategies', async () => {
|
|
223
|
-
const locator = createMockElementLocator({ actionable: false, reason: 'Element is covered' });
|
|
224
|
-
const emulator = createMockInputEmulator();
|
|
225
|
-
|
|
226
|
-
await assert.rejects(
|
|
227
|
-
executeFill(locator, emulator, { selector: '#input', value: 'test' }),
|
|
228
|
-
{ message: /not actionable/i }
|
|
229
|
-
);
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
it('should fill element with standard approach', async () => {
|
|
233
|
-
const locator = createMockElementLocator();
|
|
234
|
-
const emulator = createMockInputEmulator();
|
|
235
|
-
|
|
236
|
-
await executeFill(locator, emulator, { selector: '#input', value: 'hello' });
|
|
237
|
-
|
|
238
|
-
assert.strictEqual(locator.findElement.mock.calls.length, 1);
|
|
239
|
-
assert.strictEqual(emulator.click.mock.calls.length, 1);
|
|
240
|
-
assert.strictEqual(emulator.selectAll.mock.calls.length, 1);
|
|
241
|
-
assert.strictEqual(emulator.type.mock.calls.length, 1);
|
|
242
|
-
assert.strictEqual(emulator.type.mock.calls[0].arguments[0], 'hello');
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
it('should skip clear if clear option is false', async () => {
|
|
246
|
-
const locator = createMockElementLocator();
|
|
247
|
-
const emulator = createMockInputEmulator();
|
|
248
|
-
|
|
249
|
-
await executeFill(locator, emulator, { selector: '#input', value: 'hello', clear: false });
|
|
250
|
-
|
|
251
|
-
assert.strictEqual(emulator.selectAll.mock.calls.length, 0);
|
|
252
|
-
assert.strictEqual(emulator.type.mock.calls.length, 1);
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
it('should use React filler if react option is true', async () => {
|
|
256
|
-
const locator = createMockElementLocator();
|
|
257
|
-
const emulator = createMockInputEmulator();
|
|
258
|
-
|
|
259
|
-
// Mock createReactInputFiller
|
|
260
|
-
await executeFill(locator, emulator, { selector: '#input', value: 'hello', react: true });
|
|
261
|
-
|
|
262
|
-
// React mode skips click and type
|
|
263
|
-
assert.strictEqual(emulator.click.mock.calls.length, 0);
|
|
264
|
-
assert.strictEqual(emulator.type.mock.calls.length, 0);
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
it('should dispose element handle on success', async () => {
|
|
268
|
-
const locator = createMockElementLocator();
|
|
269
|
-
const emulator = createMockInputEmulator();
|
|
270
|
-
|
|
271
|
-
await executeFill(locator, emulator, { selector: '#input', value: 'test' });
|
|
272
|
-
|
|
273
|
-
const element = await locator.findElement('#input');
|
|
274
|
-
// Can't directly check if dispose was called, but ensure no errors
|
|
275
|
-
assert.ok(element);
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
it('should try multiple scroll strategies if element not immediately actionable', async () => {
|
|
279
|
-
let callCount = 0;
|
|
280
|
-
const locator = createMockElementLocator({
|
|
281
|
-
actionable: true
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
// Override isActionable to succeed on second call
|
|
285
|
-
const originalHandle = await locator.findElement('#input');
|
|
286
|
-
originalHandle._handle.isActionable = mock.fn(() => {
|
|
287
|
-
callCount++;
|
|
145
|
+
if (opts.exception) {
|
|
288
146
|
return Promise.resolve({
|
|
289
|
-
|
|
290
|
-
|
|
147
|
+
result: { value: undefined },
|
|
148
|
+
exceptionDetails: {
|
|
149
|
+
text: opts.exception
|
|
150
|
+
}
|
|
291
151
|
});
|
|
152
|
+
}
|
|
153
|
+
return Promise.resolve({
|
|
154
|
+
result: {
|
|
155
|
+
value: {
|
|
156
|
+
editable: true,
|
|
157
|
+
tag: 'INPUT',
|
|
158
|
+
type: 'text',
|
|
159
|
+
selector: '#username',
|
|
160
|
+
valueBefore: ''
|
|
161
|
+
}
|
|
162
|
+
}
|
|
292
163
|
});
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
const emulator = createMockInputEmulator();
|
|
296
|
-
|
|
297
|
-
await executeFill(locator, emulator, { selector: '#input', value: 'test' });
|
|
164
|
+
};
|
|
298
165
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
}
|
|
166
|
+
return {
|
|
167
|
+
session: {
|
|
168
|
+
send: mock.fn(() => Promise.resolve({}))
|
|
169
|
+
},
|
|
170
|
+
evaluateInFrame: mock.fn(() => evaluateResult())
|
|
171
|
+
};
|
|
172
|
+
}
|
|
303
173
|
|
|
304
174
|
// ---------------------------------------------------------------------------
|
|
305
175
|
// Tests: executeFillActive
|