verifaied 0.23.0.dev46__tar.gz → 0.23.1.dev48__tar.gz

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.
Files changed (57) hide show
  1. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/PKG-INFO +1 -1
  2. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/pyproject.toml +1 -1
  3. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/recorder_driver.js +16 -3
  4. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/recorder_refs.js +25 -0
  5. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_testcmd.py +48 -0
  6. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/uv.lock +1 -1
  7. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/.gitignore +0 -0
  8. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/LICENSE +0 -0
  9. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/README.md +0 -0
  10. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/__init__.py +0 -0
  11. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/__main__.py +0 -0
  12. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/analyzer.py +0 -0
  13. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/audit.py +0 -0
  14. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/cli.py +0 -0
  15. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/client.py +0 -0
  16. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/config.py +0 -0
  17. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/failure_text.py +0 -0
  18. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/instrument.py +0 -0
  19. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/instrument_snippets.py +0 -0
  20. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/instrumenter.js +0 -0
  21. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/instrumenter.py +0 -0
  22. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/prompts.py +0 -0
  23. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/proxy.py +0 -0
  24. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/record.py +0 -0
  25. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/recorder_observer.js +0 -0
  26. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/recorder_picker.js +0 -0
  27. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/recorder_spec.js +0 -0
  28. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/repo_config.py +0 -0
  29. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/run_reporter.js +0 -0
  30. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/source_index.py +0 -0
  31. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/subprocess_util.py +0 -0
  32. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/suite_report.py +0 -0
  33. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/testcmd.py +0 -0
  34. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/uploader.py +0 -0
  35. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/src/verifaied/varcmd.py +0 -0
  36. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/__init__.py +0 -0
  37. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/conftest.py +0 -0
  38. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_audit.py +0 -0
  39. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_check.py +0 -0
  40. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_check_done.py +0 -0
  41. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_clear_manual.py +0 -0
  42. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_cli.py +0 -0
  43. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_client.py +0 -0
  44. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_config.py +0 -0
  45. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_instrument.py +0 -0
  46. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_instrument_detect.py +0 -0
  47. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_instrument_snippets.py +0 -0
  48. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_instrumenter.py +0 -0
  49. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_prompt_parity.py +0 -0
  50. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_proxy.py +0 -0
  51. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_record.py +0 -0
  52. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_repo_config.py +0 -0
  53. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_reporter_parity.py +0 -0
  54. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_source_index.py +0 -0
  55. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_suite_report.py +0 -0
  56. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_uploader.py +0 -0
  57. {verifaied-0.23.0.dev46 → verifaied-0.23.1.dev48}/tests/test_varcmd.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: verifaied
3
- Version: 0.23.0.dev46
3
+ Version: 0.23.1.dev48
4
4
  Summary: Find what's untested in your code — locally, no account required
5
5
  Project-URL: Homepage, https://pypi.org/project/verifaied/
6
6
  Author: Kyle Richards
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "verifaied"
3
- version = "0.23.0.dev46"
3
+ version = "0.23.1.dev48"
4
4
  description = "Find what's untested in your code — locally, no account required"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -169,6 +169,7 @@ const {
169
169
  compactSnapshot,
170
170
  shouldAutoRead,
171
171
  shortUrl,
172
+ isOwnRequest,
172
173
  noteProblem,
173
174
  problemsSince,
174
175
  AUTO_USER_QUIET_MS,
@@ -443,9 +444,13 @@ async function main() {
443
444
  return lines;
444
445
  };
445
446
  page.on("console", (message) => {
446
- if (message.type() === "error") {
447
- noteProblem(problems, `console error: ${message.text()}`);
448
- }
447
+ if (message.type() !== "error") return;
448
+ // A refused request also arrives here as a resource-load error, which
449
+ // names the URL in its location and the verb nowhere — the coverage
450
+ // reporter's own post again, see `isOwnRequest`.
451
+ const where = message.location() || {};
452
+ if (isOwnRequest(where.url, undefined)) return;
453
+ noteProblem(problems, `console error: ${message.text()}`);
449
454
  });
450
455
  page.on("pageerror", (error) => {
451
456
  noteProblem(
@@ -458,6 +463,8 @@ async function main() {
458
463
  // A cancelled navigation or a request the page abandoned is not the
459
464
  // application failing at anything.
460
465
  if (failure === "net::ERR_ABORTED") return;
466
+ // The coverage reporter's own post — see `isOwnRequest`.
467
+ if (isOwnRequest(request.url(), request.method())) return;
461
468
  noteProblem(
462
469
  problems,
463
470
  `request failed: ${request.method()} ${shortUrl(request.url())} (${failure})`,
@@ -467,6 +474,9 @@ async function main() {
467
474
  const kind = response.request().resourceType();
468
475
  if (kind !== "document" && kind !== "xhr" && kind !== "fetch") return;
469
476
  if (response.status() < 400) return;
477
+ // The coverage reporter's own post — see `isOwnRequest`.
478
+ const request = response.request();
479
+ if (isOwnRequest(request.url(), request.method())) return;
470
480
  noteProblem(
471
481
  problems,
472
482
  `${response.request().method()} ${shortUrl(response.url())} → ${response.status()}`,
@@ -658,6 +668,9 @@ async function main() {
658
668
  const onRequest = (request) => {
659
669
  const kind = request.resourceType();
660
670
  if (kind === "eventsource" || kind === "websocket") return;
671
+ // The coverage reporter's own post — see `isOwnRequest`. It fires
672
+ // on a timer, so an action must never be held waiting for one.
673
+ if (isOwnRequest(request.url(), request.method())) return;
661
674
  inflight.set(request, Date.now());
662
675
  };
663
676
  const onDone = (request) => {
@@ -254,6 +254,30 @@ function shortUrl(url) {
254
254
  }
255
255
  }
256
256
 
257
+ /**
258
+ * Whether a request is the coverage reporter's own post — verifAIed's
259
+ * furniture, not the application's. The reporter every instrumented app
260
+ * carries POSTs `window.__coverage__` to `http://127.0.0.1:<port>/coverage`
261
+ * on a timer, fire-and-forget, and a recording starts no collector, so
262
+ * during one every post is refused. That is not the application failing
263
+ * at anything, and reporting it would have the assistant chase a
264
+ * "backend issue" on every step.
265
+ *
266
+ * The method may be unknown, and then it is simply not asked about: the
267
+ * same refused post also arrives as a `Failed to load resource` console
268
+ * error, which names the URL in its location and the verb nowhere.
269
+ */
270
+ function isOwnRequest(url, method) {
271
+ const verb = String(method == null ? "" : method);
272
+ if (verb !== "" && verb.toUpperCase() !== "POST") return false;
273
+ try {
274
+ const parsed = new URL(String(url));
275
+ return parsed.hostname === "127.0.0.1" && parsed.pathname === "/coverage";
276
+ } catch {
277
+ return false;
278
+ }
279
+ }
280
+
257
281
  /**
258
282
  * Record one problem. A repeat of the last one collapses into a count —
259
283
  * a render loop fires the same error hundreds of times and would
@@ -305,6 +329,7 @@ module.exports = {
305
329
  compactSnapshot,
306
330
  shouldAutoRead,
307
331
  shortUrl,
332
+ isOwnRequest,
308
333
  noteProblem,
309
334
  problemsSince,
310
335
  AUTO_USER_QUIET_MS,
@@ -12454,6 +12454,18 @@ def test_the_refs_module_finds_compares_and_rewrites():
12454
12454
  refs.shortUrl("http://localhost:3000/api/save?x=1#frag"),
12455
12455
  refs.shortUrl("not a url"),
12456
12456
  ],
12457
+ ownRequest: [
12458
+ refs.isOwnRequest("http://127.0.0.1:4571/coverage", "POST"),
12459
+ refs.isOwnRequest("http://127.0.0.1:4620/coverage", "post"),
12460
+ refs.isOwnRequest("http://localhost:3001/coverage", "POST"),
12461
+ refs.isOwnRequest("http://127.0.0.1:4571/coverage", "GET"),
12462
+ refs.isOwnRequest("http://127.0.0.1:4571/api/coverage", "POST"),
12463
+ refs.isOwnRequest("not a url", "POST"),
12464
+ refs.isOwnRequest("http://127.0.0.1:4571/coverage", undefined),
12465
+ refs.isOwnRequest("http://localhost:3001/coverage", undefined),
12466
+ refs.isOwnRequest("http://127.0.0.1:4571/api/coverage", undefined),
12467
+ refs.isOwnRequest("not a url", undefined),
12468
+ ],
12457
12469
  compacted: refs.compactSnapshot([
12458
12470
  "- generic [active] [ref=e1]:",
12459
12471
  " - generic [ref=e2] [cursor=pointer]:",
@@ -12529,6 +12541,25 @@ def test_the_refs_module_finds_compares_and_rewrites():
12529
12541
  assert problems["empty"] == []
12530
12542
  assert problems["ringSize"] == 250
12531
12543
  assert answer["shortUrl"] == ["/api/save?x=1", "not a url"]
12544
+ # Only the reporter's exact shape is verifAIed's furniture: any port
12545
+ # on 127.0.0.1, path /coverage, POST in any case. A `/coverage` route
12546
+ # on localhost is the application's own host and must stay reported,
12547
+ # as must a GET, another path, and anything that is not a URL. The
12548
+ # last four are the console listener's question, where the verb is
12549
+ # unknown: an unsupplied method is not asked about, and the URL alone
12550
+ # still has to be the reporter's.
12551
+ assert answer["ownRequest"] == [
12552
+ True,
12553
+ True,
12554
+ False,
12555
+ False,
12556
+ False,
12557
+ False,
12558
+ True,
12559
+ False,
12560
+ False,
12561
+ False,
12562
+ ]
12532
12563
  # Layout boxes go and their children move up a level; the active
12533
12564
  # root, a clickable container, and every leaf with text stay.
12534
12565
  assert answer["compacted"].split("\n") == [
@@ -13062,6 +13093,23 @@ def test_the_driver_watches_the_page_rather_than_driving_the_recorder():
13062
13093
  assert 'page.ariaSnapshot({ mode: "ai" })' in driver
13063
13094
 
13064
13095
 
13096
+ def test_the_driver_never_reports_the_coverage_reporter_as_a_problem():
13097
+ """The reporter an instrumented dev server injects posts coverage to a
13098
+ collector a recording never starts, so every post is refused. Four
13099
+ call sites keep that out of the assistant's view: the three problem
13100
+ listeners — `requestfailed`, a >=400 `response` (so a collector
13101
+ answering 5xx is not billed to the application either) and `console`,
13102
+ since Chromium reports every refused request as a resource-load error
13103
+ naming the URL in its location and the verb nowhere — and
13104
+ `watchRequests`, so a timer's post never holds an action's settle."""
13105
+ driver = _code_only(DRIVER_PATH.read_text())
13106
+ assert driver.count("isOwnRequest(request.url(), request.method())") == 3
13107
+ assert "isOwnRequest(where.url, undefined)" in driver
13108
+ # And it comes from the refs module, beside the rest of the pure half.
13109
+ destructure = driver.split('require(path.join(__dirname, "recorder_refs.js"))')[0]
13110
+ assert "isOwnRequest," in destructure
13111
+
13112
+
13065
13113
  def test_the_driver_ships_beside_every_module_it_requires():
13066
13114
  """All four files live in the same Python package, so the wheel that
13067
13115
  carries one carries the rest."""
@@ -442,7 +442,7 @@ wheels = [
442
442
 
443
443
  [[package]]
444
444
  name = "verifaied"
445
- version = "0.23.0"
445
+ version = "0.23.1"
446
446
  source = { editable = "." }
447
447
  dependencies = [
448
448
  { name = "httpx" },