from app.discovery.enums import MatchStatus from app.discovery.identity import IdentitySignals, decide_identity, spec_fingerprint def _sig(**overrides) -> IdentitySignals: base = IdentitySignals( source_external_id="gh-1", gtin_ean="4000000000001", manufacturer_sku="EM13-32", source_url="https://geizhals.de/a.html", title="Example Mobile 13", manufacturer="Example", model="Mobile 13", fingerprint=spec_fingerprint({"manufacturer": "Example", "model": "Mobile 13", "ram": 32}), ) return IdentitySignals(**{**base.__dict__, **overrides}) def test_sku_and_ean_and_url_match(): known = [("a", _sig())] assert decide_identity(_sig(), known).reason == "source_external_id" assert decide_identity(_sig(source_external_id="other"), known).reason == "gtin_ean" assert decide_identity(_sig(source_external_id="other", gtin_ean="x"), known).reason == "manufacturer_sku" assert decide_identity( _sig(source_external_id="other", gtin_ean="x", manufacturer_sku="y"), known, ).reason == "source_url" def test_title_plus_fingerprint_matches_stable_specs(): known = [("a", _sig(source_external_id=None, gtin_ean=None, manufacturer_sku=None, source_url=None))] incoming = _sig( source_external_id=None, gtin_ean=None, manufacturer_sku=None, source_url=None, title="Example Mobile 13", ) decision = decide_identity(incoming, known) assert decision.match_status == MatchStatus.MATCHED assert decision.reason == "title+fingerprint" def test_title_only_is_uncertain_and_never_merges(): known = [("a", _sig(source_external_id=None, gtin_ean=None, manufacturer_sku=None, source_url=None))] incoming = _sig( source_external_id=None, gtin_ean=None, manufacturer_sku=None, source_url=None, fingerprint="different", manufacturer="Other", model="Other", ) decision = decide_identity(incoming, known) assert decision.match_status == MatchStatus.MATCH_UNCERTAIN assert decision.existing_id is None assert decision.reason == "title only" def test_fingerprint_uses_observed_keys_only(): left = spec_fingerprint({"capacity_l": 2, "color": "black"}) right = spec_fingerprint({"capacity_l": 5, "color": "black"}) assert left != right assert "capacity_l=2" in left assert "ram_gb" not in left assert spec_fingerprint({"title": "ignored", "html": "", "noise": 1}) == "noise=1" def test_similar_names_do_not_merge(): known = [("a", _sig(source_external_id=None, gtin_ean=None, manufacturer_sku=None, source_url=None))] incoming = _sig( source_external_id=None, gtin_ean=None, manufacturer_sku=None, source_url=None, title="Example Mobile 14", fingerprint="other", manufacturer="Example", model="Mobile 14", ) decision = decide_identity(incoming, known) assert decision.match_status == MatchStatus.NEW_REFERENCE