"""SSR tests for the Muse Hub new repo creation wizard (issue #562).
Validates that the wizard form is rendered server-side via Jinja2 — license
options, form inputs, and HTMX attributes appear in the raw HTML response
without requiring JavaScript execution. Also validates that the availability
check endpoint returns an HTML fragment when called by HTMX.
Covers:
- test_new_repo_page_renders_license_options_server_side — license in HTML
- test_new_repo_page_has_hx_get_on_name_input — name input has hx-get attribute
- test_new_repo_page_has_visibility_inputs — Public/Private radio inputs in HTML
- test_new_repo_page_form_renders_without_js — form element in SSR HTML
- test_new_repo_page_has_hx_indicator_on_name_input — hx-indicator attribute present
- test_new_repo_page_has_name_check_indicator_span — indicator span exists in HTML
- test_new_repo_name_check_htmx_returns_available_html — HTMX → HTML span "Available"
- test_new_repo_name_check_htmx_returns_taken_html — HTMX → HTML span "taken"
- test_new_repo_name_check_json_path_unchanged — no HX-Request → JSON response
"""
from __future__ import annotations
import pytest
from httpx import AsyncClient
from sqlalchemy.ext.asyncio import AsyncSession
from musehub.db.musehub_models import MusehubRepo
# ---------------------------------------------------------------------------
# Seed helper
# ---------------------------------------------------------------------------
async def _seed_repo(
db: AsyncSession,
owner: str = "existingowner",
slug: str = "taken-repo",
) -> None:
"""Seed a public repo so the slug appears as taken in check requests."""
repo = MusehubRepo(
name=slug,
owner=owner,
slug=slug,
visibility="public",
owner_user_id="seed-uid",
)
db.add(repo)
await db.commit()
# ---------------------------------------------------------------------------
# Tests — SSR form verification
# ---------------------------------------------------------------------------
@pytest.mark.anyio
async def test_new_repo_page_renders_license_options_server_side(
client: AsyncClient,
db_session: AsyncSession,
) -> None:
"""License elements are server-rendered in the HTML response.
Confirms the license dropdown is Jinja2-rendered from the ``licenses``
context variable, not built by client-side JavaScript.
"""
response = await client.get("/musehub/ui/new")
assert response.status_code == 200
body = response.text
# CC BY license option must appear as a real tag in the raw HTML
assert " None:
"""The repository name input has an hx-get attribute pointing to /new/check.
This drives the live HTMX availability check without client JS polling.
"""
response = await client.get("/musehub/ui/new")
assert response.status_code == 200
body = response.text
assert "hx-get" in body
assert "/musehub/ui/new/check" in body
@pytest.mark.anyio
async def test_new_repo_page_has_visibility_inputs(
client: AsyncClient,
db_session: AsyncSession,
) -> None:
"""Public and Private visibility radio inputs are in the server-rendered HTML."""
response = await client.get("/musehub/ui/new")
assert response.status_code == 200
body = response.text
assert 'value="public"' in body
assert 'value="private"' in body
@pytest.mark.anyio
async def test_new_repo_page_form_renders_without_js(
client: AsyncClient,
db_session: AsyncSession,
) -> None:
"""A