diff options
Diffstat (limited to 'tests/tasks/test_scanner.py')
| -rw-r--r-- | tests/tasks/test_scanner.py | 97 |
1 files changed, 23 insertions, 74 deletions
diff --git a/tests/tasks/test_scanner.py b/tests/tasks/test_scanner.py index 332b8bf..3de5e16 100644 --- a/tests/tasks/test_scanner.py +++ b/tests/tasks/test_scanner.py @@ -4,6 +4,7 @@ from pathlib import Path from types import ModuleType +from unittest.mock import Mock from uuid import UUID import pytest @@ -20,13 +21,11 @@ SOURCE_URL = f"{BASE_URL}example/" @pytest.fixture -def scanner_module(app: Flask) -> ModuleType: - # Importing scanner registers Huey tasks. The dependency on the - # app fixture guarantees that Huey has been initialized first. +def scanner_module(app: Flask, monkeypatch: pytest.MonkeyPatch) -> ModuleType: _ = app - from webmentions_ssg.tasks import scanner + monkeypatch.setattr(scanner, "is_http_url", Mock(return_value=True)) return scanner @@ -96,11 +95,6 @@ def configure_scanner(app: Flask, root: Path, *, base_url: str | None = None) -> app.config["WEBMENTIONS_SSG_SOURCE_BASE_URL"] = base_url -# --------------------------------------------------------------------------- -# Microformats parsing -# --------------------------------------------------------------------------- - - def test_parse_entry_returns_microformats_entry(scanner_module: ModuleType) -> None: document = parse_html( f""" @@ -277,11 +271,6 @@ def test_primary_entry_rejects_nonmatching_u_url(scanner_module: ModuleType) -> scanner_module.primary_entry(document, SOURCE_URL) -# --------------------------------------------------------------------------- -# e-content -# --------------------------------------------------------------------------- - - def test_content_element_returns_e_content(scanner_module: ModuleType) -> None: document = parse_html( """ @@ -346,11 +335,6 @@ def test_content_element_rejects_multiple_e_content(scanner_module: ModuleType) scanner_module.content_element(entry) -# --------------------------------------------------------------------------- -# Canonical URLs -# --------------------------------------------------------------------------- - - def test_canonical_url_returns_absolute_url(scanner_module: ModuleType) -> None: document = parse_html( f""" @@ -393,6 +377,8 @@ def test_canonical_url_returns_none_when_missing(scanner_module: ModuleType) -> def test_canonical_url_resolves_relative_url_with_base_url( scanner_module: ModuleType, ) -> None: + scanner_module.is_http_url.side_effect = [False, True] + document = parse_html( """ <html> @@ -414,6 +400,8 @@ def test_canonical_url_resolves_relative_url_with_base_url( def test_relative_canonical_requires_base_url(scanner_module: ModuleType) -> None: + scanner_module.is_http_url.return_value = False + document = parse_html( """ <html> @@ -453,11 +441,6 @@ def test_empty_canonical_is_rejected(scanner_module: ModuleType) -> None: ) -# --------------------------------------------------------------------------- -# Target extraction -# --------------------------------------------------------------------------- - - def test_scan_source_uses_canonical_without_base_url( scanner_module: ModuleType, tmp_path: Path ) -> None: @@ -657,24 +640,6 @@ def test_scan_source_extracts_reaction_properties( assert scanned.targets == frozenset({target}) -def test_scan_source_extracts_anchor_from_e_content( - scanner_module: ModuleType, tmp_path: Path -) -> None: - path = write_post( - tmp_path, - "example", - """ - <a href="https://example.com/target"> - Target - </a> - """, - ) - - scanned = scanner_module.scan_source_file(path, root=tmp_path, base_url=None) - - assert scanned.targets == frozenset({"https://example.com/target"}) - - @pytest.mark.parametrize("tag", ("link", "area")) def test_scan_source_ignores_non_anchor_href_elements( scanner_module: ModuleType, tmp_path: Path, tag: str @@ -714,11 +679,6 @@ def test_scan_source_ignores_self_fragment( assert scanned.targets == frozenset({"https://example.com/target"}) -# --------------------------------------------------------------------------- -# Database reconciliation -# --------------------------------------------------------------------------- - - def test_scan_creates_source_and_webmentions( app: Flask, scanner_module: ModuleType, tmp_path: Path, monkeypatch: MonkeyPatch ) -> None: @@ -900,7 +860,6 @@ def test_updated_source_increments_revision( assert webmention.desired_revision == 2 assert webmention.processed_revision == 1 assert webmention.sent_revision == 1 - assert webmention.pending identifier = webmention.uuid @@ -972,7 +931,6 @@ def test_new_target_is_added_on_update( assert webmention.desired_revision == 2 assert webmention.processed_revision is None assert webmention.sent_revision is None - assert webmention.pending identifier = webmention.uuid @@ -1055,7 +1013,6 @@ def test_removed_sent_target_is_queued_again( assert webmention.desired_revision == 2 assert webmention.processed_revision == 1 assert webmention.sent_revision == 1 - assert webmention.pending assert queued == [identifier] @@ -1124,16 +1081,10 @@ def test_removed_unsent_target_is_not_queued( assert webmention.desired_revision == 2 assert webmention.processed_revision == 2 assert webmention.sent_revision is None - assert not webmention.pending assert queued == [] -# --------------------------------------------------------------------------- -# Source deletion/restoration -# --------------------------------------------------------------------------- - - def test_deleted_source_queues_previously_sent_webmention( app: Flask, scanner_module: ModuleType, tmp_path: Path, monkeypatch: MonkeyPatch ) -> None: @@ -1186,7 +1137,6 @@ def test_deleted_source_queues_previously_sent_webmention( assert webmention.desired_revision == 2 assert webmention.processed_revision == 1 assert webmention.sent_revision == 1 - assert webmention.pending assert queued == [identifier] @@ -1231,7 +1181,6 @@ def test_deleted_source_does_not_queue_unsent_webmention( assert webmention.desired_revision == 2 assert webmention.processed_revision == 2 assert webmention.sent_revision is None - assert not webmention.pending assert queued == [] @@ -1298,18 +1247,12 @@ def test_restored_source_creates_new_revision( assert webmention.active assert webmention.desired_revision == 3 assert webmention.sent_revision == 1 - assert webmention.pending identifier = webmention.uuid assert queued == [identifier] -# --------------------------------------------------------------------------- -# Queue recovery and invalid sources -# --------------------------------------------------------------------------- - - def test_pending_webmention_is_requeued_on_next_scan( app: Flask, scanner_module: ModuleType, tmp_path: Path, monkeypatch: MonkeyPatch ) -> None: @@ -1436,6 +1379,8 @@ def test_scan_sources_accepts_valid_base_url( def test_scan_sources_rejects_invalid_base_url( app: Flask, scanner_module: ModuleType, tmp_path: Path ) -> None: + scanner_module.is_http_url.return_value = False + configure_scanner(app, tmp_path, base_url="not-a-url") with pytest.raises(RuntimeError, match="absolute HTTP or HTTPS URL"): @@ -1565,6 +1510,8 @@ def test_scan_source_ignores_reaction_to_matching_hostname( def test_canonical_url_rejects_non_http_resolved_url( scanner_module: ModuleType, ) -> None: + scanner_module.is_http_url.return_value = False + document = parse_html( """ <html> @@ -1634,19 +1581,21 @@ def test_parse_entry_rejects_invalid_parser_output( scanner_module.parse_entry(element, SOURCE_URL) -@pytest.mark.parametrize( - "value", - [ - pytest.param(" ", id="empty"), - pytest.param("mailto:example@example.com", id="non-http"), - ], -) -def test_normalize_target_ignores_invalid_target( - scanner_module: ModuleType, value: str +def test_normalize_target_ignores_empty_target(scanner_module: ModuleType) -> None: + assert ( + scanner_module.normalize_target(" ", base_url=SOURCE_URL, source_url=SOURCE_URL) + is None + ) + + +def test_normalize_target_ignores_url_rejected_by_validator( + scanner_module: ModuleType, ) -> None: + scanner_module.is_http_url.return_value = False + assert ( scanner_module.normalize_target( - value, base_url=SOURCE_URL, source_url=SOURCE_URL + "https://example.com/target", base_url=SOURCE_URL, source_url=SOURCE_URL ) is None ) |
