visualcheck 0.2.2__tar.gz → 0.2.4__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 (23) hide show
  1. {visualcheck-0.2.2 → visualcheck-0.2.4}/PKG-INFO +1 -1
  2. {visualcheck-0.2.2 → visualcheck-0.2.4}/pyproject.toml +1 -1
  3. {visualcheck-0.2.2 → visualcheck-0.2.4}/src/visualcheck/baseline.py +37 -1
  4. {visualcheck-0.2.2 → visualcheck-0.2.4}/src/visualcheck/capture.py +23 -1
  5. {visualcheck-0.2.2 → visualcheck-0.2.4}/src/visualcheck/figma.py +9 -1
  6. {visualcheck-0.2.2 → visualcheck-0.2.4}/src/visualcheck.egg-info/PKG-INFO +1 -1
  7. {visualcheck-0.2.2 → visualcheck-0.2.4}/README.md +0 -0
  8. {visualcheck-0.2.2 → visualcheck-0.2.4}/setup.cfg +0 -0
  9. {visualcheck-0.2.2 → visualcheck-0.2.4}/src/visualcheck/__init__.py +0 -0
  10. {visualcheck-0.2.2 → visualcheck-0.2.4}/src/visualcheck/cli.py +0 -0
  11. {visualcheck-0.2.2 → visualcheck-0.2.4}/src/visualcheck/config.py +0 -0
  12. {visualcheck-0.2.2 → visualcheck-0.2.4}/src/visualcheck/diff_engine.py +0 -0
  13. {visualcheck-0.2.2 → visualcheck-0.2.4}/src/visualcheck/report.py +0 -0
  14. {visualcheck-0.2.2 → visualcheck-0.2.4}/src/visualcheck/runner.py +0 -0
  15. {visualcheck-0.2.2 → visualcheck-0.2.4}/src/visualcheck/schemas/visualcheck.schema.json +0 -0
  16. {visualcheck-0.2.2 → visualcheck-0.2.4}/src/visualcheck/templates/report.html +0 -0
  17. {visualcheck-0.2.2 → visualcheck-0.2.4}/src/visualcheck/utils.py +0 -0
  18. {visualcheck-0.2.2 → visualcheck-0.2.4}/src/visualcheck/views.py +0 -0
  19. {visualcheck-0.2.2 → visualcheck-0.2.4}/src/visualcheck.egg-info/SOURCES.txt +0 -0
  20. {visualcheck-0.2.2 → visualcheck-0.2.4}/src/visualcheck.egg-info/dependency_links.txt +0 -0
  21. {visualcheck-0.2.2 → visualcheck-0.2.4}/src/visualcheck.egg-info/entry_points.txt +0 -0
  22. {visualcheck-0.2.2 → visualcheck-0.2.4}/src/visualcheck.egg-info/requires.txt +0 -0
  23. {visualcheck-0.2.2 → visualcheck-0.2.4}/src/visualcheck.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: visualcheck
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: Visual regression checking with figma-first baselines, pixel+SSIM diffing, ignore regions, and HTML reports.
5
5
  Author-email: Arif Shah <ashah7775@gmail.com>
6
6
  License: MIT
@@ -3,8 +3,8 @@ requires = ["setuptools>=68", "wheel"]
3
3
  build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
+ version = "0.2.4"
6
7
  name = "visualcheck"
7
- version= "0.2.2"
8
8
  description = "Visual regression checking with figma-first baselines, pixel+SSIM diffing, ignore regions, and HTML reports."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -23,11 +23,47 @@ def baseline_path(cfg: dict, kind: str, view_id: str, snapshot_id: str) -> Path:
23
23
 
24
24
 
25
25
  def resolve_baseline(cfg: dict, view_id: str, snapshot_id: str) -> Tuple[Optional[Path], str]:
26
- """Return (path, kind). kind is figma/runtime/none."""
26
+ """Return (path, kind). kind is figma/runtime/none.
27
+
28
+ If a figma baseline is configured but not present on disk, attempt a sync
29
+ from the Figma API (if configured) and re-check. This allows workflows where
30
+ the authoritative baseline lives in Figma and should be used before creating
31
+ a runtime baseline.
32
+ """
27
33
  for kind in cfg["baseline"]["priority"]:
28
34
  p = baseline_path(cfg, kind, view_id, snapshot_id)
29
35
  if p.exists():
36
+ # If figma baseline exists, make it the authoritative runtime baseline
37
+ if kind == "figma":
38
+ try:
39
+ runtime_p = baseline_path(cfg, "runtime", view_id, snapshot_id)
40
+ ensure_dir(runtime_p.parent)
41
+ # overwrite runtime baseline with figma baseline so Figma is authoritative
42
+ shutil.copy2(p, runtime_p)
43
+ return runtime_p, "figma"
44
+ except Exception:
45
+ # If copying fails, return the figma path
46
+ return p, "figma"
30
47
  return p, kind
48
+
49
+ # If figma is configured as a priority and missing locally, try to fetch it
50
+ if "figma" in (cfg["baseline"]["priority"] or []):
51
+ try:
52
+ summary = figma_sync_baselines(cfg) # best-effort
53
+ # after sync, re-check for figma baseline
54
+ p = baseline_path(cfg, "figma", view_id, snapshot_id)
55
+ if p.exists():
56
+ try:
57
+ runtime_p = baseline_path(cfg, "runtime", view_id, snapshot_id)
58
+ ensure_dir(runtime_p.parent)
59
+ shutil.copy2(p, runtime_p)
60
+ return runtime_p, "figma"
61
+ except Exception:
62
+ return p, "figma"
63
+ except Exception:
64
+ # never fail; always fall through to runtime/none
65
+ pass
66
+
31
67
  return None, "none"
32
68
 
33
69
 
@@ -93,9 +93,31 @@ def capture_all(cfg: dict, env: str, out_dir: Path, headed: bool = False, slow_m
93
93
  url = _abs_url(base_url, pg["url"])
94
94
  print(f"[capture] view={view_id} snapshot={snap_id} url={url}")
95
95
  page.goto(url, wait_until="domcontentloaded")
96
+ # Wait for the configured wait_for selector if present, then allow extra time for lazy loads.
96
97
  if pg.get("wait_for"):
97
98
  page.wait_for_selector(pg["wait_for"], timeout=30000)
98
- page.wait_for_timeout(500)
99
+
100
+ # Optional additional wait and smart auto-scroll to ensure page fully renders dynamic content
101
+ extra_wait_ms = int(cfg.get('capture', {}).get('extra_wait_ms', 1000))
102
+ scroll_times = int(cfg.get('capture', {}).get('scrolls', 5))
103
+ scroll_delay = int(cfg.get('capture', {}).get('scroll_delay_ms', 700))
104
+
105
+ page.wait_for_timeout(extra_wait_ms)
106
+
107
+ # gentle auto-scroll to trigger lazy-loading images/content
108
+ try:
109
+ for i in range(max(1, scroll_times)):
110
+ page.keyboard.press('PageDown')
111
+ page.wait_for_timeout(scroll_delay)
112
+ except Exception:
113
+ # ignore if page doesn't accept keyboard events
114
+ try:
115
+ # fallback to mouse wheel
116
+ for i in range(max(1, scroll_times)):
117
+ page.mouse.wheel(0, 800)
118
+ page.wait_for_timeout(scroll_delay)
119
+ except Exception:
120
+ pass
99
121
 
100
122
  full_page = bool(pg.get("full_page", True))
101
123
  png_path = view_out / f"{slug(snap_id)}.png"
@@ -19,7 +19,15 @@ from decouple import config
19
19
  def _get_token(cfg: dict) -> Optional[str]:
20
20
  fig = cfg.get("figma") or {}
21
21
  token_env = fig.get("token_env") or "FIGMA_TOKEN"
22
- # Prefer .env (python-decouple); fall back to existing env var if present
22
+ # Special-case: when token_env is the canonical "FIGMA_TOKEN" string we must read
23
+ # exclusively from the repo .env (python-decouple) and NOT fall back to system env.
24
+ # This avoids accidental use of a different host env variable when the YAML explicitly
25
+ # requested the canonical name.
26
+ if token_env == "FIGMA_TOKEN":
27
+ return config(token_env, default=None)
28
+
29
+ # For custom token_env names, prefer .env but allow OS-level fallback (useful for
30
+ # host-level overrides like OPENCLAW_FIGMA_TOKEN or similarly named vars).
23
31
  return config(token_env, default=os.environ.get(token_env))
24
32
 
25
33
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: visualcheck
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: Visual regression checking with figma-first baselines, pixel+SSIM diffing, ignore regions, and HTML reports.
5
5
  Author-email: Arif Shah <ashah7775@gmail.com>
6
6
  License: MIT
File without changes
File without changes