diff --git a/pyproject.toml b/pyproject.toml index 0d2c204..54e599c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,7 @@ dependencies = [ "htmlmin", "jsmin", "Pygments", + "requests", ] description = "Write Markdown and Jinja2 templates to create a website" maintainers = [ @@ -43,7 +44,7 @@ Repository = "https://github.com/siecje/htmd.git" [tool.ruff.lint] ignore = [ - "D100", "D101", "D103", "D104", "D203", "D211", "D212", "D213", + "D100", "D101", "D103", "D104", "D105", "D107", "D203", "D211", "D212", "D213", "INP001", "RET504", "S101", @@ -65,11 +66,12 @@ lines-after-imports = 2 order-by-type = false section-order = ["future", "standard-library", "third-party", "first-party", "local-folder"] -[tool.ruff.per-file-ignores] +[tool.ruff.lint.per-file-ignores] "tests/test_app.py" = ["ARG001"] "tests/test_build.py" = ["I001"] "tests/test_drafts.py" = ["ARG001", "I001"] "tests/test_post_dates.py" = ["I001"] +"tests/test_preview.py" = ["I001"] "tests/test_verify.py" = ["I001"] [tool.setuptools] diff --git a/requirements.txt b/requirements.txt index 7ce3664..e073646 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,27 @@ beautifulsoup4==4.12.3 +blinker==1.7.0 +certifi==2024.2.2 +charset-normalizer==3.3.2 click==8.1.7 csscompressor==0.9.5 -feedwerk==1.1.0 +feedwerk==1.2.0 Flask==3.0.1 Flask-FlatPages==0.8.2 Frozen-Flask==1.0.1 +-e git+ssh://git@github.com/Siecje/htmd.git@4aec976f97c8ed913cb965500e2a3952ec24454d#egg=htmd htmlmin==0.1.12 +idna==3.6 +itsdangerous==2.1.2 +Jinja2==3.1.3 jsmin==3.0.1 +Markdown==3.5.2 +MarkupSafe==2.1.5 Pygments==2.17.2 +PyYAML==6.0.1 +requests==2.31.0 +setuptools==69.0.3 +six==1.16.0 +soupsieve==2.5 +urllib3==2.2.0 +Werkzeug==3.0.1 +wheel==0.42.0 diff --git a/tests/test_preview.py b/tests/test_preview.py index 6007cfa..a0dc09c 100644 --- a/tests/test_preview.py +++ b/tests/test_preview.py @@ -1,25 +1,120 @@ +from pathlib import Path +import time +from types import TracebackType + from click.testing import CliRunner from htmd.cli import preview +import pytest +import requests +import subprocess +import sys + + +def invoke_preview(run_start: CliRunner, args: list[str]) -> None: + # this command fails (werkzeug reload tries to run pytest) + # but it tests coverage + run_start.invoke(preview, args) + + +class run_preview: # noqa: N801 + def __init__( + self: 'run_preview', + args: list[str] | None = None, + max_tries: int = 10, + ) -> None: + self.args = args + self.max_tries = max_tries + def __enter__(self: 'run_preview') -> None: + cmd = [sys.executable, '-m', 'htmd', 'preview'] + if self.args: + cmd += self.args + self.task = subprocess.Popen(cmd) # noqa: S603 + url = 'http://localhost:9090/' + count = 0 + while count < self.max_tries: # pragma: no branch + try: + requests.get(url, timeout=1) + except requests.exceptions.ConnectionError: + count += 1 + time.sleep(0.1) + else: + break -def test_preview(run_start: CliRunner) -> None: - result = run_start.invoke(preview) - # Why is this 5? - expected_exit_code = 5 - assert result.exit_code == expected_exit_code + def __exit__( + self: 'run_preview', + exc_type: type[BaseException] | None, + exc_value: BaseException | None, + traceback: TracebackType | None, + ) -> None: + self.task.terminate() + + +def test_preview(run_start: CliRunner) -> None: # noqa: ARG001 + url = 'http://localhost:9090/' + with pytest.raises(requests.exceptions.ConnectionError): + requests.get(url, timeout=1) + success = 200 + with run_preview(): + response = requests.get(url, timeout=0.01) + assert response.status_code == success def test_preview_css_minify_js_minify(run_start: CliRunner) -> None: - run_start.invoke(preview, ['--css-minify', '--js-minify']) + args = ['--css-minify', '--js-minify'] + invoke_preview(run_start, args) + urls = ( + (200, 'http://localhost:9090/static/combined.min.css'), + (200, 'http://localhost:9090/static/combined.min.js'), + ) + js_path = Path('static') / 'scripts.js' + with js_path.open('w') as js_file: + js_file.write('document.getElementsByTagName("body");') + + with run_preview(args): + for status, url in urls: + response = requests.get(url, timeout=0.01) + assert response.status_code == status def test_preview_no_css_minify(run_start: CliRunner) -> None: - run_start.invoke(preview, ['--no-css-minify', '--js-minify']) + args = ['--no-css-minify', '--js-minify'] + invoke_preview(run_start, args) + urls = ( + (404, 'http://localhost:9090/static/combined.min.css'), + (200, 'http://localhost:9090/static/combined.min.js'), + ) + js_path = Path('static') / 'scripts.js' + with js_path.open('w') as js_file: + js_file.write('document.getElementsByTagName("body");') + + with run_preview(args): + for status, url in urls: + response = requests.get(url, timeout=0.01) + assert response.status_code == status def test_preview_css_minify_no_js_minify(run_start: CliRunner) -> None: - run_start.invoke(preview, ['--css-minify', '--no-js-minify']) + args = ['--css-minify', '--no-js-minify'] + invoke_preview(run_start, args) + urls = ( + (200, 'http://localhost:9090/static/combined.min.css'), + (404, 'http://localhost:9090/static/combined.min.js'), + ) + with run_preview(args): + for status, url in urls: + response = requests.get(url, timeout=0.01) + assert response.status_code == status def test_preview_no_css_minify_no_js_minify(run_start: CliRunner) -> None: - run_start.invoke(preview, ['--no-css-minify', '--no-js-minify']) + args = ['--no-css-minify', '--no-js-minify'] + invoke_preview(run_start, args) + urls = ( + (404, 'http://localhost:9090/static/combined.min.css'), + (404, 'http://localhost:9090/static/combined.min.js'), + ) + with run_preview(args): + for status, url in urls: + response = requests.get(url, timeout=0.01) + assert response.status_code == status