Skip to content

Commit 244fe30

Browse files
committed
Fix compatibles for windows, latest chrome; add test for xpath
1 parent 80b9b17 commit 244fe30

File tree

7 files changed

+58
-35
lines changed

7 files changed

+58
-35
lines changed

pytest_image_diff/_types.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
from pathlib import Path
12
from typing import BinaryIO, Union, Tuple, Optional
23

34
from PIL.Image import Image
45
from typing_extensions import Literal, Protocol
56

6-
PathOrFileType = Union[str, bytes, BinaryIO]
7+
PathOrFileType = Union[str, bytes, Path, BinaryIO]
78
ImageFileType = Union[Image, PathOrFileType]
89
ImageSize = Tuple[int, int]
910

pytest_image_diff/helpers.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import os
2+
import pathlib
23
import shutil
34
import typing
5+
from contextlib import contextmanager
6+
from tempfile import NamedTemporaryFile
47

58
from PIL.Image import Image
69
from _pytest import junitxml
@@ -27,6 +30,19 @@ def build_filename(
2730
)
2831

2932

33+
@contextmanager
34+
def temp_file(suffix: typing.Optional[str] = None) -> typing.Iterator[pathlib.Path]:
35+
with NamedTemporaryFile(suffix=suffix, delete=False) as tf:
36+
temp_image_path = pathlib.Path(tf.name)
37+
try:
38+
yield temp_image_path
39+
finally:
40+
try:
41+
temp_image_path.unlink()
42+
except FileNotFoundError:
43+
pass
44+
45+
3046
class TestInfo:
3147
test_name: str
3248
class_name: str
@@ -58,13 +74,13 @@ def get_test_info(
5874
return TestInfo.get_test_info(request, suffix, prefix)
5975

6076

61-
def image_save(image: ImageFileType, path: str) -> None:
77+
def image_save(image: ImageFileType, path: typing.Union[str, pathlib.Path]) -> None:
6278
if isinstance(image, Image):
6379
image.save(path)
6480
elif isinstance(image, str):
6581
if not os.path.exists(image):
6682
raise ValueError("Image maybe path. Path not exists!")
67-
shutil.copyfile(image, path)
83+
shutil.copyfile(image, str(path))
6884
elif hasattr(image, "read"):
6985
with open(path, "wb") as f:
7086
image = typing.cast(typing.BinaryIO, image)

pytest_image_diff/plugin.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import os
2-
from tempfile import NamedTemporaryFile
32
from typing import Optional, NamedTuple, cast, Callable, Generator
43

54
import pytest
@@ -8,7 +7,7 @@
87
from _pytest.runner import CallInfo
98

109
from ._types import ImageFileType, ImageRegressionCallableType, ImageDiffCallableType
11-
from .helpers import get_test_info, build_filename, image_save, ensure_dirs
10+
from .helpers import get_test_info, build_filename, image_save, ensure_dirs, temp_file
1211
from .image_diff import _diff
1312

1413
try:
@@ -18,7 +17,7 @@
1817

1918

2019
@pytest.hookimpl(tryfirst=True, hookwrapper=True) # type: ignore
21-
def pytest_runtest_makereport(item: Function, call: CallInfo) -> None:
20+
def pytest_runtest_makereport(item: Function, call: CallInfo): # type: ignore
2221
# execute all other hooks to obtain the report object
2322
outcome = yield
2423
rep = outcome.get_result()
@@ -180,8 +179,6 @@ def _factory(
180179
) -> bool:
181180
if threshold is None:
182181
threshold = image_diff_threshold
183-
image_temp_file = NamedTemporaryFile(suffix=".jpg")
184-
image_2_temp_file = NamedTemporaryFile(suffix=".jpg")
185182

186183
_info = _image_diff_info(image, suffix)
187184
diff_path = cast(str, _info.diff_name)
@@ -198,9 +195,12 @@ def _cleanup() -> None:
198195

199196
request.addfinalizer(_cleanup)
200197

201-
image_save(image, path=image_temp_file.name)
202-
image_save(image_2, path=image_2_temp_file.name)
203-
diff_ratio = _diff(image_temp_file.name, image_2_temp_file.name, diff_path)
198+
with temp_file(suffix=".jpg") as image_temp_file, temp_file(
199+
suffix=".jpg"
200+
) as image_2_temp_file:
201+
image_save(image, path=image_temp_file)
202+
image_save(image_2, path=image_2_temp_file)
203+
diff_ratio = _diff(image_temp_file, image_2_temp_file, diff_path)
204204
assert diff_ratio <= threshold, "Image not equals! See %s" % diff_path # noqa
205205
return True
206206

pytest_image_diff/splinter.py

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import os
2-
import pathlib
3-
import pytest
4-
from tempfile import NamedTemporaryFile
52
from typing import Optional, Generator
3+
4+
import pytest
65
from typing_extensions import Protocol
76

7+
from .helpers import temp_file
88

99
try:
1010
# Check pytest-splinter
@@ -39,7 +39,8 @@ def screenshot_regression(
3939
:param browser: optional, by default from `browser` fixture
4040
:param threshold: float, by default from `image_diff_threshold`
4141
:param suffix: str, need for multiple checks by one test
42-
:param xpath: str, optional xpath expression to select an element to screenshot instead of page
42+
:param xpath: str, optional xpath expression to select an element to
43+
screenshot instead of page
4344
"""
4445
default_browser = browser
4546

@@ -55,30 +56,26 @@ def _factory(
5556
if threshold is None:
5657
threshold = image_diff_threshold
5758

58-
with NamedTemporaryFile(suffix=".png", delete=False) as tf:
59-
temp_image_path = pathlib.Path(tf.name)
60-
61-
try:
59+
with temp_file(suffix=".png") as temp_image_path:
6260
screenshot_path = os.fspath(temp_image_path)
6361

6462
if xpath:
6563
# `unique_file=False` since we already have a temporary file
6664
#
67-
# Since an xpath screenshot composes its own file name, we need to give it the prefix and
68-
# suffix as separate parameters. `:-4` for the path without extension, then suffix given manually.
69-
browser.find_by_xpath(xpath).first.screenshot(screenshot_path[:-4],
70-
suffix=screenshot_path[-4:],
71-
unique_file=False,
72-
full=True,
73-
)
65+
# Since an xpath screenshot composes its own file name,
66+
# we need to give it the prefix and
67+
# suffix as separate parameters. `:-4` for the path without extension,
68+
# then suffix given manually.
69+
browser.find_by_xpath(xpath).first.screenshot(
70+
screenshot_path[:-4],
71+
suffix=screenshot_path[-4:],
72+
unique_file=False,
73+
full=True,
74+
)
7475
else:
7576
browser.driver.save_screenshot(screenshot_path)
7677

7778
result = image_regression(screenshot_path, threshold, suffix)
78-
finally:
79-
temp_image_path.unlink(missing_ok=True)
80-
81-
return result
82-
79+
return result
8380

8481
yield _factory

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ universal = 1
2020

2121
[flake8]
2222
ignore = D203
23-
exclude =
23+
exclude =
2424
.git/,
2525
.tox/,
2626
docs/,

setup.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,7 @@ def read(fname):
5454
python_requires=">=3.6, <4",
5555
entry_points={"pytest11": ["image_diff = pytest_image_diff.plugin"]},
5656
install_requires=["pytest", "typing_extensions", "diffimg", "imgdiff"],
57-
extras_require={
58-
"splinter": ["pytest-splinter>=2.1.0", "chromedriver-binary==2.40.1"]
59-
},
57+
extras_require={"splinter": ["pytest-splinter>=2.1.0", "chromedriver-binary-auto"]},
6058
zip_safe=False,
6159
include_package_data=True,
6260
keywords=["pytest"],

tests/test_splinter.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,14 @@ def test_splinter(browser, screenshot_regression):
5050
screenshot_regression()
5151
browser.driver.set_window_size(800, 600)
5252
screenshot_regression(suffix="small_window")
53+
54+
55+
@with_splinter
56+
def test_splinter_with_xpath(browser, screenshot_regression):
57+
tf = tempfile.NamedTemporaryFile(suffix=".html")
58+
tf.write(b"<html><body><h1>Example</h1></body></html>")
59+
tf.flush()
60+
61+
browser.driver.set_window_size(1280, 1024)
62+
browser.visit("file://" + tf.name)
63+
screenshot_regression(xpath="//h1")

0 commit comments

Comments
 (0)