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 # never cuts mid-word: trimmed must be a prefix ending at a space boundary 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) # Should back up to "abcdefghij" (10 chars) rather than cut "klmnop" mid-word 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