Spaces:
Paused
Paused
| """Tests for UI state management.""" | |
| import json | |
| import pytest | |
| from ui.state import ( | |
| SessionState, | |
| AssessmentHistory, | |
| ProjectFormData, | |
| RoomFormData, | |
| ImageFormData, | |
| ObservationsFormData, | |
| create_new_session, | |
| session_to_json, | |
| session_from_json, | |
| history_to_json, | |
| history_from_json, | |
| ) | |
| from ui.components import ( | |
| create_validation_message, | |
| create_room_table_data, | |
| create_history_dropdown_choices, | |
| create_stats_dict, | |
| ImageStore, | |
| ) | |
| class TestSessionState: | |
| """Test SessionState model.""" | |
| def test_create_new_session(self): | |
| session = create_new_session() | |
| assert session.session_id is not None | |
| assert len(session.session_id) == 32 # UUID hex | |
| assert session.tab1_complete is False | |
| assert len(session.rooms) == 0 | |
| def test_session_serialization(self): | |
| session = SessionState() | |
| session.project.project_name = "Test Project" | |
| session.rooms.append(RoomFormData( | |
| name="Room 1", | |
| length_ft=100, | |
| width_ft=50, | |
| ceiling_height_ft=20, | |
| )) | |
| # Serialize | |
| json_str = session_to_json(session) | |
| assert "Test Project" in json_str | |
| assert "Room 1" in json_str | |
| # Deserialize | |
| loaded = session_from_json(json_str) | |
| assert loaded.project.project_name == "Test Project" | |
| assert len(loaded.rooms) == 1 | |
| assert loaded.rooms[0].name == "Room 1" | |
| def test_session_validation_tab1_incomplete(self): | |
| session = SessionState() | |
| is_valid, errors = session.validate_tab1() | |
| assert is_valid is False | |
| assert "Project name is required" in errors | |
| assert "Address is required" in errors | |
| def test_session_validation_tab1_complete(self): | |
| session = SessionState() | |
| session.project = ProjectFormData( | |
| project_name="Test Project", | |
| address="123 Main St", | |
| city="Springfield", | |
| state="IL", | |
| zip_code="62701", | |
| client_name="Test Client", | |
| fire_date="2024-12-01", | |
| assessment_date="2024-12-15", | |
| assessor_name="John Smith", | |
| ) | |
| is_valid, errors = session.validate_tab1() | |
| assert is_valid is True | |
| assert len(errors) == 0 | |
| def test_session_validation_tab2_no_rooms(self): | |
| session = SessionState() | |
| is_valid, errors = session.validate_tab2() | |
| assert is_valid is False | |
| assert "At least one room is required" in errors | |
| def test_session_validation_tab2_invalid_dimensions(self): | |
| session = SessionState() | |
| session.rooms.append(RoomFormData( | |
| name="Room 1", | |
| length_ft=0, # Invalid | |
| width_ft=50, | |
| ceiling_height_ft=20, | |
| )) | |
| is_valid, errors = session.validate_tab2() | |
| assert is_valid is False | |
| assert any("Length must be greater than 0" in e for e in errors) | |
| def test_session_validation_tab2_complete(self): | |
| session = SessionState() | |
| session.rooms.append(RoomFormData( | |
| name="Room 1", | |
| length_ft=100, | |
| width_ft=50, | |
| ceiling_height_ft=20, | |
| )) | |
| is_valid, errors = session.validate_tab2() | |
| assert is_valid is True | |
| def test_session_validation_tab3_no_images(self): | |
| session = SessionState() | |
| is_valid, errors = session.validate_tab3() | |
| assert is_valid is False | |
| assert "At least one image is required" in errors | |
| def test_session_validation_tab3_complete(self): | |
| session = SessionState() | |
| session.rooms.append(RoomFormData(id="room-001", name="Room 1")) | |
| session.images.append(ImageFormData( | |
| filename="test.jpg", | |
| room_id="room-001", | |
| )) | |
| is_valid, errors = session.validate_tab3() | |
| assert is_valid is True | |
| def test_session_can_generate(self): | |
| session = SessionState() | |
| # Fill all required fields | |
| session.project = ProjectFormData( | |
| project_name="Test", | |
| address="123 Main", | |
| city="City", | |
| state="IL", | |
| zip_code="12345", | |
| client_name="Client", | |
| fire_date="2024-01-01", | |
| assessment_date="2024-01-02", | |
| assessor_name="Assessor", | |
| ) | |
| session.rooms.append(RoomFormData( | |
| id="room-001", | |
| name="Room 1", | |
| length_ft=100, | |
| width_ft=50, | |
| ceiling_height_ft=20, | |
| )) | |
| session.images.append(ImageFormData( | |
| filename="test.jpg", | |
| room_id="room-001", | |
| )) | |
| can_gen, errors = session.can_generate() | |
| assert can_gen is True | |
| assert len(errors) == 0 | |
| def test_session_display_name(self): | |
| session = SessionState() | |
| # Default name from session ID | |
| assert session.session_id[:8] in session.get_display_name() | |
| # Name from project | |
| session.project.project_name = "My Project" | |
| assert session.get_display_name() == "My Project" | |
| # Explicit name takes priority | |
| session.name = "Custom Name" | |
| assert session.get_display_name() == "Custom Name" | |
| class TestAssessmentHistory: | |
| """Test AssessmentHistory model.""" | |
| def test_empty_history(self): | |
| history = AssessmentHistory() | |
| assert len(history.assessments) == 0 | |
| assert history.current_session_id is None | |
| def test_add_assessment(self): | |
| history = AssessmentHistory() | |
| session = SessionState() | |
| session.project.project_name = "Test" | |
| history.add_assessment(session) | |
| assert len(history.assessments) == 1 | |
| assert history.assessments[0].session_id == session.session_id | |
| def test_add_assessment_updates_existing(self): | |
| history = AssessmentHistory() | |
| session = SessionState() | |
| session.project.project_name = "Original" | |
| history.add_assessment(session) | |
| # Update and re-add | |
| session.project.project_name = "Updated" | |
| history.add_assessment(session) | |
| # Should still have only 1 entry | |
| assert len(history.assessments) == 1 | |
| assert history.assessments[0].project.project_name == "Updated" | |
| def test_history_limit(self): | |
| history = AssessmentHistory() | |
| # Add 25 assessments | |
| for i in range(25): | |
| session = SessionState() | |
| session.project.project_name = f"Project {i}" | |
| history.add_assessment(session) | |
| # Should only keep 20 | |
| assert len(history.assessments) == 20 | |
| # Most recent should be first | |
| assert history.assessments[0].project.project_name == "Project 24" | |
| def test_get_assessment(self): | |
| history = AssessmentHistory() | |
| session = SessionState() | |
| history.add_assessment(session) | |
| retrieved = history.get_assessment(session.session_id) | |
| assert retrieved is not None | |
| assert retrieved.session_id == session.session_id | |
| # Non-existent | |
| assert history.get_assessment("nonexistent") is None | |
| def test_remove_assessment(self): | |
| history = AssessmentHistory() | |
| session = SessionState() | |
| history.add_assessment(session) | |
| history.remove_assessment(session.session_id) | |
| assert len(history.assessments) == 0 | |
| def test_history_serialization(self): | |
| history = AssessmentHistory() | |
| session = SessionState() | |
| session.project.project_name = "Test Project" | |
| history.add_assessment(session) | |
| json_str = history_to_json(history) | |
| loaded = history_from_json(json_str) | |
| assert len(loaded.assessments) == 1 | |
| assert loaded.assessments[0].project.project_name == "Test Project" | |
| def test_history_items(self): | |
| history = AssessmentHistory() | |
| session = SessionState() | |
| session.project.project_name = "Test Project" | |
| session.has_results = True | |
| history.add_assessment(session) | |
| items = history.get_history_items() | |
| assert len(items) == 1 | |
| assert items[0]["name"] == "Test Project" | |
| assert items[0]["has_results"] is True | |
| class TestUIComponents: | |
| """Test UI component helpers.""" | |
| def test_validation_message_success(self): | |
| msg = create_validation_message(True, [], "All good!") | |
| assert "✓" in msg | |
| assert "All good!" in msg | |
| def test_validation_message_failure(self): | |
| msg = create_validation_message(False, ["Error 1", "Error 2"]) | |
| assert "⚠" in msg | |
| assert "Error 1" in msg | |
| assert "Error 2" in msg | |
| def test_room_table_data(self): | |
| session = SessionState() | |
| session.rooms.append(RoomFormData( | |
| name="Room 1", | |
| length_ft=100, | |
| width_ft=50, | |
| ceiling_height_ft=20, | |
| )) | |
| data = create_room_table_data(session) | |
| assert len(data) == 1 | |
| assert data[0][0] == "Room 1" | |
| assert "100 x 50 x 20" in data[0][1] | |
| assert "5,000" in data[0][2] # Area | |
| assert "100,000" in data[0][3] # Volume | |
| def test_history_dropdown_choices(self): | |
| history = AssessmentHistory() | |
| session = SessionState() | |
| session.project.project_name = "Test Project" | |
| history.add_assessment(session) | |
| choices = create_history_dropdown_choices(history) | |
| assert len(choices) == 2 # "New Assessment" + 1 saved | |
| assert choices[0][0] == "-- New Assessment --" | |
| assert "Test Project" in choices[1][0] | |
| def test_stats_dict(self): | |
| session = SessionState() | |
| session.rooms.append(RoomFormData( | |
| name="Room 1", | |
| length_ft=100, | |
| width_ft=50, | |
| ceiling_height_ft=20, | |
| )) | |
| session.images.append(ImageFormData(filename="test.jpg", room_id="room-001")) | |
| stats = create_stats_dict(session) | |
| assert stats["rooms"] == 1 | |
| assert stats["images"] == 1 | |
| assert stats["total_floor_area_sf"] == "5,000" | |
| assert stats["total_volume_cf"] == "100,000" | |
| class TestImageStore: | |
| """Test ImageStore for in-memory image storage.""" | |
| def test_store_and_get(self): | |
| store = ImageStore() | |
| store.store("img-001", b"test image bytes") | |
| assert store.get("img-001") == b"test image bytes" | |
| assert store.get("nonexistent") is None | |
| def test_remove(self): | |
| store = ImageStore() | |
| store.store("img-001", b"test") | |
| store.remove("img-001") | |
| assert store.get("img-001") is None | |
| def test_clear(self): | |
| store = ImageStore() | |
| store.store("img-001", b"test1") | |
| store.store("img-002", b"test2") | |
| store.clear() | |
| assert store.get("img-001") is None | |
| assert store.get("img-002") is None | |
| def test_missing_ids(self): | |
| store = ImageStore() | |
| store.store("img-001", b"test") | |
| missing = store.get_missing_ids(["img-001", "img-002", "img-003"]) | |
| assert missing == ["img-002", "img-003"] | |
| def test_has_all(self): | |
| store = ImageStore() | |
| store.store("img-001", b"test1") | |
| store.store("img-002", b"test2") | |
| assert store.has_all(["img-001", "img-002"]) is True | |
| assert store.has_all(["img-001", "img-003"]) is False | |