@@ -18,6 +18,7 @@ async def test_sandbox_runner_golden_flow(demo_server, tmp_path):
1818 flow_json = tmp_path / "flow.json"
1919 screenshots_dir = tmp_path / "screenshots"
2020 artifacts_dir = tmp_path / "sandbox_artifacts"
21+ baselines_dir = tmp_path / "baselines"
2122
2223 # 1. Record
2324 recorder = InteractiveRecorder (
@@ -47,7 +48,7 @@ async def drive_recorder():
4748 test_def = generator .generate ()
4849
4950 # 3. Run sandbox
50- runner = SandboxRunner (artifacts_dir = str (artifacts_dir ), headless = True )
51+ runner = SandboxRunner (artifacts_dir = str (artifacts_dir ), baselines_dir = str ( baselines_dir ), headless = True )
5152 run_result = await runner .run (test_def )
5253
5354 # 4. Assertions
@@ -71,3 +72,93 @@ async def drive_recorder():
7172 assert step1 .console_errors is not None
7273 assert step1 .network_errors is not None
7374 assert step1 .a11y_violations is not None
75+
76+
77+ @pytest .mark .asyncio
78+ async def test_baselines_are_stable (demo_server , tmp_path ):
79+ """
80+ Verify that running the sandbox twice with the same baselines_dir actually
81+ REUSES baselines from the first run (no re-baselining).
82+ """
83+ baselines_dir = tmp_path / "shared_baselines"
84+
85+ # Minimal test def: just navigate
86+ test_def = {
87+ "url" : demo_server ,
88+ "steps" : [{
89+ "name" : "navigate_to_start" ,
90+ "action" : "navigate" ,
91+ "value" : demo_server ,
92+ "selectors" : [],
93+ "assertions" : [{"kind" : "url" , "value" : demo_server }]
94+ }]
95+ }
96+
97+ # Run 1: should CREATE baselines
98+ runner1 = SandboxRunner (
99+ artifacts_dir = str (tmp_path / "run1" ),
100+ baselines_dir = str (baselines_dir ),
101+ headless = True ,
102+ )
103+ result1 = await runner1 .run (test_def )
104+ assert result1 .status == "passed"
105+
106+ # Baselines should now exist
107+ baseline_files = list (baselines_dir .glob ("*.png" ))
108+ assert len (baseline_files ) > 0 , "Baselines should have been created"
109+
110+ # Record the modification time of the baseline
111+ mtime_after_run1 = baseline_files [0 ].stat ().st_mtime
112+
113+ # Run 2: should COMPARE against existing baselines (not overwrite)
114+ runner2 = SandboxRunner (
115+ artifacts_dir = str (tmp_path / "run2" ),
116+ baselines_dir = str (baselines_dir ),
117+ headless = True ,
118+ )
119+ result2 = await runner2 .run (test_def )
120+ assert result2 .status == "passed"
121+
122+ # Baseline file should NOT have been overwritten
123+ mtime_after_run2 = baseline_files [0 ].stat ().st_mtime
124+ assert mtime_after_run1 == mtime_after_run2 , "Baseline should not be overwritten on second run"
125+
126+ # Visual diff should be 0 or very close (same page, same viewport)
127+ nav_step = result2 .step_results [0 ]
128+ assert nav_step .visual_diff_score is not None
129+ assert nav_step .visual_diff_score < 0.1 , f"Expected near-zero visual diff, got { nav_step .visual_diff_score } "
130+
131+
132+ def test_visual_check_diff_detection (tmp_path ):
133+ """Unit test for the visual comparison engine's diff detection."""
134+ from PIL import Image
135+ from scrapewizard .engine .checks .visual import perform_visual_check
136+
137+ baselines_dir = tmp_path / "baselines"
138+ diff_dir = tmp_path / "diffs"
139+
140+ # Create a solid red baseline image
141+ img1 = Image .new ("RGB" , (100 , 100 ), color = "red" )
142+ baselines_dir .mkdir (parents = True , exist_ok = True )
143+ img1 .save (baselines_dir / "step_1.png" )
144+
145+ # Create a solid blue "current" screenshot
146+ current_path = tmp_path / "current.png"
147+ img2 = Image .new ("RGB" , (100 , 100 ), color = "blue" )
148+ img2 .save (current_path )
149+
150+ # They should differ significantly
151+ score , diff_path = perform_visual_check (
152+ str (current_path ), "step_1" , str (baselines_dir ), str (diff_dir )
153+ )
154+ assert score > 0.5 , f"Expected high diff score for red vs blue, got { score } "
155+ assert diff_path is not None
156+ assert Path (diff_path ).exists ()
157+
158+ # Now compare identical images — diff should be 0
159+ score2 , diff_path2 = perform_visual_check (
160+ str (baselines_dir / "step_1.png" ), "step_1" , str (baselines_dir ), str (diff_dir )
161+ )
162+ assert score2 == 0.0
163+ assert diff_path2 is None
164+
0 commit comments