import pytest from app.normalize.text import ( clean_description, normalize, normalize_person, person_named_in, slugify, strip_accents, unescape_html, ) @pytest.mark.parametrize( ("raw", "expected"), [ ("Café Noir", "cafe noir"), ("naïve", "naive"), ("Łódź", "lodz"), ], ) def test_strip_accents_and_lower(raw: str, expected: str) -> None: assert normalize(raw) == expected def test_normalize_drops_leading_articles() -> None: assert normalize("The Big Lebowski") == "big lebowski" assert normalize("A Quick One") == "quick one" assert normalize("An Honest Take") == "honest take" def test_normalize_collapses_whitespace_and_punct() -> None: assert normalize("Hello, world!!!") == "hello world" assert normalize("foo--bar__baz") == "foo bar baz" def test_normalize_handles_none_and_empty() -> None: assert normalize(None) == "" assert normalize("") == "" assert normalize(" ") == "" def test_normalize_person_keeps_initials() -> None: # „Mia M." → „mia m" (kropka usunięta jako interpunkcja) assert normalize_person("Mia M.") == "mia m" assert normalize_person("Mia Malkova") == "mia malkova" def test_slugify_is_url_safe() -> None: assert slugify("Brazzers Network") == "brazzers-network" assert slugify("Mia Malkova") == "mia-malkova" assert slugify("") == "" def test_strip_accents_idempotent() -> None: once = strip_accents("naïve") twice = strip_accents(once) assert once == twice == "naive" @pytest.mark.parametrize( ("title", "person", "expected"), [ ("Savannah Bond Takes It All", "Savanna Bond", True), ("Jynx Maze Anal", "Jyn Maze", True), ("Julia Ann and Bridgette B", "Julia B.", False), ("Kim Gold Solo", "Goldy Kim", False), # Jednowyrazowe nazwisko: tylko co do znaku. „Thebdck" lapal kazde „the". ("Twins Sasha Paige Share the Dick ft. Martin Spell", "Thebdck", False), ("Twins Sasha Paige Share the Dick ft. Martin Spell", "Sashamalone", False), ("Twins Sasha Paige Share the Dick ft. Martin Spell", "Dickxy", False), ("Twins Sasha Paige Share the Dick ft. Martin Spell", "Sasha Paige", True), ("Mandingo Destroys Her", "Mandingo", True), # Zlepek sxyprn rowny sklejce sasiednich czlonow tytulu. ("Joanna Angel Rides Again", "JoannaAngel", True), ("Bonnie B Solo", "Bonnieb", True), ("Joanna Smith and Angel Dark", "JoannaAngel", False), ("Mandingos Best", "Mandingo", False), # Przedrostek z limitem dlugosci: wariant zapisu tak, doklejone slowo nie. ("Alexis Crystal Returns", "Alexis Crystalline", False), ("Sasha Grey Returns", "Sash Grey", True), # feat/ft/featuring rozdziela osoby, nazwisko nie moze przez nie przejsc. ("Anna Bell ft. Bella Rose", "Bell Ft", False), ("Anna Bell feat Bella Rose", "Feat", False), ("Anna Bell FEAT. Bella Rose", "Bella Rose", True), ("Lily Lou featuring Bella Rose", "Lily Lou", True), ("Sasha Paige ft.Martin Spell", "Martin Spell", True), # ft wewnatrz slowa to nie separator. ("Craft Beer Night", "Craft Beer", True), # Zlepek tez nie przechodzi przez separator: „dick" i „ft" to sasiednie czlony # tylko dopoki tytul nie jest ciety, a byly sklejane w jedno nazwisko. ("Twins Sasha Paige Share the Dick ft. Martin Spell", "Dickft", False), ("Sasha Paige feat Martin Spell", "Paigefeat", False), ("Sasha Paige ft. Martin Spell", "Paige Ft Martin", False), ], ) def test_person_named_in(title: str, person: str, expected: bool) -> None: assert person_named_in(title, person) is expected @pytest.mark.parametrize( ("raw", "expected"), [ # xvideos JSON-LD, encje HTML5. ( "Are you sure we're allowed to do this mister Steve?? [AI]", "Are you sure we're allowed to do this mister Steve?? [AI]", ), ("The BEST (( HOT WIFE ))", "The BEST (( HOT WIFE ))"), # Podwojne kodowanie. ("Barbara &amp; Jake &lpar;4K&rpar;", "Barbara & Jake (4K)"), ("'x' "q"", "'x' \"q\""), # .title() na zakodowanym tytule. ("Alix &Amp; Cherie", "Alix & Cherie"), (" Hot Wife", "Hot Wife"), # Bez srednika albo nieznana nazwa: zostaje jak bylo. ("Me¬ice Tom & Jerry ©right; Q&A", "Me¬ice Tom & Jerry ©right; Q&A"), ("", ""), (None, ""), ], ) def test_unescape_html(raw: str | None, expected: str) -> None: assert unescape_html(raw) == expected @pytest.mark.parametrize( ("raw", "expected"), [ ('Manny in "MANUEL CREAMPIES 2". She loved it.', 'Manny in "MANUEL CREAMPIES 2". She loved it.'), # Znaczniki zakodowane jako encje. ("Is it love?<br>Eveline only ordered", "Is it love?\nEveline only ordered"), ("door.</br></br>Jessica", "door.\n\nJessica"), ("wash.<br><br><br><br>She", "wash.\n\nShe"), # Surowe znaczniki. ("Welcome, Carlo!
 ", "Welcome, Carlo!"), ('

See Bunny & more!

', "See Bunny & more!"), # To nie sa znaczniki. ("I miss you so much <3.", "I miss you so much <3."), ("It was and ", "It was and "), ('Hot', "Hot"), ("<Yokomiya-san. SSSP! No Cuts]", " None: assert clean_description(raw) == expected