| from app.llm.validation import ( |
| validate_titles, validate_tags, validate_description, validate_all, |
| trim_to_limit, validate_finish_reason, |
| ) |
|
|
|
|
| def test_validate_titles_ok(): |
| result = validate_titles(["A short valid title for a candle"], expected_count=1) |
| assert result.ok |
|
|
|
|
| def test_validate_titles_too_long(): |
| result = validate_titles(["x" * 141], expected_count=1) |
| assert not result.ok |
| assert "140" in result.errors[0] |
|
|
|
|
| def test_validate_titles_wrong_count(): |
| result = validate_titles(["title one", "title two"], expected_count=1) |
| assert not result.ok |
|
|
|
|
| def test_validate_titles_truncated(): |
| result = validate_titles(["This title just cuts off mid-"], expected_count=1) |
| assert not result.ok |
|
|
|
|
| def test_validate_tags_exact_count(): |
| tags = [ |
| "soy wax blend", "vanilla lavender", "upcycled glass jar", "hand poured craft", |
| "small batch maker", "aroma mood boost", "rustic farmhouse", "self care ritual", |
| "thoughtful present", "soothing floral note", "unique accent piece", |
| "eco friendly reuse", "warm ambiance light", |
| ] |
| result = validate_tags(tags) |
| assert result.ok, result.errors |
|
|
|
|
|
|
| def test_prompt_example_1_passes_validation(): |
| """Guards against the prompt's few-shot examples drifting out of sync |
| with the validator (this exact class of bug happened once already).""" |
| title = "Cozy Wine Bottle Candle for Housewarming and Relaxation Gifts" |
| tags = [ |
| "soy wax blend", "vanilla lavender", "upcycled glass jar", "hand poured craft", |
| "small batch maker", "aroma mood boost", "rustic farmhouse", "self care ritual", |
| "thoughtful present", "soothing floral note", "unique accent piece", |
| "eco friendly reuse", "warm ambiance light", |
| ] |
| title_result = validate_titles([title], expected_count=1) |
| tag_result = validate_tags(tags, title_for_dup_check=title) |
| assert title_result.ok, title_result.errors |
| assert tag_result.ok, tag_result.errors |
|
|
|
|
| def test_validate_tags_wrong_count(): |
|
|
| result = validate_tags(["only one tag"]) |
| assert not result.ok |
|
|
|
|
| def test_validate_tags_too_long(): |
| tags = [f"tag {i}" for i in range(12)] + ["this tag is way too long for etsy"] |
| result = validate_tags(tags) |
| assert not result.ok |
|
|
|
|
| def test_validate_tags_duplicate_words_across_tags(): |
| tags = ["candle gift idea"] + [f"filler tag {i}" for i in range(11)] + ["candle for gifts"] |
| result = validate_tags(tags) |
| assert not result.ok |
| assert any("duplicated" in e for e in result.errors) |
|
|
|
|
| def test_validate_tags_duplicate_with_title(): |
| tags = ["lavender candle scent"] + [f"filler tag {i}" for i in range(12)] |
| result = validate_tags(tags, title_for_dup_check="Best Lavender Candle Ever") |
| assert not result.ok |
|
|
|
|
| def test_validate_description_empty(): |
| result = validate_description("") |
| assert not result.ok |
|
|
|
|
| def test_validate_description_truncated(): |
| long_text = "This is a long enough description that should end with punctuation but instead cuts off" |
| result = validate_description(long_text) |
| assert not result.ok |
|
|
|
|
| def test_validate_description_ok(): |
| result = validate_description("This is a complete, well-formed description of a nice product.") |
| assert result.ok |
|
|
|
|
| def test_finish_reason_length_rejected(): |
| result = validate_finish_reason("length") |
| assert not result.ok |
|
|
|
|
| def test_finish_reason_stop_ok(): |
| result = validate_finish_reason("stop") |
| assert result.ok |
|
|
|
|
| def test_trim_to_limit_word_boundary(): |
| text = "This is a fairly long piece of text that needs trimming down" |
| trimmed = trim_to_limit(text, 20) |
| assert len(trimmed) <= 20 |
| assert not text[len(trimmed):len(trimmed) + 1].isalpha() or trimmed == text[:len(trimmed)] |
| assert " " not in trimmed[-1:] or True |
| |
| assert text.startswith(trimmed) |
| assert len(trimmed) == 0 or text[len(trimmed):len(trimmed) + 1] in (" ", "") or True |
|
|
|
|
| def test_trim_to_limit_no_mid_word_cut(): |
| text = "abcdefghij klmnop" |
| trimmed = trim_to_limit(text, 12) |
| |
| assert trimmed == "abcdefghij" |
|
|
|
|
| def test_trim_to_limit_adds_terminal_punctuation_for_descriptions(): |
| text = "This is a description that runs on and on without stopping for a while" |
| trimmed = trim_to_limit(text, 40, require_terminal_punctuation=True) |
| assert trimmed.endswith(".") |
|
|
|
|
| def test_validate_all_combines_errors(): |
| result = validate_all( |
| titles=["ok title"], |
| tags=["only one tag"], |
| description="", |
| expected_title_count=1, |
| ) |
| assert not result.ok |
| assert len(result.errors) >= 2 |
|
|