Files
StreamLens/test_button_persistence_live.py

189 lines
7.8 KiB
Python

#!/usr/bin/env python3
"""
Test button persistence throughout a live session
"""
import sys
import asyncio
import time
from pathlib import Path
# Add analyzer to path
sys.path.insert(0, str(Path(__file__).parent))
from analyzer.tui.textual.app_v2 import StreamLensAppV2
from analyzer.analysis.core import EthernetAnalyzer
from analyzer.models.flow_stats import FlowStats, FrameTypeStats
from textual_inspector import inspect_textual_app, print_widget_tree
async def simulate_data_loading_with_monitoring():
"""Simulate data loading while monitoring button persistence"""
print("🧪 Testing Button Persistence Throughout Session")
print("=" * 60)
# Create analyzer and app
analyzer = EthernetAnalyzer()
app = StreamLensAppV2(analyzer=analyzer)
async with app.run_test() as pilot:
print("📱 App started - checking initial button state...")
# Helper function to count buttons
def count_buttons():
app_data = inspect_textual_app(app)
button_count = 0
visible_buttons = 0
properly_sized = 0
def count_buttons_recursive(widget_data):
nonlocal button_count, visible_buttons, properly_sized
if widget_data.get('type') == 'Button' or 'Button' in widget_data.get('type', ''):
button_count += 1
if widget_data.get('visible', False):
visible_buttons += 1
size = widget_data.get('size', {})
if size.get('width', 0) > 0 and size.get('height', 0) > 0:
properly_sized += 1
for child in widget_data.get('children', []):
count_buttons_recursive(child)
count_buttons_recursive(app_data.get('current_screen', {}))
return button_count, visible_buttons, properly_sized
# Phase 1: Initial state (no data)
await asyncio.sleep(1)
total1, visible1, sized1 = count_buttons()
print(f"📊 Phase 1 (Initial): {total1} total, {visible1} visible, {sized1} properly sized")
# Phase 2: Add some flows to trigger refresh
print("\n🔄 Phase 2: Adding flow data to trigger refresh...")
# Add flows with different frame types
flow1 = FlowStats(src_ip="192.168.1.1", dst_ip="192.168.1.2")
flow1.frame_types["CH10-Data"] = FrameTypeStats("CH10-Data", count=100)
flow1.frame_types["UDP"] = FrameTypeStats("UDP", count=50)
analyzer.flows["flow1"] = flow1
flow2 = FlowStats(src_ip="192.168.1.3", dst_ip="192.168.1.4")
flow2.frame_types["PTP-Sync"] = FrameTypeStats("PTP-Sync", count=200)
flow2.frame_types["PTP-Signaling"] = FrameTypeStats("PTP-Signaling", count=75)
analyzer.flows["flow2"] = flow2
# Wait for UI to process the changes
await asyncio.sleep(2)
total2, visible2, sized2 = count_buttons()
print(f"📊 Phase 2 (With Data): {total2} total, {visible2} visible, {sized2} properly sized")
# Phase 3: Add more data to test ordering/refresh
print("\n🔄 Phase 3: Adding more data to test refresh logic...")
flow3 = FlowStats(src_ip="192.168.1.5", dst_ip="192.168.1.6")
flow3.frame_types["TMATS"] = FrameTypeStats("TMATS", count=500) # High count should reorder
flow3.frame_types["TCP"] = FrameTypeStats("TCP", count=25)
analyzer.flows["flow3"] = flow3
# Wait for refresh
await asyncio.sleep(2)
total3, visible3, sized3 = count_buttons()
print(f"📊 Phase 3 (More Data): {total3} total, {visible3} visible, {sized3} properly sized")
# Phase 4: Final check with detailed analysis
print("\n🔍 Phase 4: Detailed button analysis...")
app_data = inspect_textual_app(app)
buttons_found = []
def analyze_buttons(widget_data, path=""):
if widget_data.get('type') == 'Button' or 'Button' in widget_data.get('type', ''):
button_info = {
'id': widget_data.get('id'),
'label': widget_data.get('label', 'NO LABEL'),
'visible': widget_data.get('visible', False),
'size': widget_data.get('size', {}),
'classes': widget_data.get('classes', [])
}
buttons_found.append(button_info)
for child in widget_data.get('children', []):
analyze_buttons(child, f"{path}/{widget_data.get('type', 'Unknown')}")
analyze_buttons(app_data.get('current_screen', {}))
print(f"\n📋 Final Button States:")
for i, button in enumerate(buttons_found, 1):
label = button.get('label', 'NO LABEL')
size = button.get('size', {})
visible = button.get('visible', False)
status_icons = []
if visible: status_icons.append("👁️")
if size.get('height', 0) > 0: status_icons.append("📏")
if label and label != 'NO LABEL': status_icons.append("📝")
status = " ".join(status_icons) if status_icons else ""
print(f" {i:2d}. {button.get('id', 'unknown'):20} '{label:12}' {size.get('width', 0):2d}x{size.get('height', 0)} {status}")
# Summary
print(f"\n📈 PERSISTENCE TEST RESULTS:")
print(f" Phase 1 (Initial): {total1:2d} buttons ({visible1} visible, {sized1} sized)")
print(f" Phase 2 (Data): {total2:2d} buttons ({visible2} visible, {sized2} sized)")
print(f" Phase 3 (More): {total3:2d} buttons ({visible3} visible, {sized3} sized)")
# Check for consistency
if total1 == total2 == total3:
print(f" ✅ BUTTON COUNT STABLE throughout session")
else:
print(f" 🚨 Button count changed: {total1}{total2}{total3}")
if visible1 == visible2 == visible3:
print(f" ✅ BUTTON VISIBILITY STABLE throughout session")
else:
print(f" 🚨 Visibility changed: {visible1}{visible2}{visible3}")
if sized1 == sized2 == sized3 and sized3 > 0:
print(f" ✅ BUTTON SIZING STABLE and working throughout session")
else:
print(f" 🚨 Sizing changed: {sized1}{sized2}{sized3}")
# Final verdict
all_stable = (total1 == total2 == total3 and
visible1 == visible2 == visible3 and
sized1 == sized2 == sized3 and
sized3 > 0)
if all_stable:
print(f"\n🎉 SUCCESS: Buttons persist properly throughout the session!")
else:
print(f"\n⚠️ Issues detected in button persistence")
return all_stable
def main():
print("🧪 StreamLens Button Persistence Test")
print("This test simulates a full session with data loading")
print("=" * 60)
try:
success = asyncio.run(simulate_data_loading_with_monitoring())
if success:
print(f"\n✅ All button persistence tests PASSED!")
print(f"\n🎯 Both issues have been resolved:")
print(f" ✅ Buttons persist throughout the session")
print(f" ✅ Button text is visible (proper height)")
else:
print(f"\n❌ Some persistence issues remain")
except KeyboardInterrupt:
print("\n🛑 Test interrupted by user")
except Exception as e:
print(f"\n❌ Test failed with error: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
main()