package tests import "core:fmt" import "core:strings" import "core:testing" import "../src/adapters" import "../src/core" import "../src/gui" import "../src/shared" import "../src/ui" // ───────────────────────────────────────────────────────────── // Phase 2: Character Consistency + Emotion Enum + Character Sheets // ───────────────────────────────────────────────────────────── @test core_emotion_enum_roundtrip :: proc(t: ^testing.T) { emotions := []core.Emotion{.Happy, .Sad, .Angry, .Surprised, .Neutral, .Determined} names := []string{"happy", "sad", "angry", "surprised", "neutral", "determined"} for name, i in names { e := core.parse_emotion(name) testing.expect(t, e == emotions[i], fmt.tprintf("parse_emotion(%q) should map to correct enum", name)) testing.expect(t, core.emotion_name(emotions[i]) == name, fmt.tprintf("emotion_name should return %q", name)) } } @test core_emotion_parse_fuzzy :: proc(t: ^testing.T) { testing.expect(t, core.parse_emotion("joyful") == .Happy, "joyful should map to Happy") testing.expect(t, core.parse_emotion("crying") == .Sad, "crying should map to Sad") testing.expect(t, core.parse_emotion("furious") == .Angry, "furious should map to Angry") testing.expect(t, core.parse_emotion("shocked") == .Surprised, "shocked should map to Surprised") testing.expect(t, core.parse_emotion("determined") == .Determined, "determined should map to Determined") testing.expect(t, core.parse_emotion("unknown") == .Neutral, "unknown should default to Neutral") } @test core_art_style_keyword_mapping :: proc(t: ^testing.T) { styles := []string{"manga", "western-comic", "pixel-art", "watercolor", "noir", "chibi", "sketch", "cyberpunk"} for s in styles { key := core.parse_art_style_key(s) keywords := core.get_style_keywords(key) testing.expect(t, len(keywords) > 0, fmt.tprintf("style %q should have keywords", s)) } } @test core_shot_type_to_image_size :: proc(t: ^testing.T) { testing.expect(t, core.get_image_size_for_shot_type(.Establishing) == .Landscape_16_9, "establishing should be 16:9") testing.expect(t, core.get_image_size_for_shot_type(.Wide) == .Landscape_16_9, "wide should be 16:9") testing.expect(t, core.get_image_size_for_shot_type(.Medium) == .Landscape_4_3, "medium should be 4:3") testing.expect(t, core.get_image_size_for_shot_type(.Close_Up) == .Portrait_4_3, "close-up should be portrait 4:3") testing.expect(t, core.get_image_size_for_shot_type(.Extreme_Close_Up) == .Square_HD, "extreme-close-up should be square_hd") testing.expect(t, core.get_image_size_for_shot_type(.Aerial) == .Landscape_16_9, "aerial should be 16:9") } @test core_sdxl_dimensions :: proc(t: ^testing.T) { w, h := adapters.dimensions_from_sdxl_size("landscape_16_9") testing.expect(t, w == 1344 && h == 768, fmt.tprintf("16:9 should be 1344x768, got %dx%d", w, h)) w2, h2 := adapters.dimensions_from_sdxl_size("square_hd") testing.expect(t, w2 == 1024 && h2 == 1024, fmt.tprintf("square_hd should be 1024x1024, got %dx%d", w2, h2)) } @test core_character_sheet_poses_defined :: proc(t: ^testing.T) { testing.expect(t, len(adapters.CHARACTER_SHEET_POSES) == 4, "should have 4 sheet poses") testing.expect(t, adapters.CHARACTER_SHEET_POSES[0].name == "front", "first pose should be front") testing.expect(t, adapters.CHARACTER_SHEET_POSES[3].name == "back", "last pose should be back") } @test gui_action_generate_character_reference_missing_key :: proc(t: ^testing.T) { state := core.new_initial_state() defer core.dispose_state(&state) controller := ui.new_controller(state) defer ui.dispose_job_manager(&controller.jobs) // Add a character char := core.Character{id = "char_1", name = "Hero", role = .Protagonist, description = "Main character"} chars: [dynamic]core.Character append(&chars, char) controller.state.characters = chars[:] msg := gui.action_generate_character_reference(&controller, "char_1") testing.expect(t, strings.has_prefix(msg, "FAL_API_KEY"), "should report missing FAL key") } @test gui_action_generate_character_sheet_missing_key :: proc(t: ^testing.T) { state := core.new_initial_state() defer core.dispose_state(&state) controller := ui.new_controller(state) defer ui.dispose_job_manager(&controller.jobs) char := core.Character{id = "char_1", name = "Hero", role = .Protagonist, description = "Main character"} chars: [dynamic]core.Character append(&chars, char) controller.state.characters = chars[:] msg := gui.action_generate_character_sheet(&controller, "char_1") testing.expect(t, strings.has_prefix(msg, "FAL_API_KEY"), "should report missing FAL key") } @test gui_action_generate_character_reference_not_found :: proc(t: ^testing.T) { state := core.new_initial_state() defer core.dispose_state(&state) controller := ui.new_controller(state) defer ui.dispose_job_manager(&controller.jobs) msg := gui.action_generate_character_reference(&controller, "nonexistent") testing.expect(t, strings.has_prefix(msg, "FAL_API_KEY") || msg == "Character not found", "should report missing key or not found") } @test gui_action_generate_character_sheet_not_found :: proc(t: ^testing.T) { state := core.new_initial_state() defer core.dispose_state(&state) controller := ui.new_controller(state) defer ui.dispose_job_manager(&controller.jobs) msg := gui.action_generate_character_sheet(&controller, "nonexistent") testing.expect(t, strings.has_prefix(msg, "FAL_API_KEY") || msg == "Character not found", "should report missing key or not found") } @test fal_negative_prompts_defined :: proc(t: ^testing.T) { testing.expect(t, len(core.NEGATIVE_PROMPT_CHARACTER) > 0, "character negative prompt should be defined") testing.expect(t, len(core.NEGATIVE_PROMPT_PANEL) > 0, "panel negative prompt should be defined") testing.expect(t, strings.contains(core.NEGATIVE_PROMPT_PANEL, "text"), "panel negative should include text") testing.expect(t, strings.contains(core.NEGATIVE_PROMPT_PANEL, "speech bubble"), "panel negative should include speech bubble") } @test fal_quality_modifier_defined :: proc(t: ^testing.T) { testing.expect(t, len(core.QUALITY_MODIFIER) > 0, "quality modifier should be defined") testing.expect(t, strings.contains(core.QUALITY_MODIFIER, "high quality"), "should include quality terms") }