import pytest import time import sys import os import json from pathlib import Path sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "src"))) from src import api_hook_client @pytest.mark.integration def test_undo_redo_lifecycle(live_gui): client = api_hook_client.ApiHookClient() assert client.wait_for_server(timeout=15), "Hook server did not start" # 1. Set initial state print("Setting initial state...") client.set_value('temperature', 0.5) client.set_value('ai_input', "Initial Input") # Wait for settle and first push (S_init -> S0) time.sleep(3.0) # 2. Change state print("Modifying state...") client.set_value('temperature', 1.5) client.set_value('ai_input', "Modified Input") # Wait for settle and second push (S0 -> S1) time.sleep(3.0) # Verify current state temp = client.get_value('temperature') ai_in = client.get_value('ai_input') print(f"Current state: temp={temp}, ai_input={ai_in}") assert temp == 1.5 assert ai_in == "Modified Input" # 3. Undo print("Sending Undo...") client.click('btn_undo') # Wait for state to revert time.sleep(1.0) ai_in_undo = client.get_value('ai_input') temp_undo = client.get_value('temperature') print(f"After undo: ai_input={ai_in_undo}, temp={temp_undo}") assert ai_in_undo == "Initial Input" assert temp_undo == 0.5 # 4. Redo print("Sending Redo...") client.click('btn_redo') time.sleep(1.0) ai_in_redo = client.get_value('ai_input') temp_redo = client.get_value('temperature') print(f"After redo: ai_input={ai_in_redo}, temp={temp_redo}") assert ai_in_redo == "Modified Input" assert temp_redo == 1.5 print("Undo/Redo basic lifecycle PASSED.") @pytest.mark.integration def test_undo_redo_discussion_mutation(live_gui): client = api_hook_client.ApiHookClient() assert client.wait_for_server(timeout=15) # Get initial entries count initial_entries = client.get_value('disc_entries') initial_count = len(initial_entries) print(f"Initial entries: {initial_count}") # 1. Add an entry (we simulate this by appending to disc_entries) # Wait for settle time.sleep(2.0) new_entries = initial_entries + [{"role": "User", "content": "New Entry", "collapsed": False, "ts": "2026-03-11 12:00:00"}] client.set_value('disc_entries', new_entries) # Wait for debounce time.sleep(2.0) assert len(client.get_value('disc_entries')) == initial_count + 1 # 2. Undo addition print("Undoing entry addition...") client.click('btn_undo') time.sleep(0.5) assert len(client.get_value('disc_entries')) == initial_count # 3. Redo addition print("Redoing entry addition...") client.click('btn_redo') time.sleep(0.5) assert len(client.get_value('disc_entries')) == initial_count + 1 print("Undo/Redo discussion mutation PASSED.") @pytest.mark.integration def test_undo_redo_context_mutation(live_gui): client = api_hook_client.ApiHookClient() assert client.wait_for_server(timeout=15) # Wait for settle time.sleep(2.0) # 1. Add a file client.set_value('ui_file_paths', ['test_undo.py']) # Wait for debounce time.sleep(2.0) assert 'test_undo.py' in client.get_value('ui_file_paths') # 2. Undo addition print("Undoing file addition...") client.click('btn_undo') time.sleep(0.5) assert 'test_undo.py' not in client.get_value('ui_file_paths') # 3. Redo addition print("Redoing file addition...") client.click('btn_redo') time.sleep(0.5) assert 'test_undo.py' in client.get_value('ui_file_paths') print("Undo/Redo context mutation PASSED.")