""" Tests for static file serving (CSS, JS). This module tests that CSS and JavaScript files are properly served through FastAPI's static files mounting. """ import pytest from httpx import ASGITransport, AsyncClient from src.server.fastapi_app import app @pytest.fixture async def client(): """Create an async test client for the FastAPI app.""" transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as ac: yield ac class TestCSSFileServing: """Test CSS file serving functionality.""" @pytest.mark.asyncio async def test_styles_css_accessible(self, client): """Test that styles.css is accessible.""" response = await client.get("/static/css/styles.css") assert response.status_code == 200 assert "text/css" in response.headers.get("content-type", "") assert len(response.text) > 0 @pytest.mark.asyncio async def test_ux_features_css_accessible(self, client): """Test that ux_features.css is accessible.""" response = await client.get("/static/css/ux_features.css") assert response.status_code == 200 assert "text/css" in response.headers.get("content-type", "") assert len(response.text) > 0 @pytest.mark.asyncio async def test_css_contains_expected_variables(self, client): """Test that styles.css contains expected CSS variables.""" response = await client.get("/static/css/styles.css") assert response.status_code == 200 content = response.text # Check for Fluent UI design system variables assert "--color-bg-primary:" in content assert "--color-accent:" in content assert "--font-family:" in content assert "--spacing-" in content assert "--border-radius-" in content @pytest.mark.asyncio async def test_css_contains_dark_theme_support(self, client): """Test that styles.css contains dark theme support.""" response = await client.get("/static/css/styles.css") assert response.status_code == 200 content = response.text # Check for dark theme variables assert '[data-theme="dark"]' in content assert "--color-bg-primary-dark:" in content assert "--color-text-primary-dark:" in content @pytest.mark.asyncio async def test_css_contains_responsive_design(self, client): """Test that CSS files contain responsive design media queries.""" # Test styles.css response = await client.get("/static/css/styles.css") assert response.status_code == 200 assert "@media" in response.text # Test ux_features.css response = await client.get("/static/css/ux_features.css") assert response.status_code == 200 assert "@media" in response.text @pytest.mark.asyncio async def test_ux_features_css_contains_accessibility(self, client): """Test that ux_features.css contains accessibility features.""" response = await client.get("/static/css/ux_features.css") assert response.status_code == 200 content = response.text # Check for accessibility features assert ".sr-only" in content # Screen reader only assert "prefers-contrast" in content # High contrast mode assert ".keyboard-focus" in content # Keyboard navigation @pytest.mark.asyncio async def test_nonexistent_css_returns_404(self, client): """Test that requesting a nonexistent CSS file returns 404.""" response = await client.get("/static/css/nonexistent.css") # Static files might return HTML or 404, just ensure CSS exists assert response.status_code in [200, 404] class TestJavaScriptFileServing: """Test JavaScript file serving functionality.""" @pytest.mark.asyncio async def test_app_js_accessible(self, client): """Test that app.js is accessible.""" response = await client.get("/static/js/app.js") # File might not exist yet, but if it does, it should be served correctly if response.status_code == 200: assert "javascript" in response.headers.get("content-type", "").lower() @pytest.mark.asyncio async def test_websocket_client_js_accessible(self, client): """Test that websocket_client.js is accessible.""" response = await client.get("/static/js/websocket_client.js") # File might not exist yet, but if it does, it should be served correctly if response.status_code == 200: assert "javascript" in response.headers.get("content-type", "").lower() class TestHTMLTemplatesCSS: """Test that HTML templates correctly reference CSS files.""" @pytest.mark.asyncio async def test_index_page_references_css(self, client): """Test that index.html correctly references CSS files.""" response = await client.get("/") assert response.status_code == 200 content = response.text # Check for CSS references assert '/static/css/styles.css' in content assert '/static/css/ux_features.css' in content @pytest.mark.asyncio async def test_login_page_references_css(self, client): """Test that login.html correctly references CSS files.""" response = await client.get("/login") assert response.status_code == 200 content = response.text # Check for CSS reference assert '/static/css/styles.css' in content @pytest.mark.asyncio async def test_setup_page_references_css(self, client): """Test that setup.html correctly references CSS files.""" response = await client.get("/setup") assert response.status_code == 200 content = response.text # Check for CSS reference assert '/static/css/styles.css' in content @pytest.mark.asyncio async def test_queue_page_references_css(self, client): """Test that queue.html correctly references CSS files.""" response = await client.get("/queue") assert response.status_code == 200 content = response.text # Check for CSS reference assert '/static/css/styles.css' in content @pytest.mark.asyncio async def test_css_paths_are_absolute(self, client): """Test that CSS paths in templates are absolute paths.""" pages = ["/", "/login", "/setup", "/queue"] for page in pages: response = await client.get(page) assert response.status_code == 200 content = response.text # Ensure CSS links start with /static (absolute paths) if 'href="/static/css/' in content: # Good - using absolute paths assert 'href="static/css/' not in content elif 'href="static/css/' in content: msg = f"Page {page} uses relative CSS paths" pytest.fail(msg) class TestCSSContentIntegrity: """Test CSS content integrity and structure.""" @pytest.mark.asyncio async def test_styles_css_structure(self, client): """Test that styles.css has proper structure.""" response = await client.get("/static/css/styles.css") assert response.status_code == 200 content = response.text # Should have CSS variable definitions assert ":root" in content # Should have base element styles assert "body" in content or "html" in content # Should not have syntax errors (basic check) # Count braces - should be balanced open_braces = content.count("{") close_braces = content.count("}") assert open_braces == close_braces, "CSS has unbalanced braces" @pytest.mark.asyncio async def test_ux_features_css_structure(self, client): """Test that ux_features.css has proper structure.""" response = await client.get("/static/css/ux_features.css") assert response.status_code == 200 content = response.text # Should not have syntax errors (basic check) open_braces = content.count("{") close_braces = content.count("}") assert open_braces == close_braces, "CSS has unbalanced braces" @pytest.mark.asyncio async def test_css_file_sizes_reasonable(self, client): """Test that CSS files are not empty and have reasonable sizes.""" # Test styles.css response = await client.get("/static/css/styles.css") assert response.status_code == 200 assert len(response.text) > 1000, "styles.css seems too small" assert len(response.text) < 500000, "styles.css seems unusually large" # Test ux_features.css response = await client.get("/static/css/ux_features.css") assert response.status_code == 200 assert len(response.text) > 100, "ux_features.css seems too small" msg = "ux_features.css seems unusually large" assert len(response.text) < 100000, msg