Aniworld/tests/unit/test_static_files.py

260 lines
9.8 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 CSS variables are defined in base/variables.css."""
# Variables are now in a separate module file
response = await client.get("/static/css/base/variables.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 dark theme support is in base/variables.css."""
# Dark theme variables are now in a separate module file
response = await client.get("/static/css/base/variables.css")
assert response.status_code == 200
content = response.text
# Check for dark theme variables
assert '[data-theme="dark"]' in content
@pytest.mark.asyncio
async def test_css_contains_responsive_design(self, client):
"""Test that CSS files contain responsive design media queries."""
# Responsive styles are now in utilities/responsive.css
response = await client.get("/static/css/utilities/responsive.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 is a modular entry point with @import statements."""
response = await client.get("/static/css/styles.css")
assert response.status_code == 200
content = response.text
# styles.css is now an entry point with @import statements
assert "@import" in content
# Check for imports of base, components, pages, and utilities
assert 'base/' in content or "base" in content.lower()
@pytest.mark.asyncio
async def test_css_variables_file_structure(self, client):
"""Test that base/variables.css has proper structure."""
response = await client.get("/static/css/base/variables.css")
assert response.status_code == 200
content = response.text
# Should have CSS variable definitions
assert ":root" 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 (now just @imports, so smaller)
response = await client.get("/static/css/styles.css")
assert response.status_code == 200
assert len(response.text) > 100, "styles.css seems too small"
assert len(response.text) < 500000, "styles.css seems unusually large"
# Test variables.css (has actual content)
response = await client.get("/static/css/base/variables.css")
assert response.status_code == 200
assert len(response.text) > 500, "variables.css seems too small"
# 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