DocUA's picture
βœ… Enhanced Verification Modes - Production Ready
7bbd836
# test_ui_consistency.py
"""
Tests for UI consistency components across all verification modes.
Validates that standardized components provide consistent styling,
formatting, and behavior across all interfaces.
Requirements: 12.1, 12.2, 12.3, 12.4, 12.5
"""
import pytest
from datetime import datetime
from typing import Dict, Any
from src.interface.ui_consistency_components import (
StandardizedComponents,
ClassificationDisplay,
ProgressDisplay,
ErrorDisplay,
SessionDisplay,
HelpDisplay,
UITheme,
format_timestamp,
format_file_size,
truncate_text,
format_duration
)
class TestStandardizedComponents:
"""Test standardized UI component creation."""
def test_create_primary_button(self):
"""Test primary button creation with consistent styling."""
button = StandardizedComponents.create_primary_button("Test Button", "πŸ”₯", "lg")
assert button.value == "πŸ”₯ Test Button"
assert button.variant == "primary"
assert button.size == "lg"
def test_create_secondary_button(self):
"""Test secondary button creation with consistent styling."""
button = StandardizedComponents.create_secondary_button("Test Button", "βš™οΈ", "sm")
assert button.value == "βš™οΈ Test Button"
assert button.variant == "secondary"
assert button.size == "sm"
def test_create_stop_button(self):
"""Test stop button creation with consistent styling."""
button = StandardizedComponents.create_stop_button("Stop", "βœ‹")
assert button.value == "βœ‹ Stop"
assert button.variant == "stop"
def test_create_navigation_button(self):
"""Test navigation button creation with consistent styling."""
button = StandardizedComponents.create_navigation_button("Back")
assert button.value == "← Back"
assert button.size == "sm"
assert button.variant == "secondary"
def test_create_export_button(self):
"""Test export button creation for different formats."""
csv_button = StandardizedComponents.create_export_button("csv")
json_button = StandardizedComponents.create_export_button("json")
xlsx_button = StandardizedComponents.create_export_button("xlsx")
assert csv_button.value == "πŸ“„ Export CSV"
assert json_button.value == "πŸ“‹ Export JSON"
assert xlsx_button.value == "πŸ“Š Export XLSX"
# All should be secondary buttons with small size
for button in [csv_button, json_button, xlsx_button]:
assert button.variant == "secondary"
assert button.size == "sm"
class TestClassificationDisplay:
"""Test classification display formatting consistency."""
def test_format_classification_badge(self):
"""Test classification badge formatting."""
green_badge = ClassificationDisplay.format_classification_badge("green")
yellow_badge = ClassificationDisplay.format_classification_badge("yellow")
red_badge = ClassificationDisplay.format_classification_badge("red")
unknown_badge = ClassificationDisplay.format_classification_badge("unknown")
assert "🟒" in green_badge and "GREEN" in green_badge
assert "🟑" in yellow_badge and "YELLOW" in yellow_badge
assert "πŸ”΄" in red_badge and "RED" in red_badge
assert "❓" in unknown_badge and "UNKNOWN" in unknown_badge
# Test case insensitivity
assert ClassificationDisplay.format_classification_badge("GREEN") == green_badge
assert ClassificationDisplay.format_classification_badge("Red") == red_badge
def test_format_classification_html_badge(self):
"""Test HTML classification badge formatting."""
html_badge = ClassificationDisplay.format_classification_html_badge("green")
assert "<span" in html_badge
assert "🟒" in html_badge
assert "GREEN" in html_badge
assert UITheme.GREEN_BG in html_badge
assert UITheme.GREEN_TEXT in html_badge
def test_format_confidence_display(self):
"""Test confidence display formatting."""
high_confidence = ClassificationDisplay.format_confidence_display(0.95)
medium_confidence = ClassificationDisplay.format_confidence_display(0.75)
low_confidence = ClassificationDisplay.format_confidence_display(0.45)
assert "95%" in high_confidence and "🎯" in high_confidence
assert "75%" in medium_confidence and "πŸ“Š" in medium_confidence
assert "45%" in low_confidence and "⚠️" in low_confidence
def test_format_indicators_display(self):
"""Test indicators display formatting."""
# Test with indicators
indicators = ["hopelessness", "despair", "isolation"]
formatted = ClassificationDisplay.format_indicators_display(indicators)
assert "πŸ”" in formatted
assert "hopelessness" in formatted
assert "despair" in formatted
assert "isolation" in formatted
# Test with no indicators
empty_formatted = ClassificationDisplay.format_indicators_display([])
assert "πŸ”" in empty_formatted
assert "No specific indicators" in empty_formatted
# Test with many indicators (should truncate)
many_indicators = [f"indicator_{i}" for i in range(10)]
truncated = ClassificationDisplay.format_indicators_display(many_indicators)
assert "+5 more" in truncated
def test_create_classification_radio(self):
"""Test classification radio button creation."""
radio = ClassificationDisplay.create_classification_radio()
assert len(radio.choices) == 3
assert any("GREEN" in choice[0] for choice in radio.choices)
assert any("YELLOW" in choice[0] for choice in radio.choices)
assert any("RED" in choice[0] for choice in radio.choices)
# Check values
values = [choice[1] for choice in radio.choices]
assert "green" in values
assert "yellow" in values
assert "red" in values
class TestProgressDisplay:
"""Test progress display formatting consistency."""
def test_format_progress_display(self):
"""Test progress display formatting."""
progress = ProgressDisplay.format_progress_display(5, 10, "Test Mode")
assert "πŸ“Š" in progress
assert "5 of 10" in progress
assert "50%" in progress
# Test with zero total
zero_progress = ProgressDisplay.format_progress_display(0, 0, "Test Mode")
assert "Ready to start" in zero_progress
assert "Test Mode" in zero_progress
def test_format_accuracy_display(self):
"""Test accuracy display formatting."""
high_accuracy = ProgressDisplay.format_accuracy_display(9, 10)
medium_accuracy = ProgressDisplay.format_accuracy_display(7, 10)
low_accuracy = ProgressDisplay.format_accuracy_display(5, 10)
assert "90.0%" in high_accuracy and "🎯" in high_accuracy
assert "70.0%" in medium_accuracy and "⚠️" in medium_accuracy # 70% is below 75% threshold
assert "50.0%" in low_accuracy and "⚠️" in low_accuracy
# Test with zero total
zero_accuracy = ProgressDisplay.format_accuracy_display(0, 0)
assert "No verifications yet" in zero_accuracy
def test_format_processing_speed_display(self):
"""Test processing speed display formatting."""
speed = ProgressDisplay.format_processing_speed_display(10, 2.0)
assert "⚑" in speed
assert "5.0 messages/min" in speed
# Test with zero values
zero_speed = ProgressDisplay.format_processing_speed_display(0, 0)
assert "Calculating..." in zero_speed
def test_create_progress_html_bar(self):
"""Test HTML progress bar creation."""
html_bar = ProgressDisplay.create_progress_html_bar(3, 10)
assert "<div" in html_bar
assert "30.0%" in html_bar # The implementation uses float formatting
assert UITheme.PRIMARY_COLOR in html_bar
# Test with zero total
zero_bar = ProgressDisplay.create_progress_html_bar(0, 0)
assert "0%" in zero_bar
class TestErrorDisplay:
"""Test error display formatting consistency."""
def test_format_error_message(self):
"""Test error message formatting."""
error_msg = ErrorDisplay.format_error_message("Test error", "error")
warning_msg = ErrorDisplay.format_error_message("Test warning", "warning")
info_msg = ErrorDisplay.format_error_message("Test info", "info")
success_msg = ErrorDisplay.format_error_message("Test success", "success")
assert "❌" in error_msg and "Test error" in error_msg
assert "⚠️" in warning_msg and "Test warning" in warning_msg
assert "ℹ️" in info_msg and "Test info" in info_msg
assert "βœ…" in success_msg and "Test success" in success_msg
def test_create_error_html_display(self):
"""Test HTML error display creation."""
suggestions = ["Try this", "Or this"]
html_error = ErrorDisplay.create_error_html_display(
"Test error message",
"error",
suggestions
)
assert "<div" in html_error
assert "Test error message" in html_error
assert "Try this" in html_error
assert "Or this" in html_error
assert UITheme.FONT_FAMILY in html_error
# Test without suggestions
simple_error = ErrorDisplay.create_error_html_display("Simple error", "warning")
assert "Simple error" in simple_error
assert "Suggestions:" not in simple_error
class TestSessionDisplay:
"""Test session display formatting consistency."""
def test_format_session_info(self):
"""Test session information formatting."""
session_data = {
'verifier_name': 'Test User',
'mode_type': 'manual_input',
'dataset_name': 'Test Dataset',
'verified_count': 5,
'total_messages': 10,
'is_complete': False,
'accuracy': 80.0,
'created_at': datetime(2025, 1, 1, 12, 0, 0)
}
info = SessionDisplay.format_session_info(session_data)
assert "Test User" in info
assert "Manual Input" in info # Should format mode type
assert "Test Dataset" in info
assert "5/10" in info
assert "⏳ In Progress" in info
assert "80.0%" in info
assert "2025-01-01 12:00:00" in info
def test_format_session_statistics(self):
"""Test session statistics formatting."""
stats = {
'verified_count': 10,
'correct_count': 8,
'incorrect_count': 2,
'accuracy': 80.0
}
formatted_stats = SessionDisplay.format_session_statistics(stats)
assert "Messages Processed:** 10" in formatted_stats
assert "Correct Classifications:** 8" in formatted_stats
assert "Incorrect Classifications:** 2" in formatted_stats
assert "Accuracy:** 80.0%" in formatted_stats
def test_create_session_summary_card(self):
"""Test session summary card creation."""
session_data = {
'mode_type': 'file_upload',
'dataset_name': 'Test File.csv',
'verifier_name': 'Test User',
'is_complete': True
}
stats = {
'verified_count': 20,
'correct_count': 18,
'incorrect_count': 2,
'accuracy': 90.0,
'breakdown_by_type': {
'green': 10,
'yellow': 5,
'red': 3
}
}
summary = SessionDisplay.create_session_summary_card(session_data, stats)
assert "File Upload" in summary
assert "Test File.csv" in summary
assert "Test User" in summary
assert "20" in summary
assert "90.0%" in summary
assert "🟒" in summary and "10 correct" in summary
assert "🟑" in summary and "5 correct" in summary
assert "πŸ”΄" in summary and "3 correct" in summary
assert "βœ… Complete" in summary
class TestHelpDisplay:
"""Test help display formatting consistency."""
def test_create_mode_description_card(self):
"""Test mode description card creation."""
features = ["Feature 1", "Feature 2", "Feature 3"]
card = HelpDisplay.create_mode_description_card(
"manual_input",
"Test description",
features
)
assert "✏️" in card # Manual input icon
assert "Manual Input" in card
assert "Test description" in card
assert "Feature 1" in card
assert "Feature 2" in card
assert "Feature 3" in card
def test_create_format_help_display(self):
"""Test format help display creation."""
help_text = HelpDisplay.create_format_help_display()
assert "Required columns:" in help_text
assert "message" in help_text
assert "expected_classification" in help_text
assert "green" in help_text
assert "yellow" in help_text
assert "red" in help_text
assert "CSV" in help_text
assert "XLSX" in help_text
def test_create_workflow_help_display(self):
"""Test workflow help display creation."""
manual_help = HelpDisplay.create_workflow_help_display("manual_input")
dataset_help = HelpDisplay.create_workflow_help_display("enhanced_dataset")
upload_help = HelpDisplay.create_workflow_help_display("file_upload")
unknown_help = HelpDisplay.create_workflow_help_display("unknown_mode")
assert "Manual Input Workflow" in manual_help
assert "Enhanced Dataset Workflow" in dataset_help
assert "File Upload Workflow" in upload_help
assert "Unknown Mode" in unknown_help
class TestUtilityFunctions:
"""Test utility formatting functions."""
def test_format_timestamp(self):
"""Test timestamp formatting consistency."""
dt = datetime(2025, 1, 1, 12, 30, 45)
formatted = format_timestamp(dt)
assert formatted == "2025-01-01 12:30:45"
# Test with string input
string_formatted = format_timestamp("2025-01-01 12:30:45")
assert string_formatted == "2025-01-01 12:30:45"
def test_format_file_size(self):
"""Test file size formatting."""
assert format_file_size(500) == "500 B"
assert format_file_size(1536) == "1.5 KB"
assert format_file_size(2097152) == "2.0 MB"
def test_truncate_text(self):
"""Test text truncation consistency."""
short_text = "Short text"
long_text = "This is a very long text that should be truncated"
assert truncate_text(short_text, 50) == short_text
assert truncate_text(long_text, 20) == "This is a very lo..."
assert len(truncate_text(long_text, 20)) == 20
def test_format_duration(self):
"""Test duration formatting consistency."""
start = datetime(2025, 1, 1, 12, 0, 0)
# Test seconds
end_seconds = datetime(2025, 1, 1, 12, 0, 30)
assert format_duration(start, end_seconds) == "30s"
# Test minutes
end_minutes = datetime(2025, 1, 1, 12, 5, 30)
assert format_duration(start, end_minutes) == "5m 30s"
# Test hours
end_hours = datetime(2025, 1, 1, 14, 30, 0)
assert format_duration(start, end_hours) == "2h 30m"
# Test days
end_days = datetime(2025, 1, 3, 14, 0, 0)
assert format_duration(start, end_days) == "2d 2h"
class TestUITheme:
"""Test UI theme consistency."""
def test_color_scheme_consistency(self):
"""Test that color scheme is consistently defined."""
# Test that all required colors are defined
assert hasattr(UITheme, 'PRIMARY_COLOR')
assert hasattr(UITheme, 'SUCCESS_COLOR')
assert hasattr(UITheme, 'WARNING_COLOR')
assert hasattr(UITheme, 'ERROR_COLOR')
assert hasattr(UITheme, 'SECONDARY_COLOR')
# Test classification colors
assert hasattr(UITheme, 'GREEN_BG')
assert hasattr(UITheme, 'GREEN_TEXT')
assert hasattr(UITheme, 'YELLOW_BG')
assert hasattr(UITheme, 'YELLOW_TEXT')
assert hasattr(UITheme, 'RED_BG')
assert hasattr(UITheme, 'RED_TEXT')
# Test that colors are valid hex codes
colors = [
UITheme.PRIMARY_COLOR,
UITheme.SUCCESS_COLOR,
UITheme.WARNING_COLOR,
UITheme.ERROR_COLOR,
UITheme.SECONDARY_COLOR
]
for color in colors:
assert color.startswith('#')
assert len(color) == 7 # #RRGGBB format
def test_layout_consistency(self):
"""Test that layout values are consistently defined."""
assert hasattr(UITheme, 'BORDER_RADIUS')
assert hasattr(UITheme, 'PADDING_SM')
assert hasattr(UITheme, 'PADDING_MD')
assert hasattr(UITheme, 'PADDING_LG')
# Test that padding values include units
assert 'em' in UITheme.PADDING_SM
assert 'em' in UITheme.PADDING_MD
assert 'em' in UITheme.PADDING_LG
def test_typography_consistency(self):
"""Test that typography is consistently defined."""
assert hasattr(UITheme, 'FONT_FAMILY')
assert hasattr(UITheme, 'FONT_SIZE_SM')
assert hasattr(UITheme, 'FONT_SIZE_MD')
assert hasattr(UITheme, 'FONT_SIZE_LG')
# Test that font sizes include units
assert 'em' in UITheme.FONT_SIZE_SM
assert 'em' in UITheme.FONT_SIZE_MD
assert 'em' in UITheme.FONT_SIZE_LG
if __name__ == "__main__":
pytest.main([__file__])