from __future__ import annotations import os from pathlib import Path from sqlmodel import Session from backend.core import Backend from backend.scrape_artifacts import ( audit_scraped_notes, classify_scraped_note_line, clean_scraped_catalog_text, clean_scraped_notes, ) from models import Kink, KinkExample def test_classifies_full_db_profile_and_counter_leftovers() -> None: assert classify_scraped_note_line("fetlife_2579", "Female Ejaculation", "into: watching") == "profile_bucket_line" assert classify_scraped_note_line("fetlife_2579", "Female Ejaculation", "curious_about") == "profile_bucket_line" assert classify_scraped_note_line("fetlife_2579", "Female Ejaculation", "Kinksters: 667609") == "fetlife_metric_line" assert ( classify_scraped_note_line( "fetlife_2579", "Female Ejaculation", "Female Ejaculation 667,679 Kinksters into and curious", ) == "fetlife_title_popularity_line" ) assert classify_scraped_note_line("fetlife_123", "Plain Title", "Plain Title") == "title_echo_line" assert classify_scraped_note_line("fetlife_kinktionary_x", "Sober Kink", "Characteristics of Sober Kink") == "kinktionary_toc_note" def test_clean_scraped_notes_removes_only_known_artifacts() -> None: notes = "\n".join( [ "Kinksters: 667609", "into: watching", "Female Ejaculation 667,679 Kinksters into and curious", "plain future editorial note", ], ) assert clean_scraped_notes("fetlife_2579", "Female Ejaculation", notes) == "plain future editorial note" assert clean_scraped_notes("fetlife_kinktionary_x", "Sober Kink", "Characteristics of Sober Kink") == "" assert clean_scraped_catalog_text("Female Ejaculation", "Female Ejaculation") == "" assert clean_scraped_catalog_text("Female Ejaculation", "plain future example") == "plain future example" def test_audit_scraped_notes_catalogs_categories_and_remaining_rows() -> None: payload = audit_scraped_notes( [ ("fetlife_2579", "Female Ejaculation", "into: watching\nKinksters: 667609"), ("fetlife_123", "Plain Title", "Plain Title"), ("local", "Local", "plain future editorial note"), ], ) assert payload["nonempty_rows"] == 3 assert payload["artifact_rows"] == 2 assert payload["remaining_rows_after_filter"] == 1 assert payload["line_counts"]["profile_bucket_line"] == 1 assert payload["line_counts"]["fetlife_metric_line"] == 1 assert payload["line_counts"]["title_echo_line"] == 1 def test_catalog_filters_display_notes_but_preserves_popularity(tmp_path: Path) -> None: """Use a kink id NOT in CURATED_DEFINITIONS so we can assert the empty-body behavior.""" os.environ["KINK_SKIP_HEAVY_WARM"] = "1" backend = Backend(tmp_path / "scrape_artifacts.db") raw_notes = "\n".join( [ "Kinksters: 667609", "into: watching", "Made-Up Kink 667,679 Kinksters into and curious", ], ) with Session(backend.engine) as session: session.add( Kink( id="fetlife_test_made_up_kink", name="Made-Up Kink", cluster="fetlife_fetish", short_definition="", notes=raw_notes, ), ) session.commit() backend._invalidate_catalog_cache(force=True) detail = backend.get_kink("fetlife_test_made_up_kink") assert detail is not None assert detail["notes"] == "" assert detail["summary"] == "" assert detail["detail_summary"] == "" assert detail["popularity"] == 667609 def test_catalog_filters_scraped_examples(tmp_path: Path) -> None: os.environ["KINK_SKIP_HEAVY_WARM"] = "1" backend = Backend(tmp_path / "scrape_examples.db") with Session(backend.engine) as session: session.add( Kink( id="fetlife_905", name="Cornertime", cluster="fetlife_fetish", short_definition="", notes="", ), ) session.add(KinkExample(id="artifact_metric", kink_id="fetlife_905", kind="example", text="Statuses: 253")) session.add(KinkExample(id="artifact_title", kink_id="fetlife_905", kind="example", text="Cornertime")) session.add(KinkExample(id="real", kink_id="fetlife_905", kind="example", text="plain future example")) session.commit() backend._invalidate_catalog_cache(force=True) detail = backend.get_kink("fetlife_905") assert detail is not None assert detail["examples"] == ["plain future example"] assert detail["summary"] == "plain future example"