Files
erosDiffusion-ComfyUI-Erosd…/tests/test_script_parser.py
T

277 lines
8.1 KiB
Python

"""
Unit tests for script_parser.
"""
import sys
import os
# Add parent directory to path for imports
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from script_parser import (
parse_timestamp,
format_timestamp,
parse_guide_spec,
parse_audio_spec,
parse_scene_script,
ImageGuide,
SceneChunk,
)
def test_parse_timestamp_mmss():
"""Test parsing MM:SS format."""
assert parse_timestamp("00:00") == 0.0
assert parse_timestamp("00:30") == 30.0
assert parse_timestamp("01:00") == 60.0
assert parse_timestamp("01:30") == 90.0
assert parse_timestamp("02:15") == 135.0
def test_parse_timestamp_with_ms():
"""Test parsing MM:SS.ms format."""
assert parse_timestamp("00:00.5") == 0.5
assert parse_timestamp("00:01.25") == 1.25
assert parse_timestamp("01:30.5") == 90.5
def test_parse_timestamp_seconds_only():
"""Test parsing seconds-only format."""
assert parse_timestamp("30") == 30.0
assert parse_timestamp("90") == 90.0
assert parse_timestamp("15.5") == 15.5
def test_format_timestamp():
"""Test formatting seconds to MM:SS."""
assert format_timestamp(0.0) == "00:00"
assert format_timestamp(30.0) == "00:30"
assert format_timestamp(60.0) == "01:00"
assert format_timestamp(90.0) == "01:30"
assert format_timestamp(135.0) == "02:15"
def test_parse_guide_spec_first():
"""Test parsing 'first:' guide spec."""
guide = parse_guide_spec("first:$0", 0.0, 2.0)
assert guide is not None
assert guide.position == "first"
assert guide.image_ref == "$0"
assert guide.strength == 1.0
def test_parse_guide_spec_end():
"""Test parsing 'end:' guide spec."""
guide = parse_guide_spec("end:$1", 0.0, 2.0)
assert guide is not None
assert guide.position == "end"
assert guide.image_ref == "$1"
def test_parse_guide_spec_middle():
"""Test parsing 'middle:' guide spec."""
guide = parse_guide_spec("middle:$2", 0.0, 4.0)
assert guide is not None
assert guide.position == "middle"
assert guide.image_ref == "$2"
def test_parse_guide_spec_timestamp():
"""Test parsing timestamp guide spec."""
guide = parse_guide_spec("00:03:$3", 0.0, 6.0)
assert guide is not None
assert guide.position == "00" # First part before colon
assert "$3" in guide.image_ref or guide.image_ref == "03:$3"
def test_parse_guide_spec_with_strength():
"""Test parsing guide spec with strength modifier."""
guide = parse_guide_spec("first:$0 @ 0.8", 0.0, 2.0)
assert guide is not None
assert guide.position == "first"
assert guide.image_ref == "$0"
assert guide.strength == 0.8
def test_parse_audio_spec_silent():
"""Test parsing audio:silent."""
assert parse_audio_spec("audio:silent") == "silent"
assert parse_audio_spec("audio:SILENT") == "silent"
def test_parse_audio_spec_ambient():
"""Test parsing audio:ambient."""
assert parse_audio_spec("audio:ambient") == "ambient"
def test_parse_audio_spec_dialogue():
"""Test parsing audio with dialogue."""
assert parse_audio_spec('audio:"Hello world"') == "Hello world"
assert parse_audio_spec("audio:'Hello world'") == "Hello world"
def test_parse_scene_script_simple():
"""Test parsing a simple scene script."""
script = """
[00:00-00:02] A woman speaks | audio:silent | first:$0
[00:02-00:04] She smiles | audio:"Hello" | first:$1 | end:$2
"""
chunks = parse_scene_script(script)
assert len(chunks) == 2
# First chunk
assert chunks[0].start_sec == 0.0
assert chunks[0].end_sec == 2.0
assert "woman speaks" in chunks[0].prompt
assert chunks[0].audio_spec == "silent"
assert len(chunks[0].guides) == 1
# Second chunk
assert chunks[1].start_sec == 2.0
assert chunks[1].end_sec == 4.0
assert "smiles" in chunks[1].prompt
assert chunks[1].audio_spec == "Hello"
assert len(chunks[1].guides) == 2
def test_parse_scene_script_with_shot_headers():
"""Test parsing script with shot headers."""
script = """
# === SHOT 1: INTRO ===
[00:00-00:02] Opening scene | audio:silent | first:$0
# === SHOT 2: MAIN ===
[00:02-00:04] Main content | audio:"Dialogue" | first:$1
"""
chunks = parse_scene_script(script)
assert len(chunks) == 2
assert chunks[0].shot_name == "SHOT 1: INTRO"
assert chunks[1].shot_name == "SHOT 2: MAIN"
def test_scene_chunk_properties():
"""Test SceneChunk property methods."""
chunk = SceneChunk(
start_sec=0.0,
end_sec=3.0,
prompt="Test",
audio_spec="silent",
guides=[]
)
assert chunk.duration == 3.0
assert chunk.is_silent == True
assert chunk.is_ambient == False
assert chunk.dialogue is None
chunk2 = SceneChunk(
start_sec=0.0,
end_sec=2.0,
prompt="Test",
audio_spec="Hello world",
guides=[]
)
assert chunk2.is_silent == False
assert chunk2.dialogue == "Hello world"
def test_image_guide_get_position_seconds():
"""Test ImageGuide position to seconds conversion."""
guide_first = ImageGuide(position="first", image_ref="$0")
assert guide_first.get_position_seconds(2.0, 5.0) == 2.0
guide_end = ImageGuide(position="end", image_ref="$1")
assert guide_end.get_position_seconds(2.0, 5.0) == 5.0
guide_middle = ImageGuide(position="middle", image_ref="$2")
assert guide_middle.get_position_seconds(2.0, 6.0) == 4.0
def test_woman_speaking_example():
"""Test the full woman speaking example from requirements."""
script = """
# === SHOT 1: WOMAN INTRODUCTION (6 seconds total) ===
[00:00-00:02] Closeup of woman's face, soft lighting, neutral expression | audio:silent | first:$0 | end:$1
[00:02-00:04] Cowboy shot of woman speaking confidently, gesturing with hands | audio:"Hello, welcome to my channel" | first:$2 | end:$4
[00:04-00:06] Side profile view of woman nodding gently, soft smile | audio:silent | first:$5 | end:$6
"""
chunks = parse_scene_script(script)
assert len(chunks) == 3
# First chunk: closeup, silent
assert chunks[0].start_sec == 0.0
assert chunks[0].end_sec == 2.0
assert "Closeup" in chunks[0].prompt
assert chunks[0].is_silent
assert len(chunks[0].guides) == 2
# Second chunk: cowboy shot with dialogue
assert chunks[1].start_sec == 2.0
assert chunks[1].end_sec == 4.0
assert chunks[1].dialogue == "Hello, welcome to my channel"
assert not chunks[1].is_silent
# Third chunk: side profile, silent
assert chunks[2].start_sec == 4.0
assert chunks[2].end_sec == 6.0
assert chunks[2].is_silent
if __name__ == "__main__":
test_parse_timestamp_mmss()
print("[PASS] test_parse_timestamp_mmss")
test_parse_timestamp_with_ms()
print("[PASS] test_parse_timestamp_with_ms")
test_parse_timestamp_seconds_only()
print("[PASS] test_parse_timestamp_seconds_only")
test_format_timestamp()
print("[PASS] test_format_timestamp")
test_parse_guide_spec_first()
print("[PASS] test_parse_guide_spec_first")
test_parse_guide_spec_end()
print("[PASS] test_parse_guide_spec_end")
test_parse_guide_spec_middle()
print("[PASS] test_parse_guide_spec_middle")
test_parse_guide_spec_with_strength()
print("[PASS] test_parse_guide_spec_with_strength")
test_parse_audio_spec_silent()
print("[PASS] test_parse_audio_spec_silent")
test_parse_audio_spec_ambient()
print("[PASS] test_parse_audio_spec_ambient")
test_parse_audio_spec_dialogue()
print("[PASS] test_parse_audio_spec_dialogue")
test_parse_scene_script_simple()
print("[PASS] test_parse_scene_script_simple")
test_parse_scene_script_with_shot_headers()
print("[PASS] test_parse_scene_script_with_shot_headers")
test_scene_chunk_properties()
print("[PASS] test_scene_chunk_properties")
test_image_guide_get_position_seconds()
print("[PASS] test_image_guide_get_position_seconds")
test_woman_speaking_example()
print("[PASS] test_woman_speaking_example")
print("\nAll tests passed!")