Skip to content

Commit

Permalink
Chore: Use pytest fixtures in place of custom globals, etc (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
stumpylog authored Sep 30, 2024
1 parent 2649b27 commit 7dfe72c
Show file tree
Hide file tree
Showing 10 changed files with 329 additions and 254 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Bump pypa/gh-action-pypi-publish from 1.9.0 to 1.10.2 by @dependabot ([#31](https://github.com/stumpylog/gotenberg-client/pull/31))
- CI testing now runs against Gotenberg 8.11 ([#32](https://github.com/stumpylog/gotenberg-client/pull/32))
- Development tool updates in `pyproject.toml` and pre-commit hook updates
- Properly use `pytest` fixtures in all testing ([#34](https://github.com/stumpylog/gotenberg-client/pull/34))

## [0.6.0] - 2024-06-13

Expand Down
137 changes: 119 additions & 18 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,137 @@
import logging
import os
import shutil
import tempfile
from pathlib import Path
from typing import Final
from typing import Generator
from typing import Union

import pytest

from gotenberg_client import GotenbergClient
from gotenberg_client import SingleFileResponse
from gotenberg_client import ZipFileResponse

GOTENBERG_URL: Final[str] = os.getenv("GOTENBERG_URL", "http://localhost:3000")

SAMPLE_DIR: Final[Path] = Path(__file__).parent.resolve() / "samples"
SAVE_DIR: Final[Path] = Path(__file__).parent.resolve() / "outputs"
SAVE_OUTPUTS: Final[bool] = "SAVE_TEST_OUTPUT" in os.environ
@pytest.fixture(scope="session")
def gotenberg_host() -> str:
return os.getenv("GOTENBERG_URL", "http://localhost:3000")

if SAVE_OUTPUTS:
shutil.rmtree(SAVE_DIR, ignore_errors=True)
SAVE_DIR.mkdir()

@pytest.fixture(scope="session")
def web_server_host() -> str:
return os.getenv("WEBSERVER_HOST", "http://localhost:8888")


@pytest.fixture(scope="session")
def sample_directory() -> Path:
return Path(__file__).parent.resolve() / "samples"


@pytest.fixture(scope="session")
def basic_html_file(sample_directory: Path) -> Path:
return sample_directory / "basic.html"


@pytest.fixture(scope="session")
def footer_html_file(sample_directory: Path) -> Path:
return sample_directory / "footer.html"


@pytest.fixture(scope="session")
def complex_html_file(sample_directory: Path) -> Path:
return sample_directory / "complex.html"


@pytest.fixture(scope="session")
def header_html_file(sample_directory: Path) -> Path:
return sample_directory / "header.html"


@pytest.fixture(scope="session")
def img_gif_file(sample_directory: Path) -> Path:
return sample_directory / "img.gif"


@pytest.fixture(scope="session")
def font_file(sample_directory: Path) -> Path:
return sample_directory / "font.woff"


@pytest.fixture(scope="session")
def css_style_file(sample_directory: Path) -> Path:
return sample_directory / "style.css"


@pytest.fixture(scope="session")
def markdown_index_file(sample_directory: Path) -> Path:
return sample_directory / "markdown_index.html"


@pytest.fixture(scope="session")
def markdown_sample_one_file(sample_directory: Path) -> Path:
return sample_directory / "markdown1.md"


@pytest.fixture(scope="session")
def markdown_sample_two_file(sample_directory: Path) -> Path:
return sample_directory / "markdown2.md"


@pytest.fixture(scope="session")
def docx_sample_file(sample_directory: Path) -> Path:
return sample_directory / "sample.docx"


@pytest.fixture(scope="session")
def odt_sample_file(sample_directory: Path) -> Path:
return sample_directory / "sample.odt"


@pytest.fixture(scope="session")
def xlsx_sample_file(sample_directory: Path) -> Path:
return sample_directory / "sample.xlsx"


@pytest.fixture(scope="session")
def ods_sample_file(sample_directory: Path) -> Path:
return sample_directory / "sample.ods"


@pytest.fixture(scope="session")
def pdf_sample_one_file(sample_directory: Path) -> Path:
return sample_directory / "sample1.pdf"


@pytest.fixture(scope="session")
def output_file_save_directory() -> Path:
return Path(__file__).parent.resolve() / "outputs"


@pytest.fixture(scope="session")
def save_output_files(output_file_save_directory: Path) -> bool:
val = True
if val:
shutil.rmtree(output_file_save_directory, ignore_errors=True)
output_file_save_directory.mkdir()
return val


@pytest.fixture
def client() -> Generator[GotenbergClient, None, None]:
with GotenbergClient(host=GOTENBERG_URL, log_level=logging.INFO) as client:
yield client
def output_saver_factory(request, save_output_files: bool, output_file_save_directory: Path): # noqa: FBT001
def _save_the_item(response: Union[SingleFileResponse, ZipFileResponse], extra: str = ""): # noqa: ARG001
if save_output_files:
extension_mapping = {
"application/zip": ".zip",
"application/pdf": ".pdf",
"image/png": ".png",
}
extension = extension_mapping[response.headers["Content-Type"]]
response.to_file(output_file_save_directory / f"{request.node.originalname}{extension}")

return _save_the_item


@pytest.fixture
def temporary_dir() -> Generator[Path, None, None]:
"""
Creates and cleans up a temporary directory for tests
"""
with tempfile.TemporaryDirectory() as tmp_dir:
yield Path(tmp_dir).resolve()
def client(gotenberg_host: str) -> Generator[GotenbergClient, None, None]:
with GotenbergClient(host=gotenberg_host, log_level=logging.INFO) as client:
yield client
74 changes: 37 additions & 37 deletions tests/test_convert_chromium_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,84 +15,83 @@
from gotenberg_client.options import PageMarginsType
from gotenberg_client.options import PageOrientation
from gotenberg_client.options import PdfAFormat
from tests.conftest import SAMPLE_DIR
from tests.conftest import SAVE_DIR
from tests.conftest import SAVE_OUTPUTS
from tests.utils import verify_stream_contains


class TestConvertChromiumHtmlRoute:
def test_basic_convert(self, client: GotenbergClient):
test_file = SAMPLE_DIR / "basic.html"

def test_basic_convert(self, client: GotenbergClient, basic_html_file: Path):
with client.chromium.html_to_pdf() as route:
resp = route.index(test_file).run_with_retry()
resp = route.index(basic_html_file).run_with_retry()

assert resp.status_code == codes.OK
assert "Content-Type" in resp.headers
assert resp.headers["Content-Type"] == "application/pdf"
if SAVE_OUTPUTS:
resp.to_file(SAVE_DIR / "test_basic_convert.pdf")

def test_convert_with_header_footer(self, client: GotenbergClient):
test_file = SAMPLE_DIR / "basic.html"
header_file = SAMPLE_DIR / "header.html"
footer_file = SAMPLE_DIR / "footer.html"

def test_convert_with_header_footer(
self,
client: GotenbergClient,
basic_html_file: Path,
header_html_file: Path,
footer_html_file: Path,
):
with client.chromium.html_to_pdf() as route:
resp = route.index(test_file).header(header_file).footer(footer_file).run_with_retry()
resp = route.index(basic_html_file).header(header_html_file).footer(footer_html_file).run_with_retry()

assert resp.status_code == codes.OK
assert "Content-Type" in resp.headers
assert resp.headers["Content-Type"] == "application/pdf"

def test_convert_additional_files(self, client: GotenbergClient):
test_file = SAMPLE_DIR / "complex.html"
img = SAMPLE_DIR / "img.gif"
font = SAMPLE_DIR / "font.woff"
style = SAMPLE_DIR / "style.css"

def test_convert_additional_files(
self,
client: GotenbergClient,
complex_html_file: Path,
img_gif_file: Path,
font_file: Path,
css_style_file: Path,
):
with client.chromium.html_to_pdf() as route:
resp = route.index(test_file).resource(img).resource(font).resource(style).run_with_retry()
resp = (
route.index(complex_html_file)
.resource(img_gif_file)
.resource(font_file)
.resource(css_style_file)
.run_with_retry()
)

assert resp.status_code == codes.OK
assert "Content-Type" in resp.headers
assert resp.headers["Content-Type"] == "application/pdf"

if SAVE_OUTPUTS:
resp.to_file(SAVE_DIR / "test_convert_additional_files.pdf")

@pytest.mark.parametrize(
("gt_format", "pike_format"),
[(PdfAFormat.A2b, "2B"), (PdfAFormat.A3b, "3B")],
)
def test_convert_pdfa_format(
self,
client: GotenbergClient,
temporary_dir: Path,
basic_html_file: Path,
tmp_path: Path,
gt_format: PdfAFormat,
pike_format: str,
):
test_file = SAMPLE_DIR / "basic.html"

with client.chromium.html_to_pdf() as route:
resp = route.index(test_file).pdf_format(gt_format).run_with_retry()
resp = route.index(basic_html_file).pdf_format(gt_format).run_with_retry()

assert resp.status_code == codes.OK
assert "Content-Type" in resp.headers
assert resp.headers["Content-Type"] == "application/pdf"

output = temporary_dir / "test_convert_pdfa_format.pdf"
output = tmp_path / "test_convert_pdfa_format.pdf"
resp.to_file(output)
with pikepdf.open(output) as pdf:
meta = pdf.open_metadata()
assert meta.pdfa_status == pike_format


class TestConvertChromiumHtmlRouteMocked:
def test_convert_page_size(self, client: GotenbergClient, httpx_mock: HTTPXMock):
def test_convert_page_size(self, client: GotenbergClient, sample_directory: Path, httpx_mock: HTTPXMock):
httpx_mock.add_response(method="POST")
test_file = SAMPLE_DIR / "basic.html"
test_file = sample_directory / "basic.html"

with client.chromium.html_to_pdf() as route:
_ = route.index(test_file).size(A4).run()
Expand All @@ -101,9 +100,9 @@ def test_convert_page_size(self, client: GotenbergClient, httpx_mock: HTTPXMock)
verify_stream_contains("paperWidth", "8.27", request.stream)
verify_stream_contains("paperHeight", "11.7", request.stream)

def test_convert_margin(self, client: GotenbergClient, httpx_mock: HTTPXMock):
def test_convert_margin(self, client: GotenbergClient, sample_directory: Path, httpx_mock: HTTPXMock):
httpx_mock.add_response(method="POST")
test_file = SAMPLE_DIR / "basic.html"
test_file = sample_directory / "basic.html"

with client.chromium.html_to_pdf() as route:
_ = (
Expand All @@ -125,9 +124,9 @@ def test_convert_margin(self, client: GotenbergClient, httpx_mock: HTTPXMock):
verify_stream_contains("marginLeft", "3mm", request.stream)
verify_stream_contains("marginRight", "4", request.stream)

def test_convert_render_control(self, client: GotenbergClient, httpx_mock: HTTPXMock):
def test_convert_render_control(self, client: GotenbergClient, sample_directory: Path, httpx_mock: HTTPXMock):
httpx_mock.add_response(method="POST")
test_file = SAMPLE_DIR / "basic.html"
test_file = sample_directory / "basic.html"

with client.chromium.html_to_pdf() as route:
_ = route.index(test_file).render_wait(500.0).run()
Expand All @@ -142,11 +141,12 @@ def test_convert_render_control(self, client: GotenbergClient, httpx_mock: HTTPX
def test_convert_orientation(
self,
client: GotenbergClient,
sample_directory: Path,
httpx_mock: HTTPXMock,
orientation: PageOrientation,
):
httpx_mock.add_response(method="POST")
test_file = SAMPLE_DIR / "basic.html"
test_file = sample_directory / "basic.html"

with client.chromium.html_to_pdf() as route:
_ = route.index(test_file).orient(orientation).run()
Expand Down
27 changes: 19 additions & 8 deletions tests/test_convert_chromium_markdown.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,32 @@
# SPDX-FileCopyrightText: 2023-present Trenton H <[email protected]>
#
# SPDX-License-Identifier: MPL-2.0
from pathlib import Path

from httpx import codes

from gotenberg_client import GotenbergClient
from tests.conftest import SAMPLE_DIR


class TestConvertChromiumUrlRoute:
def test_basic_convert(self, client: GotenbergClient):
index = SAMPLE_DIR / "markdown_index.html"
md_files = [SAMPLE_DIR / "markdown1.md", SAMPLE_DIR / "markdown2.md"]
img = SAMPLE_DIR / "img.gif"
font = SAMPLE_DIR / "font.woff"
style = SAMPLE_DIR / "style.css"
def test_basic_convert(
self,
client: GotenbergClient,
markdown_index_file: Path,
markdown_sample_one_file: Path,
markdown_sample_two_file: Path,
img_gif_file: Path,
font_file: Path,
css_style_file: Path,
):
with client.chromium.markdown_to_pdf() as route:
resp = route.index(index).markdown_files(md_files).resources([img, font]).resource(style).run_with_retry()
resp = (
route.index(markdown_index_file)
.markdown_files([markdown_sample_one_file, markdown_sample_two_file])
.resources([img_gif_file, font_file])
.resource(css_style_file)
.run_with_retry()
)

assert resp.status_code == codes.OK
assert "Content-Type" in resp.headers
Expand Down
Loading

0 comments on commit 7dfe72c

Please sign in to comment.