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,450 @@
|
|
|
1
|
+
import { describe, it, mock, beforeEach, afterEach } from 'node:test';
|
|
2
|
+
import assert from 'node:assert';
|
|
3
|
+
import { createCookieManager } from '../page/cookie-manager.js';
|
|
4
|
+
|
|
5
|
+
describe('CookieManager', () => {
|
|
6
|
+
let mockSession;
|
|
7
|
+
let manager;
|
|
8
|
+
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
mockSession = {
|
|
11
|
+
send: mock.fn(async () => ({}))
|
|
12
|
+
};
|
|
13
|
+
manager = createCookieManager(mockSession);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
mock.reset();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe('createCookieManager', () => {
|
|
21
|
+
it('should return an object with expected methods', () => {
|
|
22
|
+
assert.ok(typeof manager.getCookies === 'function');
|
|
23
|
+
assert.ok(typeof manager.setCookies === 'function');
|
|
24
|
+
assert.ok(typeof manager.clearCookies === 'function');
|
|
25
|
+
assert.ok(typeof manager.deleteCookies === 'function');
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe('getCookies', () => {
|
|
30
|
+
it('should return all cookies when no URLs provided', async () => {
|
|
31
|
+
mockSession.send = mock.fn(async () => ({
|
|
32
|
+
cookies: [
|
|
33
|
+
{ name: 'session', value: 'abc123', domain: '.example.com', path: '/', httpOnly: true, secure: true },
|
|
34
|
+
{ name: 'prefs', value: 'dark', domain: 'example.com', path: '/', httpOnly: false, secure: false }
|
|
35
|
+
]
|
|
36
|
+
}));
|
|
37
|
+
|
|
38
|
+
const cookies = await manager.getCookies();
|
|
39
|
+
|
|
40
|
+
assert.strictEqual(cookies.length, 2);
|
|
41
|
+
assert.strictEqual(cookies[0].name, 'session');
|
|
42
|
+
assert.strictEqual(cookies[0].value, 'abc123');
|
|
43
|
+
assert.strictEqual(cookies[0].domain, '.example.com');
|
|
44
|
+
assert.strictEqual(cookies[0].httpOnly, true);
|
|
45
|
+
assert.strictEqual(cookies[0].sameSite, 'Lax');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should filter cookies by URL', async () => {
|
|
49
|
+
mockSession.send = mock.fn(async () => ({
|
|
50
|
+
cookies: [
|
|
51
|
+
{ name: 'session', value: 'abc', domain: '.example.com', path: '/', secure: true },
|
|
52
|
+
{ name: 'other', value: 'xyz', domain: 'other.com', path: '/', secure: false }
|
|
53
|
+
]
|
|
54
|
+
}));
|
|
55
|
+
|
|
56
|
+
const cookies = await manager.getCookies(['https://example.com/page']);
|
|
57
|
+
|
|
58
|
+
assert.strictEqual(cookies.length, 1);
|
|
59
|
+
assert.strictEqual(cookies[0].name, 'session');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should match subdomain cookies', async () => {
|
|
63
|
+
mockSession.send = mock.fn(async () => ({
|
|
64
|
+
cookies: [
|
|
65
|
+
{ name: 'session', value: 'abc', domain: '.example.com', path: '/', secure: false }
|
|
66
|
+
]
|
|
67
|
+
}));
|
|
68
|
+
|
|
69
|
+
const cookies = await manager.getCookies(['https://sub.example.com']);
|
|
70
|
+
|
|
71
|
+
assert.strictEqual(cookies.length, 1);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should match path-specific cookies', async () => {
|
|
75
|
+
mockSession.send = mock.fn(async () => ({
|
|
76
|
+
cookies: [
|
|
77
|
+
{ name: 'api_token', value: 'tok', domain: 'example.com', path: '/api', secure: false },
|
|
78
|
+
{ name: 'session', value: 'abc', domain: 'example.com', path: '/', secure: false }
|
|
79
|
+
]
|
|
80
|
+
}));
|
|
81
|
+
|
|
82
|
+
const cookies = await manager.getCookies(['https://example.com/api/users']);
|
|
83
|
+
|
|
84
|
+
assert.strictEqual(cookies.length, 2);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should filter secure cookies for non-HTTPS URLs', async () => {
|
|
88
|
+
mockSession.send = mock.fn(async () => ({
|
|
89
|
+
cookies: [
|
|
90
|
+
{ name: 'secure', value: 'sec', domain: 'example.com', path: '/', secure: true },
|
|
91
|
+
{ name: 'normal', value: 'nor', domain: 'example.com', path: '/', secure: false }
|
|
92
|
+
]
|
|
93
|
+
}));
|
|
94
|
+
|
|
95
|
+
const cookies = await manager.getCookies(['http://example.com']);
|
|
96
|
+
|
|
97
|
+
assert.strictEqual(cookies.length, 1);
|
|
98
|
+
assert.strictEqual(cookies[0].name, 'normal');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should handle empty cookie list', async () => {
|
|
102
|
+
mockSession.send = mock.fn(async () => ({
|
|
103
|
+
cookies: []
|
|
104
|
+
}));
|
|
105
|
+
|
|
106
|
+
const cookies = await manager.getCookies();
|
|
107
|
+
|
|
108
|
+
assert.deepStrictEqual(cookies, []);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('should handle invalid URL in filter', async () => {
|
|
112
|
+
mockSession.send = mock.fn(async () => ({
|
|
113
|
+
cookies: [
|
|
114
|
+
{ name: 'session', value: 'abc', domain: 'example.com', path: '/', secure: false }
|
|
115
|
+
]
|
|
116
|
+
}));
|
|
117
|
+
|
|
118
|
+
const cookies = await manager.getCookies(['not-a-url']);
|
|
119
|
+
|
|
120
|
+
assert.strictEqual(cookies.length, 0);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('should preserve sameSite value if present', async () => {
|
|
124
|
+
mockSession.send = mock.fn(async () => ({
|
|
125
|
+
cookies: [
|
|
126
|
+
{ name: 'strict', value: 'abc', domain: 'example.com', path: '/', sameSite: 'Strict' }
|
|
127
|
+
]
|
|
128
|
+
}));
|
|
129
|
+
|
|
130
|
+
const cookies = await manager.getCookies();
|
|
131
|
+
|
|
132
|
+
assert.strictEqual(cookies[0].sameSite, 'Strict');
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
describe('setCookies', () => {
|
|
137
|
+
it('should set cookies with URL', async () => {
|
|
138
|
+
mockSession.send = mock.fn(async () => ({}));
|
|
139
|
+
|
|
140
|
+
await manager.setCookies([
|
|
141
|
+
{ name: 'session', value: 'abc', url: 'https://example.com' }
|
|
142
|
+
]);
|
|
143
|
+
|
|
144
|
+
const call = mockSession.send.mock.calls[0];
|
|
145
|
+
assert.strictEqual(call.arguments[0], 'Storage.setCookies');
|
|
146
|
+
assert.strictEqual(call.arguments[1].cookies[0].name, 'session');
|
|
147
|
+
assert.strictEqual(call.arguments[1].cookies[0].domain, 'example.com');
|
|
148
|
+
assert.strictEqual(call.arguments[1].cookies[0].secure, true);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('should set cookies with explicit domain', async () => {
|
|
152
|
+
mockSession.send = mock.fn(async () => ({}));
|
|
153
|
+
|
|
154
|
+
await manager.setCookies([
|
|
155
|
+
{ name: 'session', value: 'abc', domain: '.example.com', path: '/app' }
|
|
156
|
+
]);
|
|
157
|
+
|
|
158
|
+
const call = mockSession.send.mock.calls[0];
|
|
159
|
+
assert.strictEqual(call.arguments[1].cookies[0].domain, '.example.com');
|
|
160
|
+
assert.strictEqual(call.arguments[1].cookies[0].path, '/app');
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('should throw for cookie without url or domain', async () => {
|
|
164
|
+
await assert.rejects(
|
|
165
|
+
() => manager.setCookies([{ name: 'session', value: 'abc' }]),
|
|
166
|
+
{ message: 'Cookie requires either url or domain' }
|
|
167
|
+
);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('should throw for invalid URL', async () => {
|
|
171
|
+
await assert.rejects(
|
|
172
|
+
() => manager.setCookies([{ name: 'session', value: 'abc', url: 'not-a-url' }]),
|
|
173
|
+
(err) => {
|
|
174
|
+
assert.ok(err.message.includes('Invalid cookie URL'));
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('should set optional cookie properties', async () => {
|
|
181
|
+
mockSession.send = mock.fn(async () => ({}));
|
|
182
|
+
|
|
183
|
+
await manager.setCookies([
|
|
184
|
+
{
|
|
185
|
+
name: 'session',
|
|
186
|
+
value: 'abc',
|
|
187
|
+
domain: 'example.com',
|
|
188
|
+
expires: 1234567890,
|
|
189
|
+
httpOnly: true,
|
|
190
|
+
sameSite: 'Strict'
|
|
191
|
+
}
|
|
192
|
+
]);
|
|
193
|
+
|
|
194
|
+
const cookie = mockSession.send.mock.calls[0].arguments[1].cookies[0];
|
|
195
|
+
assert.strictEqual(cookie.expires, 1234567890);
|
|
196
|
+
assert.strictEqual(cookie.httpOnly, true);
|
|
197
|
+
assert.strictEqual(cookie.sameSite, 'Strict');
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('should derive secure from HTTPS URL', async () => {
|
|
201
|
+
mockSession.send = mock.fn(async () => ({}));
|
|
202
|
+
|
|
203
|
+
await manager.setCookies([
|
|
204
|
+
{ name: 'session', value: 'abc', url: 'https://example.com' }
|
|
205
|
+
]);
|
|
206
|
+
|
|
207
|
+
const cookie = mockSession.send.mock.calls[0].arguments[1].cookies[0];
|
|
208
|
+
assert.strictEqual(cookie.secure, true);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('should derive non-secure from HTTP URL', async () => {
|
|
212
|
+
mockSession.send = mock.fn(async () => ({}));
|
|
213
|
+
|
|
214
|
+
await manager.setCookies([
|
|
215
|
+
{ name: 'session', value: 'abc', url: 'http://example.com' }
|
|
216
|
+
]);
|
|
217
|
+
|
|
218
|
+
const cookie = mockSession.send.mock.calls[0].arguments[1].cookies[0];
|
|
219
|
+
assert.strictEqual(cookie.secure, false);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
it('should use default path when not specified', async () => {
|
|
223
|
+
mockSession.send = mock.fn(async () => ({}));
|
|
224
|
+
|
|
225
|
+
await manager.setCookies([
|
|
226
|
+
{ name: 'session', value: 'abc', domain: 'example.com' }
|
|
227
|
+
]);
|
|
228
|
+
|
|
229
|
+
const cookie = mockSession.send.mock.calls[0].arguments[1].cookies[0];
|
|
230
|
+
assert.strictEqual(cookie.path, '/');
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it('should set multiple cookies at once', async () => {
|
|
234
|
+
mockSession.send = mock.fn(async () => ({}));
|
|
235
|
+
|
|
236
|
+
await manager.setCookies([
|
|
237
|
+
{ name: 'a', value: '1', domain: 'example.com' },
|
|
238
|
+
{ name: 'b', value: '2', domain: 'example.com' }
|
|
239
|
+
]);
|
|
240
|
+
|
|
241
|
+
const cookies = mockSession.send.mock.calls[0].arguments[1].cookies;
|
|
242
|
+
assert.strictEqual(cookies.length, 2);
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
describe('clearCookies', () => {
|
|
247
|
+
it('should clear all cookies when no filters provided', async () => {
|
|
248
|
+
mockSession.send = mock.fn(async (method) => {
|
|
249
|
+
if (method === 'Storage.getCookies') {
|
|
250
|
+
return { cookies: [{ name: 'a' }, { name: 'b' }] };
|
|
251
|
+
}
|
|
252
|
+
return {};
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
const result = await manager.clearCookies();
|
|
256
|
+
|
|
257
|
+
assert.strictEqual(result.count, 2);
|
|
258
|
+
const clearCall = mockSession.send.mock.calls.find(c => c.arguments[0] === 'Storage.clearCookies');
|
|
259
|
+
assert.ok(clearCall);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it('should clear cookies by URL', async () => {
|
|
263
|
+
mockSession.send = mock.fn(async (method) => {
|
|
264
|
+
if (method === 'Storage.getCookies') {
|
|
265
|
+
return {
|
|
266
|
+
cookies: [
|
|
267
|
+
{ name: 'a', domain: 'example.com', path: '/', secure: false },
|
|
268
|
+
{ name: 'b', domain: 'other.com', path: '/', secure: false }
|
|
269
|
+
]
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
return {};
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
const result = await manager.clearCookies(['https://example.com']);
|
|
276
|
+
|
|
277
|
+
assert.strictEqual(result.count, 1);
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it('should clear cookies by domain option', async () => {
|
|
281
|
+
mockSession.send = mock.fn(async (method) => {
|
|
282
|
+
if (method === 'Storage.getCookies') {
|
|
283
|
+
return {
|
|
284
|
+
cookies: [
|
|
285
|
+
{ name: 'a', domain: 'example.com', path: '/' },
|
|
286
|
+
{ name: 'b', domain: '.example.com', path: '/' },
|
|
287
|
+
{ name: 'c', domain: 'other.com', path: '/' }
|
|
288
|
+
]
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
return {};
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
const result = await manager.clearCookies([], { domain: 'example.com' });
|
|
295
|
+
|
|
296
|
+
assert.strictEqual(result.count, 2);
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
it('should handle deletion failures gracefully', async () => {
|
|
300
|
+
let deleteAttempts = 0;
|
|
301
|
+
mockSession.send = mock.fn(async (method) => {
|
|
302
|
+
if (method === 'Storage.getCookies') {
|
|
303
|
+
return {
|
|
304
|
+
cookies: [
|
|
305
|
+
{ name: 'a', domain: 'example.com', path: '/' },
|
|
306
|
+
{ name: 'b', domain: 'example.com', path: '/' }
|
|
307
|
+
]
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
if (method === 'Network.deleteCookies') {
|
|
311
|
+
deleteAttempts++;
|
|
312
|
+
if (deleteAttempts === 1) {
|
|
313
|
+
throw new Error('Delete failed');
|
|
314
|
+
}
|
|
315
|
+
return {};
|
|
316
|
+
}
|
|
317
|
+
return {};
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
const result = await manager.clearCookies(['https://example.com']);
|
|
321
|
+
|
|
322
|
+
assert.strictEqual(result.count, 1);
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
describe('deleteCookies', () => {
|
|
327
|
+
it('should delete cookie by name', async () => {
|
|
328
|
+
mockSession.send = mock.fn(async (method) => {
|
|
329
|
+
if (method === 'Storage.getCookies') {
|
|
330
|
+
return {
|
|
331
|
+
cookies: [
|
|
332
|
+
{ name: 'session', domain: 'example.com', path: '/' },
|
|
333
|
+
{ name: 'prefs', domain: 'example.com', path: '/' }
|
|
334
|
+
]
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
return {};
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
const result = await manager.deleteCookies('session');
|
|
341
|
+
|
|
342
|
+
assert.strictEqual(result.count, 1);
|
|
343
|
+
const deleteCall = mockSession.send.mock.calls.find(c => c.arguments[0] === 'Network.deleteCookies');
|
|
344
|
+
assert.strictEqual(deleteCall.arguments[1].name, 'session');
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it('should delete multiple cookies by name array', async () => {
|
|
348
|
+
mockSession.send = mock.fn(async (method) => {
|
|
349
|
+
if (method === 'Storage.getCookies') {
|
|
350
|
+
return {
|
|
351
|
+
cookies: [
|
|
352
|
+
{ name: 'a', domain: 'example.com', path: '/' },
|
|
353
|
+
{ name: 'b', domain: 'example.com', path: '/' },
|
|
354
|
+
{ name: 'c', domain: 'example.com', path: '/' }
|
|
355
|
+
]
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
return {};
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
const result = await manager.deleteCookies(['a', 'c']);
|
|
362
|
+
|
|
363
|
+
assert.strictEqual(result.count, 2);
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
it('should filter by domain', async () => {
|
|
367
|
+
mockSession.send = mock.fn(async (method) => {
|
|
368
|
+
if (method === 'Storage.getCookies') {
|
|
369
|
+
return {
|
|
370
|
+
cookies: [
|
|
371
|
+
{ name: 'session', domain: 'example.com', path: '/' },
|
|
372
|
+
{ name: 'session', domain: 'other.com', path: '/' }
|
|
373
|
+
]
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
return {};
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
const result = await manager.deleteCookies('session', { domain: 'example.com' });
|
|
380
|
+
|
|
381
|
+
assert.strictEqual(result.count, 1);
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
it('should filter by path', async () => {
|
|
385
|
+
mockSession.send = mock.fn(async (method) => {
|
|
386
|
+
if (method === 'Storage.getCookies') {
|
|
387
|
+
return {
|
|
388
|
+
cookies: [
|
|
389
|
+
{ name: 'token', domain: 'example.com', path: '/api' },
|
|
390
|
+
{ name: 'token', domain: 'example.com', path: '/' }
|
|
391
|
+
]
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
return {};
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
const result = await manager.deleteCookies('token', { path: '/api' });
|
|
398
|
+
|
|
399
|
+
assert.strictEqual(result.count, 1);
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
it('should return zero count when no matching cookies', async () => {
|
|
403
|
+
mockSession.send = mock.fn(async (method) => {
|
|
404
|
+
if (method === 'Storage.getCookies') {
|
|
405
|
+
return { cookies: [] };
|
|
406
|
+
}
|
|
407
|
+
return {};
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
const result = await manager.deleteCookies('nonexistent');
|
|
411
|
+
|
|
412
|
+
assert.strictEqual(result.count, 0);
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
it('should handle deletion failures gracefully', async () => {
|
|
416
|
+
mockSession.send = mock.fn(async (method) => {
|
|
417
|
+
if (method === 'Storage.getCookies') {
|
|
418
|
+
return {
|
|
419
|
+
cookies: [{ name: 'session', domain: 'example.com', path: '/' }]
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
if (method === 'Network.deleteCookies') {
|
|
423
|
+
throw new Error('Delete failed');
|
|
424
|
+
}
|
|
425
|
+
return {};
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
const result = await manager.deleteCookies('session');
|
|
429
|
+
|
|
430
|
+
assert.strictEqual(result.count, 0);
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
it('should match subdomain cookies', async () => {
|
|
434
|
+
mockSession.send = mock.fn(async (method) => {
|
|
435
|
+
if (method === 'Storage.getCookies') {
|
|
436
|
+
return {
|
|
437
|
+
cookies: [
|
|
438
|
+
{ name: 'session', domain: '.example.com', path: '/' }
|
|
439
|
+
]
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
return {};
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
const result = await manager.deleteCookies('session', { domain: 'example.com' });
|
|
446
|
+
|
|
447
|
+
assert.strictEqual(result.count, 1);
|
|
448
|
+
});
|
|
449
|
+
});
|
|
450
|
+
});
|