"""Tests for Signal reactive system - parsing, codegen, and execution.""" import textwrap def test_parse_signal_declaration(): """Test parsing a signal assignment.""" from ritz.parser import parse_component source = textwrap.dedent( """ @component def Counter(): count = signal(0) with P(): yield "test" """ ) ir = parse_component(source) # Should have signal in body assert len(ir["body"]) == 2 signal_stmt = ir["body"][0] assert signal_stmt["type"] == "signal" assert signal_stmt["name"] == "count" assert signal_stmt["initial"]["type"] == "constant" assert signal_stmt["initial"]["value"] == 0 def test_parse_signal_in_template(): """Test parsing signal reference in f-string.""" from ritz.parser import parse_component source = textwrap.dedent( """ @component def Counter(): count = signal(0) with P(): yield f"Count: {count}" """ ) ir = parse_component(source) # Find the yield statement with_stmt = ir["body"][1] yield_stmt = with_stmt["body"][0] # Should be an f-string assert yield_stmt["value"]["type"] == "fstring" parts = yield_stmt["value"]["parts"] # Should have "Count: " as constant and count as formatted value assert any(p["type"] == "constant" for p in parts) assert any(p["type"] == "formatted_value" for p in parts) def test_parse_event_handler(): """Test parsing onclick event handler.""" from ritz.parser import parse_component source = textwrap.dedent( """ @component def Counter(): count = signal(0) def increment(): count += 1 with Button(onclick=increment): yield "Click me" """ ) ir = parse_component(source) # Should have signal, function, and with statement assert len(ir["body"]) == 3 # Check function definition func_stmt = ir["body"][1] assert func_stmt["type"] == "function" assert func_stmt["name"] == "increment" # Check onclick prop with_stmt = ir["body"][2] onclick_prop = with_stmt["element"]["props"].get("onclick") assert onclick_prop is not None assert onclick_prop["type"] == "name" assert onclick_prop["id"] == "increment" def test_parse_signal_update(): """Test parsing signal increment (count += 1).""" from ritz.parser import parse_component source = textwrap.dedent( """ @component def Counter(): count = signal(0) def increment(): count += 1 """ ) ir = parse_component(source) # Get the increment function func_stmt = ir["body"][1] func_body = func_stmt["body"][0] # Should be an augmented assignment assert func_body["type"] == "augassign" assert func_body["target"] == "count" assert func_body["op"] == "Add" assert func_body["value"]["type"] == "constant" assert func_body["value"]["value"] == 1