cdp-skill 1.0.2 → 1.0.4
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 +3 -0
- package/SKILL.md +34 -5
- package/package.json +2 -1
- package/src/capture/console-capture.js +241 -0
- package/src/capture/debug-capture.js +144 -0
- package/src/capture/error-aggregator.js +151 -0
- package/src/capture/eval-serializer.js +320 -0
- package/src/capture/index.js +40 -0
- package/src/capture/network-capture.js +211 -0
- package/src/capture/pdf-capture.js +256 -0
- package/src/capture/screenshot-capture.js +325 -0
- package/src/cdp/browser.js +569 -0
- package/src/cdp/connection.js +369 -0
- package/src/cdp/discovery.js +138 -0
- package/src/cdp/index.js +29 -0
- package/src/cdp/target-and-session.js +439 -0
- package/src/cdp-skill.js +25 -11
- package/src/constants.js +79 -0
- package/src/dom/actionability.js +638 -0
- package/src/dom/click-executor.js +923 -0
- package/src/dom/element-handle.js +496 -0
- package/src/dom/element-locator.js +475 -0
- package/src/dom/element-validator.js +120 -0
- package/src/dom/fill-executor.js +489 -0
- package/src/dom/index.js +248 -0
- package/src/dom/input-emulator.js +406 -0
- package/src/dom/keyboard-executor.js +202 -0
- package/src/dom/quad-helpers.js +89 -0
- package/src/dom/react-filler.js +94 -0
- package/src/dom/wait-executor.js +423 -0
- package/src/index.js +6 -6
- package/src/page/cookie-manager.js +202 -0
- package/src/page/dom-stability.js +181 -0
- package/src/page/index.js +36 -0
- package/src/{page.js → page/page-controller.js} +109 -839
- package/src/page/wait-utilities.js +302 -0
- package/src/page/web-storage-manager.js +108 -0
- package/src/runner/context-helpers.js +224 -0
- package/src/runner/execute-browser.js +518 -0
- package/src/runner/execute-form.js +315 -0
- package/src/runner/execute-input.js +308 -0
- package/src/runner/execute-interaction.js +672 -0
- package/src/runner/execute-navigation.js +180 -0
- package/src/runner/execute-query.js +771 -0
- package/src/runner/index.js +51 -0
- package/src/runner/step-executors.js +421 -0
- package/src/runner/step-validator.js +641 -0
- package/src/tests/Actionability.test.js +613 -0
- package/src/tests/BrowserClient.test.js +1 -1
- package/src/tests/ChromeDiscovery.test.js +1 -1
- package/src/tests/ClickExecutor.test.js +554 -0
- package/src/tests/ConsoleCapture.test.js +1 -1
- package/src/tests/ContextHelpers.test.js +453 -0
- package/src/tests/CookieManager.test.js +450 -0
- package/src/tests/DebugCapture.test.js +307 -0
- package/src/tests/ElementHandle.test.js +1 -1
- package/src/tests/ElementLocator.test.js +1 -1
- package/src/tests/ErrorAggregator.test.js +1 -1
- package/src/tests/EvalSerializer.test.js +391 -0
- package/src/tests/FillExecutor.test.js +611 -0
- package/src/tests/InputEmulator.test.js +1 -1
- package/src/tests/KeyboardExecutor.test.js +430 -0
- package/src/tests/NetworkErrorCapture.test.js +1 -1
- package/src/tests/PageController.test.js +1 -1
- package/src/tests/PdfCapture.test.js +333 -0
- package/src/tests/ScreenshotCapture.test.js +1 -1
- package/src/tests/SessionRegistry.test.js +1 -1
- package/src/tests/StepValidator.test.js +527 -0
- package/src/tests/TargetManager.test.js +1 -1
- package/src/tests/TestRunner.test.js +1 -1
- package/src/tests/WaitStrategy.test.js +1 -1
- package/src/tests/WaitUtilities.test.js +508 -0
- package/src/tests/WebStorageManager.test.js +333 -0
- package/src/types.js +309 -0
- package/src/capture.js +0 -1400
- package/src/cdp.js +0 -1286
- package/src/dom.js +0 -4379
- package/src/runner.js +0 -3676
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
import { describe, it, mock, beforeEach, afterEach } from 'node:test';
|
|
2
|
+
import assert from 'node:assert';
|
|
3
|
+
import { createKeyboardExecutor } from '../dom/keyboard-executor.js';
|
|
4
|
+
|
|
5
|
+
describe('KeyboardExecutor', () => {
|
|
6
|
+
let mockSession;
|
|
7
|
+
let mockElementLocator;
|
|
8
|
+
let mockInputEmulator;
|
|
9
|
+
let executor;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
mockSession = {
|
|
13
|
+
send: mock.fn(async () => ({}))
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const createMockElement = () => ({
|
|
17
|
+
_handle: {
|
|
18
|
+
objectId: 'obj-123',
|
|
19
|
+
scrollIntoView: mock.fn(async () => {}),
|
|
20
|
+
waitForStability: mock.fn(async () => {}),
|
|
21
|
+
focus: mock.fn(async () => {}),
|
|
22
|
+
dispose: mock.fn(async () => {})
|
|
23
|
+
},
|
|
24
|
+
objectId: 'obj-123'
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
mockElementLocator = {
|
|
28
|
+
findElement: mock.fn(async () => createMockElement())
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
mockInputEmulator = {
|
|
32
|
+
type: mock.fn(async () => {})
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
executor = createKeyboardExecutor(mockSession, mockElementLocator, mockInputEmulator);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
afterEach(() => {
|
|
39
|
+
mock.reset();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe('createKeyboardExecutor', () => {
|
|
43
|
+
it('should return an object with expected methods', () => {
|
|
44
|
+
assert.ok(typeof executor.executeType === 'function');
|
|
45
|
+
assert.ok(typeof executor.executeSelect === 'function');
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('executeType', () => {
|
|
50
|
+
it('should throw if selector is not provided', async () => {
|
|
51
|
+
await assert.rejects(
|
|
52
|
+
() => executor.executeType({ text: 'hello' }),
|
|
53
|
+
{ message: 'Type requires selector and text' }
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should throw if text is not provided', async () => {
|
|
58
|
+
await assert.rejects(
|
|
59
|
+
() => executor.executeType({ selector: '#input' }),
|
|
60
|
+
{ message: 'Type requires selector and text' }
|
|
61
|
+
);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should throw when element not found', async () => {
|
|
65
|
+
mockElementLocator.findElement = mock.fn(async () => null);
|
|
66
|
+
|
|
67
|
+
await assert.rejects(
|
|
68
|
+
() => executor.executeType({ selector: '#missing', text: 'hello' }),
|
|
69
|
+
(err) => {
|
|
70
|
+
assert.ok(err.message.includes('not found'));
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should type text into element', async () => {
|
|
77
|
+
mockSession.send = mock.fn(async (method, params) => {
|
|
78
|
+
if (method === 'Runtime.callFunctionOn') {
|
|
79
|
+
return { result: { value: { editable: true } } };
|
|
80
|
+
}
|
|
81
|
+
return {};
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const result = await executor.executeType({ selector: '#input', text: 'hello world' });
|
|
85
|
+
|
|
86
|
+
assert.strictEqual(result.selector, '#input');
|
|
87
|
+
assert.strictEqual(result.typed, 'hello world');
|
|
88
|
+
assert.strictEqual(result.length, 11);
|
|
89
|
+
assert.strictEqual(mockInputEmulator.type.mock.calls.length, 1);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should pass delay option to input emulator', async () => {
|
|
93
|
+
mockSession.send = mock.fn(async (method, params) => {
|
|
94
|
+
if (method === 'Runtime.callFunctionOn') {
|
|
95
|
+
return { result: { value: { editable: true } } };
|
|
96
|
+
}
|
|
97
|
+
return {};
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
await executor.executeType({ selector: '#input', text: 'test', delay: 50 });
|
|
101
|
+
|
|
102
|
+
const typeCall = mockInputEmulator.type.mock.calls[0];
|
|
103
|
+
assert.deepStrictEqual(typeCall.arguments, ['test', { delay: 50 }]);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should throw when element is not editable', async () => {
|
|
107
|
+
mockSession.send = mock.fn(async () => ({
|
|
108
|
+
result: { value: { editable: false, reason: 'readonly' } }
|
|
109
|
+
}));
|
|
110
|
+
|
|
111
|
+
await assert.rejects(
|
|
112
|
+
() => executor.executeType({ selector: '#readonly', text: 'test' }),
|
|
113
|
+
(err) => {
|
|
114
|
+
assert.ok(err.message.includes('not editable'));
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('should scroll element into view before typing', async () => {
|
|
121
|
+
mockSession.send = mock.fn(async () => ({
|
|
122
|
+
result: { value: { editable: true } }
|
|
123
|
+
}));
|
|
124
|
+
|
|
125
|
+
const mockElement = {
|
|
126
|
+
_handle: {
|
|
127
|
+
objectId: 'obj-123',
|
|
128
|
+
scrollIntoView: mock.fn(async () => {}),
|
|
129
|
+
waitForStability: mock.fn(async () => {}),
|
|
130
|
+
focus: mock.fn(async () => {}),
|
|
131
|
+
dispose: mock.fn(async () => {})
|
|
132
|
+
},
|
|
133
|
+
objectId: 'obj-123'
|
|
134
|
+
};
|
|
135
|
+
mockElementLocator.findElement = mock.fn(async () => mockElement);
|
|
136
|
+
|
|
137
|
+
await executor.executeType({ selector: '#input', text: 'test' });
|
|
138
|
+
|
|
139
|
+
assert.strictEqual(mockElement._handle.scrollIntoView.mock.calls.length, 1);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('should focus element before typing', async () => {
|
|
143
|
+
mockSession.send = mock.fn(async () => ({
|
|
144
|
+
result: { value: { editable: true } }
|
|
145
|
+
}));
|
|
146
|
+
|
|
147
|
+
const mockElement = {
|
|
148
|
+
_handle: {
|
|
149
|
+
objectId: 'obj-123',
|
|
150
|
+
scrollIntoView: mock.fn(async () => {}),
|
|
151
|
+
waitForStability: mock.fn(async () => {}),
|
|
152
|
+
focus: mock.fn(async () => {}),
|
|
153
|
+
dispose: mock.fn(async () => {})
|
|
154
|
+
},
|
|
155
|
+
objectId: 'obj-123'
|
|
156
|
+
};
|
|
157
|
+
mockElementLocator.findElement = mock.fn(async () => mockElement);
|
|
158
|
+
|
|
159
|
+
await executor.executeType({ selector: '#input', text: 'test' });
|
|
160
|
+
|
|
161
|
+
assert.strictEqual(mockElement._handle.focus.mock.calls.length, 1);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('should dispose element handle after typing', async () => {
|
|
165
|
+
mockSession.send = mock.fn(async () => ({
|
|
166
|
+
result: { value: { editable: true } }
|
|
167
|
+
}));
|
|
168
|
+
|
|
169
|
+
const mockElement = {
|
|
170
|
+
_handle: {
|
|
171
|
+
objectId: 'obj-123',
|
|
172
|
+
scrollIntoView: mock.fn(async () => {}),
|
|
173
|
+
waitForStability: mock.fn(async () => {}),
|
|
174
|
+
focus: mock.fn(async () => {}),
|
|
175
|
+
dispose: mock.fn(async () => {})
|
|
176
|
+
},
|
|
177
|
+
objectId: 'obj-123'
|
|
178
|
+
};
|
|
179
|
+
mockElementLocator.findElement = mock.fn(async () => mockElement);
|
|
180
|
+
|
|
181
|
+
await executor.executeType({ selector: '#input', text: 'test' });
|
|
182
|
+
|
|
183
|
+
assert.strictEqual(mockElement._handle.dispose.mock.calls.length, 1);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('should convert non-string text to string', async () => {
|
|
187
|
+
mockSession.send = mock.fn(async () => ({
|
|
188
|
+
result: { value: { editable: true } }
|
|
189
|
+
}));
|
|
190
|
+
|
|
191
|
+
const result = await executor.executeType({ selector: '#input', text: 12345 });
|
|
192
|
+
|
|
193
|
+
assert.strictEqual(result.typed, '12345');
|
|
194
|
+
assert.strictEqual(result.length, 5);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
describe('executeSelect', () => {
|
|
199
|
+
it('should throw if selector is not provided as string', async () => {
|
|
200
|
+
await assert.rejects(
|
|
201
|
+
() => executor.executeSelect(null),
|
|
202
|
+
{ message: 'Select requires a selector string or params object' }
|
|
203
|
+
);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('should throw if params object has no selector', async () => {
|
|
207
|
+
await assert.rejects(
|
|
208
|
+
() => executor.executeSelect({ start: 0, end: 5 }),
|
|
209
|
+
{ message: 'Select requires selector' }
|
|
210
|
+
);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('should throw when element not found', async () => {
|
|
214
|
+
mockElementLocator.findElement = mock.fn(async () => null);
|
|
215
|
+
|
|
216
|
+
await assert.rejects(
|
|
217
|
+
() => executor.executeSelect('#missing'),
|
|
218
|
+
(err) => {
|
|
219
|
+
assert.ok(err.message.includes('not found'));
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it('should select all text with string selector', async () => {
|
|
226
|
+
mockSession.send = mock.fn(async () => ({
|
|
227
|
+
result: {
|
|
228
|
+
value: {
|
|
229
|
+
success: true,
|
|
230
|
+
start: 0,
|
|
231
|
+
end: 10,
|
|
232
|
+
selectedText: 'hello test',
|
|
233
|
+
totalLength: 10
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}));
|
|
237
|
+
|
|
238
|
+
const result = await executor.executeSelect('#input');
|
|
239
|
+
|
|
240
|
+
assert.strictEqual(result.selector, '#input');
|
|
241
|
+
assert.strictEqual(result.start, 0);
|
|
242
|
+
assert.strictEqual(result.end, 10);
|
|
243
|
+
assert.strictEqual(result.selectedText, 'hello test');
|
|
244
|
+
assert.strictEqual(result.totalLength, 10);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it('should select text range with start and end', async () => {
|
|
248
|
+
mockSession.send = mock.fn(async () => ({
|
|
249
|
+
result: {
|
|
250
|
+
value: {
|
|
251
|
+
success: true,
|
|
252
|
+
start: 2,
|
|
253
|
+
end: 7,
|
|
254
|
+
selectedText: 'llo t',
|
|
255
|
+
totalLength: 10
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}));
|
|
259
|
+
|
|
260
|
+
const result = await executor.executeSelect({ selector: '#input', start: 2, end: 7 });
|
|
261
|
+
|
|
262
|
+
assert.strictEqual(result.start, 2);
|
|
263
|
+
assert.strictEqual(result.end, 7);
|
|
264
|
+
assert.strictEqual(result.selectedText, 'llo t');
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('should throw when selection fails', async () => {
|
|
268
|
+
mockSession.send = mock.fn(async () => ({
|
|
269
|
+
result: {
|
|
270
|
+
value: {
|
|
271
|
+
success: false,
|
|
272
|
+
reason: 'Element does not support text selection'
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}));
|
|
276
|
+
|
|
277
|
+
await assert.rejects(
|
|
278
|
+
() => executor.executeSelect('#div'),
|
|
279
|
+
{ message: 'Element does not support text selection' }
|
|
280
|
+
);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it('should scroll element into view before selecting', async () => {
|
|
284
|
+
mockSession.send = mock.fn(async () => ({
|
|
285
|
+
result: {
|
|
286
|
+
value: {
|
|
287
|
+
success: true,
|
|
288
|
+
start: 0,
|
|
289
|
+
end: 5,
|
|
290
|
+
selectedText: 'hello',
|
|
291
|
+
totalLength: 5
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}));
|
|
295
|
+
|
|
296
|
+
const mockElement = {
|
|
297
|
+
_handle: {
|
|
298
|
+
objectId: 'obj-123',
|
|
299
|
+
scrollIntoView: mock.fn(async () => {}),
|
|
300
|
+
waitForStability: mock.fn(async () => {}),
|
|
301
|
+
focus: mock.fn(async () => {}),
|
|
302
|
+
dispose: mock.fn(async () => {})
|
|
303
|
+
},
|
|
304
|
+
objectId: 'obj-123'
|
|
305
|
+
};
|
|
306
|
+
mockElementLocator.findElement = mock.fn(async () => mockElement);
|
|
307
|
+
|
|
308
|
+
await executor.executeSelect('#input');
|
|
309
|
+
|
|
310
|
+
assert.strictEqual(mockElement._handle.scrollIntoView.mock.calls.length, 1);
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it('should focus element before selecting', async () => {
|
|
314
|
+
mockSession.send = mock.fn(async () => ({
|
|
315
|
+
result: {
|
|
316
|
+
value: {
|
|
317
|
+
success: true,
|
|
318
|
+
start: 0,
|
|
319
|
+
end: 5,
|
|
320
|
+
selectedText: 'hello',
|
|
321
|
+
totalLength: 5
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}));
|
|
325
|
+
|
|
326
|
+
const mockElement = {
|
|
327
|
+
_handle: {
|
|
328
|
+
objectId: 'obj-123',
|
|
329
|
+
scrollIntoView: mock.fn(async () => {}),
|
|
330
|
+
waitForStability: mock.fn(async () => {}),
|
|
331
|
+
focus: mock.fn(async () => {}),
|
|
332
|
+
dispose: mock.fn(async () => {})
|
|
333
|
+
},
|
|
334
|
+
objectId: 'obj-123'
|
|
335
|
+
};
|
|
336
|
+
mockElementLocator.findElement = mock.fn(async () => mockElement);
|
|
337
|
+
|
|
338
|
+
await executor.executeSelect('#input');
|
|
339
|
+
|
|
340
|
+
assert.strictEqual(mockElement._handle.focus.mock.calls.length, 1);
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
it('should dispose element handle after selection', async () => {
|
|
344
|
+
mockSession.send = mock.fn(async () => ({
|
|
345
|
+
result: {
|
|
346
|
+
value: {
|
|
347
|
+
success: true,
|
|
348
|
+
start: 0,
|
|
349
|
+
end: 5,
|
|
350
|
+
selectedText: 'hello',
|
|
351
|
+
totalLength: 5
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}));
|
|
355
|
+
|
|
356
|
+
const mockElement = {
|
|
357
|
+
_handle: {
|
|
358
|
+
objectId: 'obj-123',
|
|
359
|
+
scrollIntoView: mock.fn(async () => {}),
|
|
360
|
+
waitForStability: mock.fn(async () => {}),
|
|
361
|
+
focus: mock.fn(async () => {}),
|
|
362
|
+
dispose: mock.fn(async () => {})
|
|
363
|
+
},
|
|
364
|
+
objectId: 'obj-123'
|
|
365
|
+
};
|
|
366
|
+
mockElementLocator.findElement = mock.fn(async () => mockElement);
|
|
367
|
+
|
|
368
|
+
await executor.executeSelect('#input');
|
|
369
|
+
|
|
370
|
+
assert.strictEqual(mockElement._handle.dispose.mock.calls.length, 1);
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
it('should handle contenteditable elements', async () => {
|
|
374
|
+
mockSession.send = mock.fn(async () => ({
|
|
375
|
+
result: {
|
|
376
|
+
value: {
|
|
377
|
+
success: true,
|
|
378
|
+
start: 0,
|
|
379
|
+
end: 15,
|
|
380
|
+
selectedText: 'editable text!',
|
|
381
|
+
totalLength: 15
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}));
|
|
385
|
+
|
|
386
|
+
const result = await executor.executeSelect('#contenteditable');
|
|
387
|
+
|
|
388
|
+
assert.strictEqual(result.success, undefined); // Only success is not passed to result
|
|
389
|
+
assert.strictEqual(result.selectedText, 'editable text!');
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
it('should handle selection with only start index', async () => {
|
|
393
|
+
mockSession.send = mock.fn(async () => ({
|
|
394
|
+
result: {
|
|
395
|
+
value: {
|
|
396
|
+
success: true,
|
|
397
|
+
start: 5,
|
|
398
|
+
end: 10,
|
|
399
|
+
selectedText: ' test',
|
|
400
|
+
totalLength: 10
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}));
|
|
404
|
+
|
|
405
|
+
const result = await executor.executeSelect({ selector: '#input', start: 5 });
|
|
406
|
+
|
|
407
|
+
assert.strictEqual(result.start, 5);
|
|
408
|
+
assert.strictEqual(result.end, 10);
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
it('should handle selection with only end index', async () => {
|
|
412
|
+
mockSession.send = mock.fn(async () => ({
|
|
413
|
+
result: {
|
|
414
|
+
value: {
|
|
415
|
+
success: true,
|
|
416
|
+
start: 0,
|
|
417
|
+
end: 5,
|
|
418
|
+
selectedText: 'hello',
|
|
419
|
+
totalLength: 10
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}));
|
|
423
|
+
|
|
424
|
+
const result = await executor.executeSelect({ selector: '#input', end: 5 });
|
|
425
|
+
|
|
426
|
+
assert.strictEqual(result.start, 0);
|
|
427
|
+
assert.strictEqual(result.end, 5);
|
|
428
|
+
});
|
|
429
|
+
});
|
|
430
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it, mock, beforeEach, afterEach } from 'node:test';
|
|
2
2
|
import assert from 'node:assert';
|
|
3
|
-
import { createNetworkCapture } from '../capture.js';
|
|
3
|
+
import { createNetworkCapture } from '../capture/index.js';
|
|
4
4
|
|
|
5
5
|
describe('NetworkErrorCapture', () => {
|
|
6
6
|
let networkCapture;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it, mock, beforeEach, afterEach } from 'node:test';
|
|
2
2
|
import assert from 'node:assert';
|
|
3
|
-
import { createPageController, WaitCondition } from '../page.js';
|
|
3
|
+
import { createPageController, WaitCondition } from '../page/index.js';
|
|
4
4
|
import { ErrorTypes } from '../utils.js';
|
|
5
5
|
|
|
6
6
|
describe('PageController', () => {
|