mirror of
https://git.zavage.net/Zavage-Software/wabot.git
synced 2026-07-21 13:06:08 -06:00
test: verify screenshot seam alignment; release tile buffers
This commit is contained in:
parent
ab50a984a8
commit
cafacee2b9
@ -2298,6 +2298,48 @@ class TestChromiumPath:
|
|||||||
if c.args and str(c.args[0]).startswith("window.scrollTo")
|
if c.args and str(c.args[0]).startswith("window.scrollTo")
|
||||||
]
|
]
|
||||||
assert len(scroll_calls) >= 2
|
assert len(scroll_calls) >= 2
|
||||||
|
|
||||||
|
def test_tall_page_stitches_tiles_bottom_aligned(self, tmp_path):
|
||||||
|
driver = MagicMock(name="driver")
|
||||||
|
driver.capabilities = {"browserName": "chrome"}
|
||||||
|
driver.execute_script.side_effect = lambda script: {
|
||||||
|
"return document.body.parentNode.scrollWidth": 100,
|
||||||
|
"return document.body.parentNode.scrollHeight": 150, # 3 tiles of 60
|
||||||
|
"return document.documentElement.clientWidth": 100,
|
||||||
|
"return window.innerHeight": 60,
|
||||||
|
}.get(script) # window.scrollTo(...) -> None
|
||||||
|
driver.get_screenshot_as_png.side_effect = [
|
||||||
|
png_bytes(100, 60, (255, 0, 0)), # tile @ y=0
|
||||||
|
png_bytes(100, 60, (0, 255, 0)), # tile @ y=60
|
||||||
|
png_bytes(100, 60, (0, 0, 255)), # tile @ y=120, clamped to paste_y=90
|
||||||
|
]
|
||||||
|
out = tmp_path / "shot.png"
|
||||||
|
assert save_full_page(driver, str(out)) is True
|
||||||
|
img = Image.open(out)
|
||||||
|
assert img.size == (100, 150)
|
||||||
|
assert img.getpixel((50, 30)) == (255, 0, 0) # first tile
|
||||||
|
assert img.getpixel((50, 75)) == (0, 255, 0) # second tile (rows 60-89)
|
||||||
|
assert img.getpixel((50, 140)) == (0, 0, 255) # third tile, bottom-aligned
|
||||||
|
|
||||||
|
def test_wide_page_clamps_last_column(self, tmp_path):
|
||||||
|
driver = MagicMock(name="driver")
|
||||||
|
driver.capabilities = {"browserName": "chrome"}
|
||||||
|
driver.execute_script.side_effect = lambda script: {
|
||||||
|
"return document.body.parentNode.scrollWidth": 150, # 2 columns of 100
|
||||||
|
"return document.body.parentNode.scrollHeight": 60,
|
||||||
|
"return document.documentElement.clientWidth": 100,
|
||||||
|
"return window.innerHeight": 60,
|
||||||
|
}.get(script)
|
||||||
|
driver.get_screenshot_as_png.side_effect = [
|
||||||
|
png_bytes(100, 60, (255, 0, 0)), # column @ x=0
|
||||||
|
png_bytes(100, 60, (0, 0, 255)), # column @ x=100, clamped to paste_x=50
|
||||||
|
]
|
||||||
|
out = tmp_path / "shot.png"
|
||||||
|
assert save_full_page(driver, str(out)) is True
|
||||||
|
img = Image.open(out)
|
||||||
|
assert img.size == (150, 60)
|
||||||
|
assert img.getpixel((25, 30)) == (255, 0, 0) # left column (cols 0-49)
|
||||||
|
assert img.getpixel((140, 30)) == (0, 0, 255) # right column, clamped (cols 50-149)
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2: Run tests to verify they fail**
|
- [ ] **Step 2: Run tests to verify they fail**
|
||||||
@ -2371,12 +2413,14 @@ def _stitch_chromium(driver, filename: str) -> bool:
|
|||||||
while x < total_width:
|
while x < total_width:
|
||||||
driver.execute_script(f"window.scrollTo({x}, {y})")
|
driver.execute_script(f"window.scrollTo({x}, {y})")
|
||||||
time.sleep(_SCROLL_SETTLE_SECONDS)
|
time.sleep(_SCROLL_SETTLE_SECONDS)
|
||||||
tile = Image.open(BytesIO(driver.get_screenshot_as_png()))
|
# Tiles are device pixels; the canvas/scroll math is CSS pixels. Assumes
|
||||||
# the last row/column can't scroll a full viewport: paste aligned
|
# devicePixelRatio == 1 (true for headless chromium in the test target).
|
||||||
# to the bottom/right edge instead of duplicating content
|
with Image.open(BytesIO(driver.get_screenshot_as_png())) as tile:
|
||||||
paste_x = min(x, total_width - viewport_width)
|
# the last row/column can't scroll a full viewport: paste aligned
|
||||||
paste_y = min(y, total_height - viewport_height)
|
# to the bottom/right edge instead of duplicating content
|
||||||
stitched.paste(tile, (max(paste_x, 0), max(paste_y, 0)))
|
paste_x = min(x, total_width - viewport_width)
|
||||||
|
paste_y = min(y, total_height - viewport_height)
|
||||||
|
stitched.paste(tile, (max(paste_x, 0), max(paste_y, 0)))
|
||||||
x += viewport_width
|
x += viewport_width
|
||||||
y += viewport_height
|
y += viewport_height
|
||||||
stitched.save(filename)
|
stitched.save(filename)
|
||||||
@ -2387,7 +2431,7 @@ def _stitch_chromium(driver, filename: str) -> bool:
|
|||||||
- [ ] **Step 4: Run tests to verify they pass**
|
- [ ] **Step 4: Run tests to verify they pass**
|
||||||
|
|
||||||
Run: `uv run pytest tests/unit/test_screenshot.py -v`
|
Run: `uv run pytest tests/unit/test_screenshot.py -v`
|
||||||
Expected: 3 passed. Also run `uv run pytest` — all unit tests still pass.
|
Expected: 5 passed. Also run `uv run pytest` — all unit tests still pass.
|
||||||
|
|
||||||
- [ ] **Step 5: Commit**
|
- [ ] **Step 5: Commit**
|
||||||
|
|
||||||
@ -2949,7 +2993,7 @@ Run: `uv run pytest tests/unit/test_api.py -v`
|
|||||||
Expected: 11 passed
|
Expected: 11 passed
|
||||||
|
|
||||||
Run: `uv run pytest`
|
Run: `uv run pytest`
|
||||||
Expected: full unit suite passes (126 tests: pacing 7, sessions 14, hosts 19, reattach 6, fields 17, page 36, screenshot 3, browser 13, api 11)
|
Expected: full unit suite passes (128 tests: pacing 7, sessions 14, hosts 19, reattach 6, fields 17, page 36, screenshot 5, browser 13, api 11)
|
||||||
|
|
||||||
- [ ] **Step 5: Commit**
|
- [ ] **Step 5: Commit**
|
||||||
|
|
||||||
|
|||||||
@ -59,12 +59,14 @@ def _stitch_chromium(driver, filename: str) -> bool:
|
|||||||
while x < total_width:
|
while x < total_width:
|
||||||
driver.execute_script(f"window.scrollTo({x}, {y})")
|
driver.execute_script(f"window.scrollTo({x}, {y})")
|
||||||
time.sleep(_SCROLL_SETTLE_SECONDS)
|
time.sleep(_SCROLL_SETTLE_SECONDS)
|
||||||
tile = Image.open(BytesIO(driver.get_screenshot_as_png()))
|
# Tiles are device pixels; the canvas/scroll math is CSS pixels. Assumes
|
||||||
# the last row/column can't scroll a full viewport: paste aligned
|
# devicePixelRatio == 1 (true for headless chromium in the test target).
|
||||||
# to the bottom/right edge instead of duplicating content
|
with Image.open(BytesIO(driver.get_screenshot_as_png())) as tile:
|
||||||
paste_x = min(x, total_width - viewport_width)
|
# the last row/column can't scroll a full viewport: paste aligned
|
||||||
paste_y = min(y, total_height - viewport_height)
|
# to the bottom/right edge instead of duplicating content
|
||||||
stitched.paste(tile, (max(paste_x, 0), max(paste_y, 0)))
|
paste_x = min(x, total_width - viewport_width)
|
||||||
|
paste_y = min(y, total_height - viewport_height)
|
||||||
|
stitched.paste(tile, (max(paste_x, 0), max(paste_y, 0)))
|
||||||
x += viewport_width
|
x += viewport_width
|
||||||
y += viewport_height
|
y += viewport_height
|
||||||
stitched.save(filename)
|
stitched.save(filename)
|
||||||
|
|||||||
@ -66,3 +66,45 @@ class TestChromiumPath:
|
|||||||
if c.args and str(c.args[0]).startswith("window.scrollTo")
|
if c.args and str(c.args[0]).startswith("window.scrollTo")
|
||||||
]
|
]
|
||||||
assert len(scroll_calls) >= 2
|
assert len(scroll_calls) >= 2
|
||||||
|
|
||||||
|
def test_tall_page_stitches_tiles_bottom_aligned(self, tmp_path):
|
||||||
|
driver = MagicMock(name="driver")
|
||||||
|
driver.capabilities = {"browserName": "chrome"}
|
||||||
|
driver.execute_script.side_effect = lambda script: {
|
||||||
|
"return document.body.parentNode.scrollWidth": 100,
|
||||||
|
"return document.body.parentNode.scrollHeight": 150, # 3 tiles of 60
|
||||||
|
"return document.documentElement.clientWidth": 100,
|
||||||
|
"return window.innerHeight": 60,
|
||||||
|
}.get(script) # window.scrollTo(...) -> None
|
||||||
|
driver.get_screenshot_as_png.side_effect = [
|
||||||
|
png_bytes(100, 60, (255, 0, 0)), # tile @ y=0
|
||||||
|
png_bytes(100, 60, (0, 255, 0)), # tile @ y=60
|
||||||
|
png_bytes(100, 60, (0, 0, 255)), # tile @ y=120, clamped to paste_y=90
|
||||||
|
]
|
||||||
|
out = tmp_path / "shot.png"
|
||||||
|
assert save_full_page(driver, str(out)) is True
|
||||||
|
img = Image.open(out)
|
||||||
|
assert img.size == (100, 150)
|
||||||
|
assert img.getpixel((50, 30)) == (255, 0, 0) # first tile
|
||||||
|
assert img.getpixel((50, 75)) == (0, 255, 0) # second tile (rows 60-89)
|
||||||
|
assert img.getpixel((50, 140)) == (0, 0, 255) # third tile, bottom-aligned
|
||||||
|
|
||||||
|
def test_wide_page_clamps_last_column(self, tmp_path):
|
||||||
|
driver = MagicMock(name="driver")
|
||||||
|
driver.capabilities = {"browserName": "chrome"}
|
||||||
|
driver.execute_script.side_effect = lambda script: {
|
||||||
|
"return document.body.parentNode.scrollWidth": 150, # 2 columns of 100
|
||||||
|
"return document.body.parentNode.scrollHeight": 60,
|
||||||
|
"return document.documentElement.clientWidth": 100,
|
||||||
|
"return window.innerHeight": 60,
|
||||||
|
}.get(script)
|
||||||
|
driver.get_screenshot_as_png.side_effect = [
|
||||||
|
png_bytes(100, 60, (255, 0, 0)), # column @ x=0
|
||||||
|
png_bytes(100, 60, (0, 0, 255)), # column @ x=100, clamped to paste_x=50
|
||||||
|
]
|
||||||
|
out = tmp_path / "shot.png"
|
||||||
|
assert save_full_page(driver, str(out)) is True
|
||||||
|
img = Image.open(out)
|
||||||
|
assert img.size == (150, 60)
|
||||||
|
assert img.getpixel((25, 30)) == (255, 0, 0) # left column (cols 0-49)
|
||||||
|
assert img.getpixel((140, 30)) == (0, 0, 255) # right column, clamped (cols 50-149)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user