""" Test suite for Habits frontend page structure and navigation Story US-006: Frontend - Page structure, layout, and navigation link """ import sys import os from pathlib import Path # Add parent directory to path for imports sys.path.insert(0, str(Path(__file__).parent.parent)) def test_habits_html_exists(): """Test 1: habits.html exists in dashboard/""" habits_path = Path(__file__).parent.parent / 'habits.html' assert habits_path.exists(), "habits.html should exist in dashboard/" print("✓ Test 1: habits.html exists") def test_habits_html_structure(): """Test 2: Page includes common.css, Lucide icons, and swipe-nav.js""" habits_path = Path(__file__).parent.parent / 'habits.html' content = habits_path.read_text() assert 'href="/echo/common.css"' in content, "Should include common.css" assert 'lucide@latest/dist/umd/lucide.min.js' in content, "Should include Lucide icons" assert 'src="/echo/swipe-nav.js"' in content, "Should include swipe-nav.js" print("✓ Test 2: Page includes required CSS and JS") def test_page_has_header(): """Test 3: Page has header with 'Habits' title and 'Add Habit' button""" habits_path = Path(__file__).parent.parent / 'habits.html' content = habits_path.read_text() assert 'class="page-title"' in content, "Should have page-title element" assert '>HabitsHabits') nav_end = content.find('', nav_start) nav_section = content[nav_start:nav_end] assert '/echo/habits.html' in nav_section, "Habits link should be in navigation" assert 'dumbbell' in nav_section, "Dumbbell icon should be in navigation" print("✓ Test 6: index.html includes Habits navigation link") def test_page_fetches_habits(): """Test 7: Page fetches GET /echo/api/habits on load""" habits_path = Path(__file__).parent.parent / 'habits.html' content = habits_path.read_text() assert "fetch('/echo/api/habits')" in content or 'fetch("/echo/api/habits")' in content, \ "Should fetch from /echo/api/habits" assert 'loadHabits' in content, "Should have loadHabits function" # Check that loadHabits is called on page load # (either in inline script or as last statement) assert content.count('loadHabits()') > 0, "loadHabits should be called" print("✓ Test 7: Page fetches habits on load") def test_habit_card_rendering(): """Test 8: Placeholder habit card rendering exists""" habits_path = Path(__file__).parent.parent / 'habits.html' content = habits_path.read_text() assert 'renderHabitCard' in content, "Should have renderHabitCard function" assert 'habit-card' in content, "Should have habit-card class" assert 'renderHabits' in content, "Should have renderHabits function" print("✓ Test 8: Habit card rendering functions exist") def test_no_console_errors_structure(): """Test 9: No obvious console error sources (basic structure check)""" habits_path = Path(__file__).parent.parent / 'habits.html' content = habits_path.read_text() # Check for basic script structure assert '') assert script_open == script_close, f"Script tags should match (found {script_open} opens, {script_close} closes)" print("✓ Test 10: HTML structure is well-formed") def run_all_tests(): """Run all tests in sequence""" tests = [ test_habits_html_exists, test_habits_html_structure, test_page_has_header, test_empty_state, test_grid_container, test_index_navigation_link, test_page_fetches_habits, test_habit_card_rendering, test_no_console_errors_structure, test_typecheck, ] print(f"\nRunning {len(tests)} frontend tests for US-006...\n") failed = [] for test in tests: try: test() except AssertionError as e: print(f"✗ {test.__name__}: {e}") failed.append((test.__name__, str(e))) except Exception as e: print(f"✗ {test.__name__}: Unexpected error: {e}") failed.append((test.__name__, str(e))) print(f"\n{'='*60}") if failed: print(f"FAILED: {len(failed)} test(s) failed:") for name, error in failed: print(f" - {name}: {error}") sys.exit(1) else: print(f"SUCCESS: All {len(tests)} tests passed!") sys.exit(0) if __name__ == '__main__': run_all_tests()