@vforsh/argus 0.1.7 → 0.1.8

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/dist/argus.js CHANGED
@@ -5,15 +5,29 @@ var __getProtoOf = Object.getPrototypeOf;
5
5
  var __defProp = Object.defineProperty;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ function __accessProp(key) {
9
+ return this[key];
10
+ }
11
+ var __toESMCache_node;
12
+ var __toESMCache_esm;
8
13
  var __toESM = (mod, isNodeMode, target) => {
14
+ var canCache = mod != null && typeof mod === "object";
15
+ if (canCache) {
16
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
17
+ var cached = cache.get(mod);
18
+ if (cached)
19
+ return cached;
20
+ }
9
21
  target = mod != null ? __create(__getProtoOf(mod)) : {};
10
22
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
11
23
  for (let key of __getOwnPropNames(mod))
12
24
  if (!__hasOwnProp.call(to, key))
13
25
  __defProp(to, key, {
14
- get: () => mod[key],
26
+ get: __accessProp.bind(mod, key),
15
27
  enumerable: true
16
28
  });
29
+ if (canCache)
30
+ cache.set(mod, to);
17
31
  return to;
18
32
  };
19
33
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
@@ -5211,16 +5225,72 @@ var buildModifyFunction = (options) => {
5211
5225
  }
5212
5226
  };
5213
5227
  // ../argus-watcher/dist/cdp/dom/setFile.js
5228
+ var DISPATCH_FILE_EVENTS_AND_GET_COUNT = `function() {
5229
+ var el = this;
5230
+ el.dispatchEvent(new Event('input', { bubbles: true }));
5231
+ el.dispatchEvent(new Event('change', { bubbles: true }));
5232
+ return el.files ? el.files.length : 0;
5233
+ }`;
5234
+ var getBackendNodeId = async (session, nodeId) => {
5235
+ const described = await session.sendAndWait("DOM.describeNode", { nodeId });
5236
+ return described.node?.backendNodeId ?? null;
5237
+ };
5238
+ var resolveObjectId = async (session, params) => {
5239
+ const resolved = await session.sendAndWait("DOM.resolveNode", params);
5240
+ return resolved.object?.objectId ?? null;
5241
+ };
5242
+ var trySetFiles = async (session, params, files) => {
5243
+ try {
5244
+ await session.sendAndWait("DOM.setFileInputFiles", {
5245
+ files,
5246
+ ...params
5247
+ });
5248
+ return true;
5249
+ } catch {
5250
+ return false;
5251
+ }
5252
+ };
5253
+ var setFilesUsingStableNodeRef = async (session, nodeId, files) => {
5254
+ const backendNodeId = await getBackendNodeId(session, nodeId);
5255
+ const objectIdFromBackendNode = backendNodeId != null ? await resolveObjectId(session, { backendNodeId }) : null;
5256
+ if (objectIdFromBackendNode != null && await trySetFiles(session, { objectId: objectIdFromBackendNode }, files)) {
5257
+ return { backendNodeId, objectId: objectIdFromBackendNode };
5258
+ }
5259
+ if (backendNodeId != null && await trySetFiles(session, { backendNodeId }, files)) {
5260
+ return { backendNodeId, objectId: objectIdFromBackendNode };
5261
+ }
5262
+ const objectIdFromNode = await resolveObjectId(session, { nodeId });
5263
+ if (objectIdFromNode != null && await trySetFiles(session, { objectId: objectIdFromNode }, files)) {
5264
+ return { backendNodeId, objectId: objectIdFromNode };
5265
+ }
5266
+ await session.sendAndWait("DOM.setFileInputFiles", { files, nodeId });
5267
+ return { backendNodeId, objectId: objectIdFromNode };
5268
+ };
5269
+ var setFileOnResolvedNode = async (session, nodeId, files) => {
5270
+ const { backendNodeId, objectId } = await setFilesUsingStableNodeRef(session, nodeId, files);
5271
+ const resolvedObjectId = objectId ?? await resolveObjectId(session, backendNodeId != null ? { backendNodeId } : { nodeId });
5272
+ if (!resolvedObjectId) {
5273
+ return false;
5274
+ }
5275
+ const result = await session.sendAndWait("Runtime.callFunctionOn", {
5276
+ objectId: resolvedObjectId,
5277
+ functionDeclaration: DISPATCH_FILE_EVENTS_AND_GET_COUNT,
5278
+ awaitPromise: false,
5279
+ returnByValue: true
5280
+ });
5281
+ return typeof result.result?.value === "number" && result.result.value > 0;
5282
+ };
5214
5283
  var setFileOnResolvedNodes = async (session, nodeIds, files) => {
5215
5284
  if (nodeIds.length === 0)
5216
5285
  return 0;
5286
+ let updatedCount = 0;
5217
5287
  for (const nodeId of nodeIds) {
5218
- await session.sendAndWait("DOM.setFileInputFiles", {
5219
- files,
5220
- nodeId
5221
- });
5288
+ const ok = await setFileOnResolvedNode(session, nodeId, files);
5289
+ if (ok) {
5290
+ updatedCount += 1;
5291
+ }
5222
5292
  }
5223
- return nodeIds.length;
5293
+ return updatedCount;
5224
5294
  };
5225
5295
  // ../argus-watcher/dist/cdp/dom/fill.js
5226
5296
  var FILL_FUNCTION = `function(value) {
@@ -5262,79 +5332,6 @@ var fillResolvedNodes = async (session, nodeIds, value) => {
5262
5332
  }
5263
5333
  return nodeIds.length;
5264
5334
  };
5265
- // ../argus-watcher/dist/http/routes/postDomTree.js
5266
- var handle11 = async (req, res, _url, ctx) => {
5267
- const payload = await readJsonBody(req, res);
5268
- if (!payload) {
5269
- return;
5270
- }
5271
- if (!payload.selector || typeof payload.selector !== "string") {
5272
- return respondInvalidBody(res, "selector is required");
5273
- }
5274
- const all = payload.all ?? false;
5275
- if (typeof all !== "boolean") {
5276
- return respondInvalidBody(res, "all must be a boolean");
5277
- }
5278
- emitRequest(ctx, res, "dom/tree");
5279
- try {
5280
- const response = await fetchDomSubtreeBySelector(ctx.cdpSession, {
5281
- selector: payload.selector,
5282
- depth: payload.depth,
5283
- maxNodes: payload.maxNodes,
5284
- all,
5285
- text: payload.text
5286
- });
5287
- if (!all && response.matches > 1) {
5288
- return respondJson(res, {
5289
- ok: false,
5290
- error: {
5291
- message: `Selector matched ${response.matches} elements; pass all=true to return all matches`,
5292
- code: "multiple_matches"
5293
- }
5294
- }, 400);
5295
- }
5296
- respondJson(res, response);
5297
- } catch (error) {
5298
- respondError(res, error);
5299
- }
5300
- };
5301
-
5302
- // ../argus-watcher/dist/http/routes/postDomInfo.js
5303
- var handle12 = async (req, res, _url, ctx) => {
5304
- const payload = await readJsonBody(req, res);
5305
- if (!payload) {
5306
- return;
5307
- }
5308
- if (!payload.selector || typeof payload.selector !== "string") {
5309
- return respondInvalidBody(res, "selector is required");
5310
- }
5311
- const all = payload.all ?? false;
5312
- if (typeof all !== "boolean") {
5313
- return respondInvalidBody(res, "all must be a boolean");
5314
- }
5315
- emitRequest(ctx, res, "dom/info");
5316
- try {
5317
- const response = await fetchDomInfoBySelector(ctx.cdpSession, {
5318
- selector: payload.selector,
5319
- all,
5320
- outerHtmlMaxChars: payload.outerHtmlMaxChars,
5321
- text: payload.text
5322
- });
5323
- if (!all && response.matches > 1) {
5324
- return respondJson(res, {
5325
- ok: false,
5326
- error: {
5327
- message: `Selector matched ${response.matches} elements; pass all=true to return all matches`,
5328
- code: "multiple_matches"
5329
- }
5330
- }, 400);
5331
- }
5332
- respondJson(res, response);
5333
- } catch (error) {
5334
- respondError(res, error);
5335
- }
5336
- };
5337
-
5338
5335
  // ../argus-watcher/dist/cdp/mouse.js
5339
5336
  var resolveDomSelectorMatches = async (session, selector, all, text) => {
5340
5337
  await session.sendAndWait("DOM.enable");
@@ -5521,6 +5518,205 @@ var createNotInteractableError = (message) => {
5521
5518
  return error;
5522
5519
  };
5523
5520
 
5521
+ // ../argus-watcher/dist/cdp/dom/submit.js
5522
+ var SUBMIT_DECLARATION = `function(strategy) {
5523
+ var target = this;
5524
+
5525
+ function isForm(el) {
5526
+ return typeof HTMLFormElement !== 'undefined' && el instanceof HTMLFormElement;
5527
+ }
5528
+
5529
+ function resolveForm(el) {
5530
+ if (!el) {
5531
+ return null;
5532
+ }
5533
+ if (isForm(el)) {
5534
+ return el;
5535
+ }
5536
+ if (el.form) {
5537
+ return el.form;
5538
+ }
5539
+ if (typeof el.closest === 'function') {
5540
+ return el.closest('form');
5541
+ }
5542
+ return null;
5543
+ }
5544
+
5545
+ function resolveSubmitter(el, form) {
5546
+ if (!el || !form || isForm(el)) {
5547
+ return undefined;
5548
+ }
5549
+ if (
5550
+ typeof HTMLElement !== 'undefined'
5551
+ && el instanceof HTMLElement
5552
+ && el.form === form
5553
+ && (
5554
+ (typeof HTMLButtonElement !== 'undefined' && el instanceof HTMLButtonElement)
5555
+ || (
5556
+ typeof HTMLInputElement !== 'undefined'
5557
+ && el instanceof HTMLInputElement
5558
+ && (el.type === 'submit' || el.type === 'image')
5559
+ )
5560
+ )
5561
+ ) {
5562
+ return el;
5563
+ }
5564
+ return undefined;
5565
+ }
5566
+
5567
+ function submitElement(el, submitter) {
5568
+ if (!el) {
5569
+ return false;
5570
+ }
5571
+ if (typeof el.requestSubmit === 'function') {
5572
+ try {
5573
+ if (submitter !== undefined) {
5574
+ el.requestSubmit(submitter);
5575
+ } else {
5576
+ el.requestSubmit();
5577
+ }
5578
+ } catch (_) {
5579
+ el.requestSubmit();
5580
+ }
5581
+ return true;
5582
+ }
5583
+ if (typeof el.submit === 'function') {
5584
+ el.submit();
5585
+ return true;
5586
+ }
5587
+ var event = new Event('submit', { bubbles: true, cancelable: true });
5588
+ el.dispatchEvent(event);
5589
+ return true;
5590
+ }
5591
+
5592
+ var nearestForm = resolveForm(target);
5593
+ var submitter = resolveSubmitter(target, nearestForm);
5594
+
5595
+ if (strategy === 'form') {
5596
+ return submitElement(nearestForm, submitter);
5597
+ }
5598
+
5599
+ if (strategy === 'self') {
5600
+ return submitElement(target);
5601
+ }
5602
+
5603
+ if (submitElement(nearestForm, submitter)) {
5604
+ return true;
5605
+ }
5606
+
5607
+ return submitElement(target);
5608
+ }`;
5609
+ var submitResolvedNode = async (session, nodeId, strategy) => {
5610
+ await scrollIntoView(session, nodeId);
5611
+ const resolved = await session.sendAndWait("DOM.resolveNode", { nodeId });
5612
+ const objectId = resolved.object?.objectId;
5613
+ if (!objectId) {
5614
+ return false;
5615
+ }
5616
+ const result = await session.sendAndWait("Runtime.callFunctionOn", {
5617
+ objectId,
5618
+ functionDeclaration: SUBMIT_DECLARATION,
5619
+ arguments: [{ value: strategy }],
5620
+ awaitPromise: false,
5621
+ returnByValue: true
5622
+ });
5623
+ return result.result?.value === true;
5624
+ };
5625
+ var submitResolvedNodes = async (session, nodeIds, strategy) => {
5626
+ if (nodeIds.length === 0) {
5627
+ return 0;
5628
+ }
5629
+ let submittedCount = 0;
5630
+ for (const nodeId of nodeIds) {
5631
+ const ok = await submitResolvedNode(session, nodeId, strategy);
5632
+ if (ok) {
5633
+ submittedCount += 1;
5634
+ }
5635
+ }
5636
+ return submittedCount;
5637
+ };
5638
+ var submitElements = async (session, options) => {
5639
+ await session.sendAndWait("DOM.enable");
5640
+ const all = options.all ?? false;
5641
+ const waitMs = options.wait ?? 0;
5642
+ const strategy = options.strategy ?? "auto";
5643
+ const result = waitMs > 0 ? await waitForSelectorMatches(session, options.selector, all, options.text, waitMs) : await resolveSelectorMatches(session, await getDomRootId(session), options.selector, all, options.text);
5644
+ const submittedCount = await submitResolvedNodes(session, result.nodeIds, strategy);
5645
+ return { allNodeIds: result.allNodeIds, submittedCount };
5646
+ };
5647
+ // ../argus-watcher/dist/http/routes/postDomTree.js
5648
+ var handle11 = async (req, res, _url, ctx) => {
5649
+ const payload = await readJsonBody(req, res);
5650
+ if (!payload) {
5651
+ return;
5652
+ }
5653
+ if (!payload.selector || typeof payload.selector !== "string") {
5654
+ return respondInvalidBody(res, "selector is required");
5655
+ }
5656
+ const all = payload.all ?? false;
5657
+ if (typeof all !== "boolean") {
5658
+ return respondInvalidBody(res, "all must be a boolean");
5659
+ }
5660
+ emitRequest(ctx, res, "dom/tree");
5661
+ try {
5662
+ const response = await fetchDomSubtreeBySelector(ctx.cdpSession, {
5663
+ selector: payload.selector,
5664
+ depth: payload.depth,
5665
+ maxNodes: payload.maxNodes,
5666
+ all,
5667
+ text: payload.text
5668
+ });
5669
+ if (!all && response.matches > 1) {
5670
+ return respondJson(res, {
5671
+ ok: false,
5672
+ error: {
5673
+ message: `Selector matched ${response.matches} elements; pass all=true to return all matches`,
5674
+ code: "multiple_matches"
5675
+ }
5676
+ }, 400);
5677
+ }
5678
+ respondJson(res, response);
5679
+ } catch (error) {
5680
+ respondError(res, error);
5681
+ }
5682
+ };
5683
+
5684
+ // ../argus-watcher/dist/http/routes/postDomInfo.js
5685
+ var handle12 = async (req, res, _url, ctx) => {
5686
+ const payload = await readJsonBody(req, res);
5687
+ if (!payload) {
5688
+ return;
5689
+ }
5690
+ if (!payload.selector || typeof payload.selector !== "string") {
5691
+ return respondInvalidBody(res, "selector is required");
5692
+ }
5693
+ const all = payload.all ?? false;
5694
+ if (typeof all !== "boolean") {
5695
+ return respondInvalidBody(res, "all must be a boolean");
5696
+ }
5697
+ emitRequest(ctx, res, "dom/info");
5698
+ try {
5699
+ const response = await fetchDomInfoBySelector(ctx.cdpSession, {
5700
+ selector: payload.selector,
5701
+ all,
5702
+ outerHtmlMaxChars: payload.outerHtmlMaxChars,
5703
+ text: payload.text
5704
+ });
5705
+ if (!all && response.matches > 1) {
5706
+ return respondJson(res, {
5707
+ ok: false,
5708
+ error: {
5709
+ message: `Selector matched ${response.matches} elements; pass all=true to return all matches`,
5710
+ code: "multiple_matches"
5711
+ }
5712
+ }, 400);
5713
+ }
5714
+ respondJson(res, response);
5715
+ } catch (error) {
5716
+ respondError(res, error);
5717
+ }
5718
+ };
5719
+
5524
5720
  // ../argus-watcher/dist/http/routes/postDomHover.js
5525
5721
  var handle13 = async (req, res, _url, ctx) => {
5526
5722
  const payload = await readJsonBody(req, res);
@@ -6001,6 +6197,15 @@ var handle19 = async (req, res, _url, ctx) => {
6001
6197
  }, 400);
6002
6198
  }
6003
6199
  const updatedCount = await setFileOnResolvedNodes(ctx.cdpSession, nodeIds, payload.files);
6200
+ if (nodeIds.length > 0 && updatedCount === 0) {
6201
+ return respondJson(res, {
6202
+ ok: false,
6203
+ error: {
6204
+ message: "Matched file input element(s), but none accepted files after DOM.setFileInputFiles + input/change dispatch",
6205
+ code: "set_file_failed"
6206
+ }
6207
+ }, 500);
6208
+ }
6004
6209
  const response = { ok: true, matches: allNodeIds.length, updated: updatedCount };
6005
6210
  respondJson(res, response);
6006
6211
  } catch (error) {
@@ -6098,8 +6303,54 @@ var handle21 = async (req, res, _url, ctx) => {
6098
6303
  }
6099
6304
  };
6100
6305
 
6101
- // ../argus-watcher/dist/http/routes/postDomScroll.js
6306
+ // ../argus-watcher/dist/http/routes/postDomSubmit.js
6102
6307
  var handle22 = async (req, res, _url, ctx) => {
6308
+ const payload = await readJsonBody(req, res);
6309
+ if (!payload) {
6310
+ return;
6311
+ }
6312
+ if (!payload.selector || typeof payload.selector !== "string") {
6313
+ return respondInvalidBody(res, "selector is required");
6314
+ }
6315
+ const all = payload.all ?? false;
6316
+ if (typeof all !== "boolean") {
6317
+ return respondInvalidBody(res, "all must be a boolean");
6318
+ }
6319
+ const waitMs = payload.wait ?? 0;
6320
+ if (typeof waitMs !== "number" || !Number.isFinite(waitMs) || waitMs < 0) {
6321
+ return respondInvalidBody(res, "wait must be a non-negative number (ms)");
6322
+ }
6323
+ const strategy = payload.strategy ?? "auto";
6324
+ if (strategy !== "auto" && strategy !== "form" && strategy !== "self") {
6325
+ return respondInvalidBody(res, "strategy must be one of: auto, form, self");
6326
+ }
6327
+ emitRequest(ctx, res, "dom/submit");
6328
+ try {
6329
+ const { allNodeIds, submittedCount } = await submitElements(ctx.cdpSession, {
6330
+ selector: payload.selector,
6331
+ all,
6332
+ text: payload.text,
6333
+ wait: waitMs,
6334
+ strategy
6335
+ });
6336
+ if (!all && allNodeIds.length > 1) {
6337
+ return respondJson(res, {
6338
+ ok: false,
6339
+ error: {
6340
+ message: `Selector matched ${allNodeIds.length} elements; pass all=true to submit all matches`,
6341
+ code: "multiple_matches"
6342
+ }
6343
+ }, 400);
6344
+ }
6345
+ const response = { ok: true, matches: allNodeIds.length, submitted: submittedCount };
6346
+ respondJson(res, response);
6347
+ } catch (error) {
6348
+ respondError(res, error);
6349
+ }
6350
+ };
6351
+
6352
+ // ../argus-watcher/dist/http/routes/postDomScroll.js
6353
+ var handle23 = async (req, res, _url, ctx) => {
6103
6354
  const payload = await readJsonBody(req, res);
6104
6355
  if (!payload) {
6105
6356
  return;
@@ -6168,7 +6419,7 @@ var getViewportSize = async (session) => {
6168
6419
  };
6169
6420
 
6170
6421
  // ../argus-watcher/dist/http/routes/postDomScrollTo.js
6171
- var handle23 = async (req, res, _url, ctx) => {
6422
+ var handle24 = async (req, res, _url, ctx) => {
6172
6423
  const payload = await readJsonBody(req, res);
6173
6424
  if (!payload) {
6174
6425
  return;
@@ -6227,14 +6478,14 @@ var handle23 = async (req, res, _url, ctx) => {
6227
6478
  };
6228
6479
 
6229
6480
  // ../argus-watcher/dist/http/routes/getEmulation.js
6230
- var handle24 = (_req, res, _url, ctx) => {
6481
+ var handle25 = (_req, res, _url, ctx) => {
6231
6482
  emitRequest(ctx, res, "emulation");
6232
6483
  const status = ctx.emulationController.getStatus({ attached: ctx.getCdpStatus().attached });
6233
6484
  respondJson(res, status);
6234
6485
  };
6235
6486
 
6236
6487
  // ../argus-watcher/dist/http/routes/postEmulation.js
6237
- var handle25 = async (req, res, _url, ctx) => {
6488
+ var handle26 = async (req, res, _url, ctx) => {
6238
6489
  const payload = await readJsonBody(req, res);
6239
6490
  if (!payload) {
6240
6491
  return;
@@ -6297,14 +6548,14 @@ var handle25 = async (req, res, _url, ctx) => {
6297
6548
  };
6298
6549
 
6299
6550
  // ../argus-watcher/dist/http/routes/getThrottle.js
6300
- var handle26 = (_req, res, _url, ctx) => {
6551
+ var handle27 = (_req, res, _url, ctx) => {
6301
6552
  emitRequest(ctx, res, "throttle");
6302
6553
  const status = ctx.throttleController.getStatus({ attached: ctx.getCdpStatus().attached });
6303
6554
  respondJson(res, status);
6304
6555
  };
6305
6556
 
6306
6557
  // ../argus-watcher/dist/http/routes/postThrottle.js
6307
- var handle27 = async (req, res, _url, ctx) => {
6558
+ var handle28 = async (req, res, _url, ctx) => {
6308
6559
  const payload = await readJsonBody(req, res);
6309
6560
  if (!payload) {
6310
6561
  return;
@@ -6402,7 +6653,7 @@ var buildActionCode = (action, key, value) => {
6402
6653
  };
6403
6654
 
6404
6655
  // ../argus-watcher/dist/http/routes/postStorageLocal.js
6405
- var handle28 = async (req, res, _url, ctx) => {
6656
+ var handle29 = async (req, res, _url, ctx) => {
6406
6657
  const payload = await readJsonBody(req, res);
6407
6658
  if (!payload) {
6408
6659
  return;
@@ -6427,7 +6678,7 @@ var handle28 = async (req, res, _url, ctx) => {
6427
6678
  };
6428
6679
 
6429
6680
  // ../argus-watcher/dist/http/routes/postReload.js
6430
- var handle29 = async (req, res, _url, ctx) => {
6681
+ var handle30 = async (req, res, _url, ctx) => {
6431
6682
  const payload = await readJsonBody(req, res);
6432
6683
  if (!payload) {
6433
6684
  return;
@@ -6445,7 +6696,7 @@ var handle29 = async (req, res, _url, ctx) => {
6445
6696
  };
6446
6697
 
6447
6698
  // ../argus-watcher/dist/http/routes/postShutdown.js
6448
- var handle30 = (_req, res, _url, ctx) => {
6699
+ var handle31 = (_req, res, _url, ctx) => {
6449
6700
  emitRequest(ctx, res, "shutdown");
6450
6701
  const response = { ok: true };
6451
6702
  respondJson(res, response);
@@ -6457,7 +6708,7 @@ var handle30 = (_req, res, _url, ctx) => {
6457
6708
  };
6458
6709
 
6459
6710
  // ../argus-watcher/dist/http/routes/getTargets.js
6460
- var handle31 = async (_req, res, _url, ctx) => {
6711
+ var handle32 = async (_req, res, _url, ctx) => {
6461
6712
  if (!ctx.sourceHandle?.listTargets) {
6462
6713
  return respondJson(res, { ok: false, error: { message: "Not available", code: "not_available" } }, 400);
6463
6714
  }
@@ -6471,7 +6722,7 @@ var handle31 = async (_req, res, _url, ctx) => {
6471
6722
  };
6472
6723
 
6473
6724
  // ../argus-watcher/dist/http/routes/postAttach.js
6474
- var handle32 = async (req, res, _url, ctx) => {
6725
+ var handle33 = async (req, res, _url, ctx) => {
6475
6726
  if (!ctx.sourceHandle?.attachTarget) {
6476
6727
  return respondJson(res, { ok: false, error: { message: "Not available", code: "not_available" } }, 400);
6477
6728
  }
@@ -6492,7 +6743,7 @@ var handle32 = async (req, res, _url, ctx) => {
6492
6743
  };
6493
6744
 
6494
6745
  // ../argus-watcher/dist/http/routes/postDetach.js
6495
- var handle33 = async (req, res, _url, ctx) => {
6746
+ var handle34 = async (req, res, _url, ctx) => {
6496
6747
  if (!ctx.sourceHandle?.detachTarget) {
6497
6748
  return respondJson(res, { ok: false, error: { message: "Not available", code: "not_available" } }, 400);
6498
6749
  }
@@ -6535,18 +6786,19 @@ var routes = {
6535
6786
  "POST /dom/set-file": { handler: handle19 },
6536
6787
  "POST /dom/focus": { handler: handle20 },
6537
6788
  "POST /dom/fill": { handler: handle21 },
6538
- "POST /dom/scroll": { handler: handle22 },
6539
- "POST /dom/scroll-to": { handler: handle23 },
6540
- "GET /emulation": { handler: handle24 },
6541
- "POST /emulation": { handler: handle25 },
6542
- "GET /throttle": { handler: handle26 },
6543
- "POST /throttle": { handler: handle27 },
6544
- "POST /storage/local": { handler: handle28 },
6545
- "POST /reload": { handler: handle29 },
6546
- "POST /shutdown": { handler: handle30 },
6547
- "GET /targets": { handler: handle31, extensionOnly: true },
6548
- "POST /attach": { handler: handle32, extensionOnly: true },
6549
- "POST /detach": { handler: handle33, extensionOnly: true }
6789
+ "POST /dom/submit": { handler: handle22 },
6790
+ "POST /dom/scroll": { handler: handle23 },
6791
+ "POST /dom/scroll-to": { handler: handle24 },
6792
+ "GET /emulation": { handler: handle25 },
6793
+ "POST /emulation": { handler: handle26 },
6794
+ "GET /throttle": { handler: handle27 },
6795
+ "POST /throttle": { handler: handle28 },
6796
+ "POST /storage/local": { handler: handle29 },
6797
+ "POST /reload": { handler: handle30 },
6798
+ "POST /shutdown": { handler: handle31 },
6799
+ "GET /targets": { handler: handle32, extensionOnly: true },
6800
+ "POST /attach": { handler: handle33, extensionOnly: true },
6801
+ "POST /detach": { handler: handle34, extensionOnly: true }
6550
6802
  };
6551
6803
  var dispatch = (req, res, url, ctx) => {
6552
6804
  const entry = routes[`${req.method} ${url.pathname}`];
@@ -7123,7 +7375,7 @@ var createTraceRecorder = (options) => {
7123
7375
  await new Promise((resolve) => state.stream.end(resolve));
7124
7376
  };
7125
7377
  options.session.onEvent("Tracing.dataCollected", (params) => {
7126
- if (!active || active.state !== "recording") {
7378
+ if (!active) {
7127
7379
  return;
7128
7380
  }
7129
7381
  const payload = params;
@@ -9178,7 +9430,7 @@ class SessionManager {
9178
9430
  const enabledDomains = new Set;
9179
9431
  const tabHandlers = new Map;
9180
9432
  this.eventHandlers.set(tabId, tabHandlers);
9181
- const handle34 = {
9433
+ const handle35 = {
9182
9434
  isAttached: () => this.sessions.has(tabId),
9183
9435
  sendAndWait: async (method, params, options) => {
9184
9436
  if (!this.sessions.has(tabId)) {
@@ -9220,7 +9472,7 @@ class SessionManager {
9220
9472
  title,
9221
9473
  faviconUrl,
9222
9474
  attachedAt: Date.now(),
9223
- handle: handle34,
9475
+ handle: handle35,
9224
9476
  enabledDomains
9225
9477
  };
9226
9478
  this.sessions.set(tabId, session);
@@ -10372,9 +10624,9 @@ var runStart = async (options) => {
10372
10624
  artifactsBaseDir = resolvePath(trimmed);
10373
10625
  }
10374
10626
  const inject = await resolveInjectScript(options.inject, output);
10375
- let handle34;
10627
+ let handle35;
10376
10628
  try {
10377
- handle34 = await startWatcher({
10629
+ handle35 = await startWatcher({
10378
10630
  id: watcherId,
10379
10631
  source: "cdp",
10380
10632
  match: Object.keys(match).length > 0 ? match : undefined,
@@ -10394,7 +10646,7 @@ var runStart = async (options) => {
10394
10646
  }
10395
10647
  const shutdown = async () => {
10396
10648
  try {
10397
- await handle34.close();
10649
+ await handle35.close();
10398
10650
  } catch {}
10399
10651
  await chrome.closeGracefully();
10400
10652
  };
@@ -10410,23 +10662,23 @@ var runStart = async (options) => {
10410
10662
  rmSync2(chrome.userDataDir, { recursive: true, force: true });
10411
10663
  } catch {}
10412
10664
  }
10413
- handle34.close().then(() => process.exit(0));
10665
+ handle35.close().then(() => process.exit(0));
10414
10666
  });
10415
- handle34.events.on("cdpAttached", ({ target }) => {
10667
+ handle35.events.on("cdpAttached", ({ target }) => {
10416
10668
  const typeInfo = target?.type ? ` (type: ${target.type})` : "";
10417
10669
  output.writeHuman(`[${watcherId}] CDP attached: ${target?.title} (${target?.url})${typeInfo}`);
10418
10670
  });
10419
- handle34.events.on("cdpDetached", ({ reason, target }) => {
10671
+ handle35.events.on("cdpDetached", ({ reason, target }) => {
10420
10672
  output.writeHuman(`[${watcherId}] CDP detached: ${reason} (last target: ${target?.title})`);
10421
10673
  });
10422
10674
  const result = {
10423
- id: handle34.watcher.id,
10675
+ id: handle35.watcher.id,
10424
10676
  chromePid: chrome.chrome.pid,
10425
10677
  cdpHost: chrome.cdpHost,
10426
10678
  cdpPort: chrome.cdpPort,
10427
- watcherHost: handle34.watcher.host,
10428
- watcherPort: handle34.watcher.port,
10429
- watcherPid: handle34.watcher.pid
10679
+ watcherHost: handle35.watcher.host,
10680
+ watcherPort: handle35.watcher.port,
10681
+ watcherPid: handle35.watcher.pid
10430
10682
  };
10431
10683
  if (options.json) {
10432
10684
  output.writeJson(result);
@@ -11294,9 +11546,9 @@ var runWatcherStart = async (options) => {
11294
11546
  if (options.parent?.trim()) {
11295
11547
  match.parent = options.parent.trim();
11296
11548
  }
11297
- let handle34;
11549
+ let handle35;
11298
11550
  try {
11299
- handle34 = await startWatcher({
11551
+ handle35 = await startWatcher({
11300
11552
  id: watcherId,
11301
11553
  source: sourceMode,
11302
11554
  match: sourceMode === "cdp" && Object.keys(match).length > 0 ? match : undefined,
@@ -11314,10 +11566,10 @@ var runWatcherStart = async (options) => {
11314
11566
  return;
11315
11567
  }
11316
11568
  const result = {
11317
- id: handle34.watcher.id,
11318
- host: handle34.watcher.host,
11319
- port: handle34.watcher.port,
11320
- pid: handle34.watcher.pid,
11569
+ id: handle35.watcher.id,
11570
+ host: handle35.watcher.host,
11571
+ port: handle35.watcher.port,
11572
+ pid: handle35.watcher.pid,
11321
11573
  source: sourceMode,
11322
11574
  matchUrl: match.url,
11323
11575
  matchType: match.type,
@@ -11330,7 +11582,7 @@ var runWatcherStart = async (options) => {
11330
11582
  };
11331
11583
  const cleanup = async () => {
11332
11584
  try {
11333
- await handle34.close();
11585
+ await handle35.close();
11334
11586
  } catch {}
11335
11587
  };
11336
11588
  process.on("SIGINT", () => {
@@ -11339,12 +11591,12 @@ var runWatcherStart = async (options) => {
11339
11591
  process.on("SIGTERM", () => {
11340
11592
  cleanup().then(() => process.exit(0));
11341
11593
  });
11342
- handle34.events.on("cdpAttached", ({ target }) => {
11594
+ handle35.events.on("cdpAttached", ({ target }) => {
11343
11595
  const typeInfo = target?.type ? ` (type: ${target.type})` : "";
11344
- output.writeHuman(`[${handle34.watcher.id}] CDP attached: ${target?.title} (${target?.url})${typeInfo}`);
11596
+ output.writeHuman(`[${handle35.watcher.id}] CDP attached: ${target?.title} (${target?.url})${typeInfo}`);
11345
11597
  });
11346
- handle34.events.on("cdpDetached", ({ reason, target }) => {
11347
- output.writeHuman(`[${handle34.watcher.id}] CDP detached: ${reason} (last target: ${target?.title})`);
11598
+ handle35.events.on("cdpDetached", ({ reason, target }) => {
11599
+ output.writeHuman(`[${handle35.watcher.id}] CDP detached: ${reason} (last target: ${target?.title})`);
11348
11600
  });
11349
11601
  if (options.json) {
11350
11602
  output.writeJson(result);
@@ -11556,9 +11808,9 @@ var checkWatcherReachable = async (watcher) => {
11556
11808
  // dist/commands/watcherNativeHost.js
11557
11809
  var runWatcherNativeHost = async (options) => {
11558
11810
  const watcherId = options.id?.trim() || "extension";
11559
- let handle34;
11811
+ let handle35;
11560
11812
  try {
11561
- handle34 = await startWatcher({
11813
+ handle35 = await startWatcher({
11562
11814
  id: watcherId,
11563
11815
  source: "extension",
11564
11816
  host: "127.0.0.1",
@@ -11569,10 +11821,10 @@ var runWatcherNativeHost = async (options) => {
11569
11821
  console.error(`Failed to start watcher: ${error instanceof Error ? error.message : error}`);
11570
11822
  process.exit(1);
11571
11823
  }
11572
- console.error(`[NativeHost] Watcher started: id=${handle34.watcher.id} port=${handle34.watcher.port}`);
11824
+ console.error(`[NativeHost] Watcher started: id=${handle35.watcher.id} port=${handle35.watcher.port}`);
11573
11825
  const cleanup = async () => {
11574
11826
  try {
11575
- await handle34.close();
11827
+ await handle35.close();
11576
11828
  } catch {}
11577
11829
  };
11578
11830
  process.on("SIGINT", () => {
@@ -14081,11 +14333,91 @@ var runDomSetFile = async (id, options) => {
14081
14333
  process.exitCode = 1;
14082
14334
  return;
14083
14335
  }
14336
+ if (successResp.updated === 0) {
14337
+ output.writeWarn(`Matched ${successResp.matches} file input element(s), but none accepted files`);
14338
+ process.exitCode = 1;
14339
+ return;
14340
+ }
14084
14341
  const fileLabel = files.length === 1 ? "1 file" : `${files.length} files`;
14085
14342
  const elLabel = successResp.updated === 1 ? "1 element" : `${successResp.updated} elements`;
14086
14343
  output.writeHuman(`Set ${fileLabel} on ${elLabel} for selector: ${options.selector}`);
14087
14344
  };
14088
14345
 
14346
+ // dist/commands/domSubmit.js
14347
+ var runDomSubmit = async (id, options) => {
14348
+ const output = createOutput(options);
14349
+ if (!options.selector || options.selector.trim() === "") {
14350
+ output.writeWarn("--selector or --testid is required");
14351
+ process.exitCode = 2;
14352
+ return;
14353
+ }
14354
+ let waitMs = 0;
14355
+ if (options.wait != null) {
14356
+ const parsed = parseDurationMs(options.wait);
14357
+ if (parsed == null || parsed < 0) {
14358
+ output.writeWarn("Invalid --wait value: expected a duration like 5s, 500ms, 2m.");
14359
+ process.exitCode = 2;
14360
+ return;
14361
+ }
14362
+ waitMs = parsed;
14363
+ }
14364
+ const strategy = options.strategy ?? "auto";
14365
+ if (strategy !== "auto" && strategy !== "form" && strategy !== "self") {
14366
+ output.writeWarn("Invalid --strategy value: expected auto, form, or self.");
14367
+ process.exitCode = 2;
14368
+ return;
14369
+ }
14370
+ const body = {
14371
+ selector: options.selector,
14372
+ all: options.all ?? false,
14373
+ text: options.text,
14374
+ strategy
14375
+ };
14376
+ if (waitMs > 0) {
14377
+ body.wait = waitMs;
14378
+ }
14379
+ const result = await requestWatcherJson({
14380
+ id,
14381
+ path: "/dom/submit",
14382
+ method: "POST",
14383
+ body,
14384
+ timeoutMs: Math.max(30000, waitMs + 5000),
14385
+ returnErrorResponse: true
14386
+ });
14387
+ if (!result.ok) {
14388
+ writeRequestError(result, output);
14389
+ return;
14390
+ }
14391
+ const response = result.data;
14392
+ if (!response.ok) {
14393
+ const errorResp = response;
14394
+ if (options.json) {
14395
+ output.writeJson(response);
14396
+ } else {
14397
+ output.writeWarn(`Error: ${errorResp.error.message}`);
14398
+ }
14399
+ process.exitCode = 1;
14400
+ return;
14401
+ }
14402
+ const successResp = response;
14403
+ if (options.json) {
14404
+ output.writeJson(successResp);
14405
+ return;
14406
+ }
14407
+ if (successResp.matches === 0) {
14408
+ output.writeWarn(`No element found for selector: ${options.selector}`);
14409
+ process.exitCode = 1;
14410
+ return;
14411
+ }
14412
+ if (successResp.submitted === 0) {
14413
+ output.writeWarn(`Matched ${successResp.matches} element(s), but none could be submitted`);
14414
+ process.exitCode = 1;
14415
+ return;
14416
+ }
14417
+ const label = successResp.submitted === 1 ? "1 element" : `${successResp.submitted} elements`;
14418
+ output.writeHuman(`Submitted ${label} for selector: ${options.selector}`);
14419
+ };
14420
+
14089
14421
  // dist/commands/domScroll.js
14090
14422
  var runDomScroll = async (id, options) => {
14091
14423
  const output = createOutput(options);
@@ -14548,6 +14880,17 @@ Examples:
14548
14880
  return;
14549
14881
  await runDomSetFile(id, options);
14550
14882
  });
14883
+ dom.command("submit").argument("[id]", "Watcher id to query").description("Submit a form or the nearest form for the matched element(s)").option("--selector <css>", "CSS selector for a form or a descendant element").option("--testid <id>", `Shorthand for --selector "[data-testid='<id>']"`).option("--all", "Allow multiple matches (default: error if >1 match)").option("--text <string>", "Filter by textContent (trimmed). Supports /regex/flags syntax").option("--wait <duration>", "Wait for selector to appear (e.g. 5s, 500ms)").option("--strategy <mode>", "Submit strategy: auto (default), form, or self").option("--json", "Output JSON for automation").addHelpText("after", `
14884
+ Examples:
14885
+ $ argus dom submit app --selector "form"
14886
+ $ argus dom submit app --selector "input[type=email]"
14887
+ $ argus dom submit app --selector "button[type=submit]" --strategy form
14888
+ $ argus dom submit app --selector "#login" --wait 5s
14889
+ `).action(async (id, options) => {
14890
+ if (!resolveTestId(options))
14891
+ return;
14892
+ await runDomSubmit(id, options);
14893
+ });
14551
14894
  dom.command("scroll").argument("[id]", "Watcher id to query").description("Emulate a touch scroll gesture (fires real scroll/wheel events)").option("--selector <css>", "CSS selector — scroll at element center").option("--testid <id>", `Shorthand for --selector "[data-testid='<id>']"`).option("--pos <x,y>", "Viewport coordinates to scroll at (mutually exclusive with selector)").requiredOption("--by <dx,dy>", "Scroll delta (positive y = scroll down)").option("--all", "Allow multiple matches (default: error if >1 match)").option("--text <string>", "Filter by textContent (trimmed). Supports /regex/flags syntax").option("--json", "Output JSON for automation").addHelpText("after", `
14552
14895
  Examples:
14553
14896
  $ argus dom scroll app --by 0,300