Add standardized HTMX conventions, interaction patterns, and migration guide for ThrillWiki UX

This commit is contained in:
pacnpal
2025-12-22 16:56:27 -05:00
parent 2e35f8c5d9
commit ae31e889d7
144 changed files with 25792 additions and 4440 deletions

View File

@@ -0,0 +1,357 @@
"""
Tests for UX component templates.
These tests verify that component templates render correctly
with various parameter combinations.
"""
import pytest
from django.template import Context, Template
from django.test import RequestFactory, override_settings
@pytest.mark.django_db
class TestPageHeaderComponent:
"""Tests for page_header.html component."""
def test_renders_title(self):
"""Should render title text."""
template = Template(
"""
{% include 'components/layout/page_header.html' with title='Test Title' %}
"""
)
html = template.render(Context({}))
assert "Test Title" in html
def test_renders_subtitle(self):
"""Should render subtitle when provided."""
template = Template(
"""
{% include 'components/layout/page_header.html' with
title='Title'
subtitle='Subtitle text'
%}
"""
)
html = template.render(Context({}))
assert "Subtitle text" in html
def test_renders_icon(self):
"""Should render icon when provided."""
template = Template(
"""
{% include 'components/layout/page_header.html' with
title='Title'
icon='fas fa-star'
%}
"""
)
html = template.render(Context({}))
assert "fas fa-star" in html
def test_renders_primary_action(self):
"""Should render primary action button."""
template = Template(
"""
{% include 'components/layout/page_header.html' with
title='Title'
primary_action_url='/create/'
primary_action_text='Create'
%}
"""
)
html = template.render(Context({}))
assert "Create" in html
assert "/create/" in html
@pytest.mark.django_db
class TestActionBarComponent:
"""Tests for action_bar.html component."""
def test_renders_primary_action(self):
"""Should render primary action button."""
template = Template(
"""
{% include 'components/ui/action_bar.html' with
primary_action_text='Save'
primary_action_url='/save/'
%}
"""
)
html = template.render(Context({}))
assert "Save" in html
assert "/save/" in html
def test_renders_secondary_action(self):
"""Should render secondary action button."""
template = Template(
"""
{% include 'components/ui/action_bar.html' with
secondary_action_text='Preview'
%}
"""
)
html = template.render(Context({}))
assert "Preview" in html
def test_renders_tertiary_action(self):
"""Should render tertiary action button."""
template = Template(
"""
{% include 'components/ui/action_bar.html' with
tertiary_action_text='Cancel'
tertiary_action_url='/back/'
%}
"""
)
html = template.render(Context({}))
assert "Cancel" in html
assert "/back/" in html
def test_alignment_classes(self):
"""Should apply correct alignment classes."""
template = Template(
"""
{% include 'components/ui/action_bar.html' with
align='between'
primary_action_text='Save'
%}
"""
)
html = template.render(Context({}))
assert "justify-between" in html
@pytest.mark.django_db
class TestSkeletonComponents:
"""Tests for skeleton screen components."""
def test_list_skeleton_renders(self):
"""Should render list skeleton with specified rows."""
template = Template(
"""
{% include 'components/skeletons/list_skeleton.html' with rows=3 %}
"""
)
html = template.render(Context({}))
assert "animate-pulse" in html
def test_card_grid_skeleton_renders(self):
"""Should render card grid skeleton."""
template = Template(
"""
{% include 'components/skeletons/card_grid_skeleton.html' with cards=4 %}
"""
)
html = template.render(Context({}))
assert "animate-pulse" in html
def test_detail_skeleton_renders(self):
"""Should render detail skeleton."""
template = Template(
"""
{% include 'components/skeletons/detail_skeleton.html' %}
"""
)
html = template.render(Context({}))
assert "animate-pulse" in html
def test_form_skeleton_renders(self):
"""Should render form skeleton."""
template = Template(
"""
{% include 'components/skeletons/form_skeleton.html' with fields=3 %}
"""
)
html = template.render(Context({}))
assert "animate-pulse" in html
def test_table_skeleton_renders(self):
"""Should render table skeleton."""
template = Template(
"""
{% include 'components/skeletons/table_skeleton.html' with rows=5 columns=4 %}
"""
)
html = template.render(Context({}))
assert "animate-pulse" in html
@pytest.mark.django_db
class TestModalComponents:
"""Tests for modal components."""
def test_modal_base_renders(self):
"""Should render modal base structure."""
template = Template(
"""
{% include 'components/modals/modal_base.html' with
modal_id='test-modal'
show_var='showModal'
title='Test Modal'
%}
"""
)
html = template.render(Context({}))
assert "test-modal" in html
assert "Test Modal" in html
assert "showModal" in html
def test_modal_confirm_renders(self):
"""Should render confirmation modal."""
template = Template(
"""
{% include 'components/modals/modal_confirm.html' with
modal_id='confirm-modal'
show_var='showConfirm'
title='Confirm Action'
message='Are you sure?'
confirm_text='Yes'
%}
"""
)
html = template.render(Context({}))
assert "confirm-modal" in html
assert "Confirm Action" in html
assert "Are you sure?" in html
assert "Yes" in html
def test_modal_confirm_destructive_variant(self):
"""Should apply destructive styling."""
template = Template(
"""
{% include 'components/modals/modal_confirm.html' with
modal_id='delete-modal'
show_var='showDelete'
title='Delete'
message='Delete this item?'
confirm_variant='destructive'
%}
"""
)
html = template.render(Context({}))
assert "btn-destructive" in html
@pytest.mark.django_db
class TestBreadcrumbComponent:
"""Tests for breadcrumb component."""
def test_renders_breadcrumbs(self):
"""Should render breadcrumb navigation."""
template = Template(
"""
{% include 'components/navigation/breadcrumbs.html' %}
"""
)
breadcrumbs = [
{"label": "Home", "url": "/", "is_current": False},
{"label": "Parks", "url": "/parks/", "is_current": False},
{"label": "Test Park", "url": None, "is_current": True},
]
html = template.render(Context({"breadcrumbs": breadcrumbs}))
assert "Home" in html
assert "Parks" in html
assert "Test Park" in html
def test_renders_schema_org_markup(self):
"""Should include Schema.org BreadcrumbList."""
template = Template(
"""
{% include 'components/navigation/breadcrumbs.html' %}
"""
)
breadcrumbs = [
{"label": "Home", "url": "/", "is_current": False, "schema_position": 1},
{"label": "Test", "url": None, "is_current": True, "schema_position": 2},
]
html = template.render(Context({"breadcrumbs": breadcrumbs}))
assert "BreadcrumbList" in html
def test_empty_breadcrumbs(self):
"""Should handle empty breadcrumbs gracefully."""
template = Template(
"""
{% include 'components/navigation/breadcrumbs.html' %}
"""
)
html = template.render(Context({"breadcrumbs": []}))
# Should not error, may render nothing or empty nav
assert html is not None
@pytest.mark.django_db
class TestStatusBadgeComponent:
"""Tests for status badge component."""
def test_renders_status_text(self):
"""Should render status label."""
template = Template(
"""
{% include 'components/status_badge.html' with status='published' label='Published' %}
"""
)
html = template.render(Context({}))
assert "Published" in html
def test_applies_status_colors(self):
"""Should apply appropriate color classes for status."""
# Test published/active status
template = Template(
"""
{% include 'components/status_badge.html' with status='published' %}
"""
)
html = template.render(Context({}))
# Should have some indication of success/green styling
assert "green" in html.lower() or "success" in html.lower() or "published" in html.lower()
@pytest.mark.django_db
class TestLoadingIndicatorComponent:
"""Tests for loading indicator component."""
def test_renders_loading_indicator(self):
"""Should render loading indicator."""
template = Template(
"""
{% include 'htmx/components/loading_indicator.html' with text='Loading...' %}
"""
)
html = template.render(Context({}))
assert "Loading" in html
def test_renders_with_id(self):
"""Should render with specified ID for htmx-indicator."""
template = Template(
"""
{% include 'htmx/components/loading_indicator.html' with id='my-loader' %}
"""
)
html = template.render(Context({}))
assert "my-loader" in html