Aniworld/tests/unit/test_static_files.py
Lukas 2bc616a062 feat: Integrate CSS styling with FastAPI static files
- Verified CSS files are properly served through FastAPI StaticFiles
- All templates use absolute paths (/static/css/...)
- Confirmed Fluent UI design system with light/dark theme support
- Added comprehensive test suite (17 tests, all passing):
  * CSS file accessibility tests
  * Theme support verification
  * Responsive design validation
  * Accessibility feature checks
  * Content integrity validation
- Updated infrastructure.md with CSS integration details
- Removed completed task from instructions.md

CSS Files:
- styles.css (1,840 lines): Main Fluent UI design system
- ux_features.css (203 lines): UX enhancements and accessibility

Test coverage:
- tests/unit/test_static_files.py: Full static file serving tests
2025-10-17 19:13:37 +02:00

244 lines
9.0 KiB
Python

"""
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