146 lines
5.1 KiB
Python
146 lines
5.1 KiB
Python
"""Tests for jobsource/resolve.py — all network-free via monkeypatched _verify."""
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from jobsource.config import get_settings
|
|
from jobsource.resolve import (
|
|
_search_api_lookup,
|
|
_slug,
|
|
_verify,
|
|
resolve_website,
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# _slug
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestSlug:
|
|
def test_basic(self):
|
|
assert _slug("GitHub") == "github"
|
|
|
|
def test_strips_legal_suffix_inc(self):
|
|
assert _slug("Acme Inc") == "acme"
|
|
|
|
def test_strips_legal_suffix_llc(self):
|
|
assert _slug("Widgets LLC") == "widgets"
|
|
|
|
def test_strips_legal_suffix_corp(self):
|
|
assert _slug("MegaCorp Corp") == "megacorp"
|
|
|
|
def test_strips_multiple_words(self):
|
|
assert _slug("Some Company Ltd") == "somecompany"
|
|
|
|
def test_removes_spaces_and_punctuation(self):
|
|
assert _slug("Foo & Bar") == "foobar"
|
|
|
|
def test_empty_after_strip_returns_none(self):
|
|
assert _slug("LLC") is None
|
|
|
|
def test_empty_string_returns_none(self):
|
|
assert _slug("") is None
|
|
|
|
def test_gmbh(self):
|
|
assert _slug("Acme GmbH") == "acme"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# resolve_website — tier 1: provider-supplied
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestResolveWebsiteTier1:
|
|
def test_returns_provider_website_unchanged_if_has_scheme(self, monkeypatch):
|
|
called = []
|
|
monkeypatch.setattr("jobsource.resolve._verify", lambda c, u: called.append(u) or None)
|
|
result = resolve_website("Acme", "https://acme.com")
|
|
assert result == "https://acme.com"
|
|
assert called == [] # no network call
|
|
|
|
def test_adds_https_if_no_scheme(self, monkeypatch):
|
|
monkeypatch.setattr("jobsource.resolve._verify", lambda c, u: None)
|
|
result = resolve_website("Acme", "acme.com")
|
|
assert result == "https://acme.com"
|
|
|
|
def test_placeholder_website_skips_to_next_tier(self, monkeypatch):
|
|
verify_calls = []
|
|
monkeypatch.setattr("jobsource.resolve._verify", lambda c, u: verify_calls.append(u) or None)
|
|
result = resolve_website("Acme", "PLACEHOLDER_URL")
|
|
assert result is None
|
|
assert len(verify_calls) >= 1 # fell through to tier 2
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# resolve_website — tier 2: slug guess
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestResolveWebsiteTier2:
|
|
def test_verified_slug_returned(self, monkeypatch):
|
|
monkeypatch.setattr(
|
|
"jobsource.resolve._verify",
|
|
lambda c, u: "https://github.com/" if "github" in u else None,
|
|
)
|
|
result = resolve_website("GitHub")
|
|
assert result == "https://github.com/"
|
|
|
|
def test_miss_returns_none_when_search_disabled(self, monkeypatch):
|
|
monkeypatch.setattr("jobsource.resolve._verify", lambda c, u: None)
|
|
result = resolve_website("Acme Corp")
|
|
assert result is None
|
|
|
|
def test_unslugable_name_skips_tier2(self, monkeypatch):
|
|
verify_calls = []
|
|
monkeypatch.setattr("jobsource.resolve._verify", lambda c, u: verify_calls.append(u) or None)
|
|
result = resolve_website("LLC") # slug → None
|
|
assert result is None
|
|
assert verify_calls == []
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# resolve_website — tier 3: search API (gated stub)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestResolveWebsiteTier3:
|
|
def test_search_api_stub_returns_none(self, monkeypatch):
|
|
monkeypatch.setattr("jobsource.resolve._verify", lambda c, u: None)
|
|
get_settings.cache_clear()
|
|
monkeypatch.setenv("SEARCH_API_ENABLED", "true")
|
|
monkeypatch.setenv("SEARCH_API_KEY", "real-key-abc")
|
|
get_settings.cache_clear()
|
|
|
|
lookup_called = []
|
|
|
|
def fake_lookup(name, client):
|
|
lookup_called.append(name)
|
|
return None # stub
|
|
|
|
monkeypatch.setattr("jobsource.resolve._search_api_lookup", fake_lookup)
|
|
result = resolve_website("Some Obscure Co")
|
|
assert result is None
|
|
assert lookup_called == ["Some Obscure Co"]
|
|
get_settings.cache_clear()
|
|
|
|
def test_search_api_disabled_by_default(self, monkeypatch):
|
|
monkeypatch.setattr("jobsource.resolve._verify", lambda c, u: None)
|
|
lookup_called = []
|
|
monkeypatch.setattr(
|
|
"jobsource.resolve._search_api_lookup",
|
|
lambda name, client: lookup_called.append(name) or None,
|
|
)
|
|
resolve_website("Acme")
|
|
assert lookup_called == []
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# _search_api_lookup stub contract
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestSearchApiLookupStub:
|
|
def test_returns_none(self):
|
|
assert _search_api_lookup("Acme", None) is None # type: ignore[arg-type]
|