Coverage for tests/conftest.py: 100%
49 statements
« prev ^ index » next coverage.py v7.10.3, created at 2026-08-22 19:08 +0000
« prev ^ index » next coverage.py v7.10.3, created at 2026-08-22 19:08 +0000
1import dataclasses
2import pathlib
3import typing
5import hypothesis
6import pytest
7from faker import Faker
9from meta_tags_parser import parse, structs
12FIXTURES_DIRECTORY: typing.Final = pathlib.Path(__file__).parent / "html_fixtures"
13DETERMINISTIC_SEED: typing.Final = 20260818
14HYPOTHESIS_PROFILE_NAME: typing.Final = "meta-tags-parser"
15POSSIBLE_OG_TAGS_VALUES: typing.Final[tuple[str, ...]] = (
16 "title",
17 "url",
18 "image",
19 "type",
20 "description",
21 "locale",
22 "site_name",
23 "video",
24)
25EXTRA_OTHER_TAG_NAMES: typing.Final[tuple[str, ...]] = ("article:name", "article:description")
26REPEATED_TAG_LIMIT: typing.Final = 5
29# parsing multi megabyte fixtures is slower than the hypothesis default deadline allows,
30# and a deadline makes property tests flaky on loaded CI runners
31hypothesis.settings.register_profile(HYPOTHESIS_PROFILE_NAME, deadline=None, print_blob=True)
32hypothesis.settings.load_profile(HYPOTHESIS_PROFILE_NAME)
35@typing.final
36@dataclasses.dataclass(kw_only=True, slots=True, frozen=True)
37class FakeMetaPage:
38 """Randomly generated page together with what the parser must find inside it."""
40 html_source: str
41 social_tag_values: typing.Mapping[str, str]
42 other_tag_names: tuple[str, ...]
45@pytest.fixture(name="faker_seed", autouse=True)
46def provide_faker_seed() -> int:
47 """Keep faker output reproducible, a failing test must be replayable."""
48 return DETERMINISTIC_SEED
51@pytest.fixture(autouse=True)
52def restore_global_settings() -> typing.Iterator[None]:
53 """Undo whatever set_settings_for_meta_tags did inside a test."""
54 yield
55 parse.set_settings_for_meta_tags(structs.DEFAULT_SETTINGS_FROM_USER)
58def _build_tag_content(faker: Faker, one_name: str) -> str:
59 if one_name in ("url", "video"):
60 return str(faker.url())
61 if one_name == "image":
62 return str(faker.image_url())
63 return str(faker.text())
66@pytest.fixture
67def provide_fake_meta_page(faker: Faker) -> FakeMetaPage:
68 """Generate a random page with known Open Graph, Twitter, basic and other tags."""
69 markup_buffer: typing.Final[list[str]] = [
70 f"""<meta name="{one_name}" content="{faker.text()}">""" for one_name in structs.BASIC_META_TAGS
71 ]
72 social_tag_values: typing.Final[dict[str, str]] = {}
73 for one_name in POSSIBLE_OG_TAGS_VALUES:
74 for _ in range(faker.random_int(min=1, max=REPEATED_TAG_LIMIT)):
75 tag_content: str = _build_tag_content(faker, one_name)
76 markup_buffer.append(f"""<meta property="og:{one_name}" content="{tag_content}">""")
77 markup_buffer.append(f"""<meta name="twitter:{one_name}" content="{tag_content}">""")
78 social_tag_values[one_name] = tag_content
79 markup_buffer.append(f"<title>{faker.text()}</title>")
80 markup_buffer.extend(f"""<meta name="{one_name}" content="{faker.text()}">""" for one_name in EXTRA_OTHER_TAG_NAMES)
81 markup_buffer.append("""<meta name="bad-tag">""")
82 markup_buffer.append("""<meta property="another-bad-tag">""")
83 return FakeMetaPage(
84 html_source=("\n \t" * faker.random_int(min=1, max=REPEATED_TAG_LIMIT)).join(markup_buffer),
85 social_tag_values=social_tag_values,
86 other_tag_names=EXTRA_OTHER_TAG_NAMES,
87 )
90@pytest.fixture
91def provide_html_file_paths() -> list[pathlib.Path]:
92 """Return the real captured pages shipped with the repository."""
93 return sorted(FIXTURES_DIRECTORY.glob("*.html"))