Regula sklejki sasiednich czlonow (JoannaAngel, Bonnieb) nie byla pilnowana na granicy obsady: przy martwym separatorze "Dickft" i "Paigefeat" wychodzily jako trafienia. Trzy przypadki, ktore na starym regexie daly True, a teraz daja False. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
148 lines
5.9 KiB
Python
148 lines
5.9 KiB
Python
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!<br /> ", "Welcome, Carlo!"),
|
|
('<p>See <a href="/x">Bunny</a> & <b>more</b>!</p>', "See Bunny & more!"),
|
|
# To nie sa znaczniki.
|
|
("I miss you so much <3.", "I miss you so much <3."),
|
|
("It was <a lot of fun> and <b careful>", "It was <a lot of fun> and <b careful>"),
|
|
('<span style="color: red" class=x>Hot</span>', "Hot"),
|
|
("<Yokomiya-san. SSSP! No Cuts]", "<Yokomiya-san. SSSP! No Cuts]"),
|
|
("lips&tongues; Alix &Amp; Cherie", "lips&tongues; Alix & Cherie"),
|
|
(" ", None),
|
|
(None, None),
|
|
],
|
|
)
|
|
def test_clean_description(raw: str | None, expected: str | None) -> None:
|
|
assert clean_description(raw) == expected
|