Skip to content

Commit 96c4a30

Browse files
committed
add tests; more types
1 parent dcee95c commit 96c4a30

9 files changed

Lines changed: 144 additions & 19 deletions

File tree

.github/workflows/format.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ jobs:
1616
with:
1717
python-version: "3.x"
1818
- run: pip install black
19-
- run: black src
19+
- run: black src tests
2020
- run: git diff --exit-code

.github/workflows/test.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: test
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
9+
jobs:
10+
pre-commit:
11+
name: black
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
- uses: actions/setup-python@v5
16+
with:
17+
python-version: "3.x"
18+
- run: pip install .
19+
- run: pip install pytest
20+
- run: pytest

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ download = "https://pypi.org/project/pyodr/#files"
3232
tracker = "https://github.com/opendocument-app/compare-html/issues"
3333
"release notes" = "https://github.com/opendocument-app/compare-html/releases"
3434

35+
[tool.pytest.ini_options]
36+
pythonpath = ["src"]
37+
3538
[build-system]
3639
requires = [
3740
"setuptools",

src/htmlcmp/html_render_diff.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
from selenium.webdriver.support.ui import WebDriverWait
1515

1616

17-
def to_url(path: Path):
18-
if not isinstance(path, Path):
19-
raise TypeError(f"Expected Path, got {type(path)}")
17+
def to_url(path: str | Path):
18+
if not isinstance(path, (str, Path)):
19+
raise TypeError(f"Expected str or Path, got {type(path)}")
2020

21-
if path.is_file():
21+
if isinstance(path, Path):
22+
if not path.is_file():
23+
raise FileNotFoundError(f"File not found: {path}")
2224
return path.resolve().as_uri()
2325
return path
2426

@@ -55,9 +57,7 @@ def screenshot(browser, url: str):
5557
return Image.open(io.BytesIO(png))
5658

5759

58-
def get_browser(
59-
driver: str = "firefox", max_width: int = 1000, max_height: int = 10000
60-
):
60+
def get_browser(driver: str, max_width: int = 1000, max_height: int = 10000):
6161
if not isinstance(driver, str):
6262
raise TypeError(f"Expected str, got {type(driver)}")
6363
if not isinstance(max_width, int) or not isinstance(max_height, int):
@@ -71,19 +71,19 @@ def get_browser(
7171
options = webdriver.FirefoxOptions()
7272
options.add_argument("--headless")
7373
browser = webdriver.Firefox(options=options)
74-
else: # chrome or unknown
74+
elif driver == "chrome":
7575
options = webdriver.ChromeOptions()
7676
options.add_argument("--headless=new")
7777
browser = webdriver.Chrome(options=options)
78+
else:
79+
raise ValueError(f"Unsupported driver: {driver}")
7880
browser.set_window_size(max_width, max_height)
7981
return browser
8082

8183

82-
def html_render_diff(a: Path, b: Path, browser):
83-
if not isinstance(a, Path) or not isinstance(b, Path):
84-
raise TypeError("Both arguments must be of type Path")
85-
if not a.is_file() or not b.is_file():
86-
raise FileNotFoundError("Both arguments must be files")
84+
def html_render_diff(a: str | Path, b: str | Path, browser):
85+
if browser is None:
86+
raise TypeError("Browser instance cannot be None")
8787

8888
image_a = screenshot(browser, to_url(a))
8989
image_b = screenshot(browser, to_url(b))

src/htmlcmp/tidy_output.py

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@
1010
from htmlcmp.common import bcolors
1111

1212

13-
def tidy_json(path):
13+
def tidy_json(path: Path) -> int:
14+
if not isinstance(path, Path):
15+
raise TypeError("path must be a Path object")
16+
if not path.is_file():
17+
raise FileNotFoundError(f"{path} is not a file")
18+
1419
try:
1520
with open(path, "r") as f:
1621
json.load(f)
@@ -19,7 +24,16 @@ def tidy_json(path):
1924
return 1
2025

2126

22-
def tidy_html(path, html_tidy_config=None):
27+
def tidy_html(path: Path, html_tidy_config: Path = None) -> int:
28+
if not isinstance(path, Path):
29+
raise TypeError("path must be a Path object")
30+
if not path.is_file():
31+
raise FileNotFoundError(f"{path} is not a file")
32+
if html_tidy_config is not None and not isinstance(html_tidy_config, Path):
33+
raise TypeError("html_tidy_config must be a Path object or None")
34+
if html_tidy_config is not None and not html_tidy_config.is_file():
35+
raise FileNotFoundError(f"{html_tidy_config} is not a file")
36+
2337
cmd = ["tidy"]
2438
if html_tidy_config:
2539
cmd.extend(["-config", str(html_tidy_config.resolve())])
@@ -34,22 +48,47 @@ def tidy_html(path, html_tidy_config=None):
3448
return 0
3549

3650

37-
def tidy_file(path, html_tidy_config=None):
51+
def tidy_file(path: Path, html_tidy_config: Path = None) -> int:
52+
if not isinstance(path, Path):
53+
raise TypeError("path must be a Path object")
54+
if not path.is_file():
55+
raise FileNotFoundError(f"{path} is not a file")
56+
3857
if path.suffix == ".json":
3958
return tidy_json(path)
4059
elif path.suffix == ".html":
4160
return tidy_html(path, html_tidy_config=html_tidy_config)
4261

4362

44-
def tidyable_file(path):
63+
def tidyable_file(path: Path) -> bool:
64+
if not isinstance(path, Path):
65+
raise TypeError("path must be a Path object")
66+
if not path.is_file():
67+
raise FileNotFoundError(f"{path} is not a file")
68+
4569
if path.suffix == ".json":
4670
return True
4771
if path.suffix == ".html":
4872
return True
4973
return False
5074

5175

52-
def tidy_dir(path, level=0, prefix="", html_tidy_config=None):
76+
def tidy_dir(
77+
path: Path, level: int = 0, prefix: str = "", html_tidy_config: Path = None
78+
) -> dict[str, list[Path]]:
79+
if not isinstance(path, Path):
80+
raise TypeError("path must be a Path object")
81+
if not path.is_dir():
82+
raise NotADirectoryError(f"{path} is not a directory")
83+
if not isinstance(level, int) or level < 0:
84+
raise ValueError("level must be a non-negative integer")
85+
if not isinstance(prefix, str):
86+
raise TypeError("prefix must be a string")
87+
if html_tidy_config is not None and not isinstance(html_tidy_config, Path):
88+
raise TypeError("html_tidy_config must be a Path object or None")
89+
if html_tidy_config is not None and not html_tidy_config.is_file():
90+
raise FileNotFoundError(f"{html_tidy_config} is not a file")
91+
5392
prefix_file = prefix + "├── "
5493
if level == 0:
5594
print(f"tidy dir {path}")

tests/test1.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<body>
4+
test1
5+
</body>
6+
</html>

tests/test2.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<body>
4+
test2
5+
</body>
6+
</html>

tests/test_html_render_diff.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import pytest
2+
from pathlib import Path
3+
4+
from htmlcmp.html_render_diff import to_url, get_browser, html_render_diff
5+
6+
7+
def test_to_url():
8+
with pytest.raises(TypeError):
9+
to_url(None)
10+
with pytest.raises(TypeError):
11+
to_url(1)
12+
with pytest.raises(FileNotFoundError):
13+
to_url(Path(__file__).parent)
14+
assert to_url("file:///path/to/file") == "file:///path/to/file"
15+
assert to_url("https://example.com") == "https://example.com"
16+
assert to_url(Path(__file__))
17+
18+
19+
def test_get_browser():
20+
with pytest.raises(ValueError):
21+
get_browser("unsupported_driver")
22+
23+
# Test with Chrome
24+
browser = get_browser("chrome")
25+
assert browser.name == "chrome"
26+
browser.quit()
27+
28+
# Test with Firefox
29+
browser = get_browser("firefox")
30+
assert browser.name == "firefox"
31+
browser.quit()
32+
33+
# Test with PhantomJS
34+
browser = get_browser("phantomjs")
35+
assert browser.name == "phantomjs"
36+
browser.quit()
37+
38+
39+
def test_html_render_diff():
40+
test1 = Path(__file__).parent / "test1.html"
41+
test2 = Path(__file__).parent / "test2.html"
42+
43+
with pytest.raises(TypeError):
44+
html_render_diff(None, None, None)
45+
with pytest.raises(TypeError):
46+
html_render_diff(str(test1), str(test2), None)
47+
48+
diff, _ = html_render_diff(test1, test1, get_browser("firefox"))
49+
assert diff.getbbox() is None
50+
diff, _ = html_render_diff(test1, test2, get_browser("firefox"))
51+
assert diff.getbbox() is not None

0 commit comments

Comments
 (0)