Thin CONTENT_ROOT content plane (ADR-0003/0004) with space visual field, product UI for Title/Abstract/Visual, page list sidebar, and tests. Update capability model and smoke checklist; mark WP-0006 finished.
113 lines
3.4 KiB
Python
113 lines
3.4 KiB
Python
from unittest.mock import patch
|
|
|
|
import pytest
|
|
from django.urls import reverse
|
|
|
|
from coulomb_social.apps.members.models import Member
|
|
from coulomb_social.apps.spaces.content import clear_content_cache, load_space_page, render_markdown
|
|
from coulomb_social.apps.spaces.forgejo import ContentFetchError, FetchedFile
|
|
from coulomb_social.apps.spaces.models import Space
|
|
|
|
|
|
def test_render_markdown_strips_script():
|
|
html = render_markdown("# Hi\n\n<script>alert(1)</script>\n\n**bold**")
|
|
assert "<script>" not in html
|
|
assert "bold" in html
|
|
assert "Hi" in html
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_load_space_page_unbound(tmp_path, settings):
|
|
settings.CONTENT_ROOT = str(tmp_path / "empty-content")
|
|
space = Space(tenant_id="t", slug="x", title="X")
|
|
page = load_space_page(space)
|
|
assert page.error
|
|
err = page.error.lower()
|
|
assert "content plane" in err or "not bound" in err or "forgejo" in err
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_load_space_page_fetches_and_renders():
|
|
clear_content_cache()
|
|
space = Space(
|
|
tenant_id="t",
|
|
slug="demo",
|
|
title="Demo",
|
|
forgejo_owner="coulomb",
|
|
forgejo_repo="coulomb-social",
|
|
default_branch="main",
|
|
content_root="docs/space-fixtures/demo/pages",
|
|
)
|
|
fake = FetchedFile(
|
|
path="docs/space-fixtures/demo/pages/index.md",
|
|
text="# Hello demo\n\nParagraph.\n",
|
|
source="forgejo-raw",
|
|
)
|
|
with patch(
|
|
"coulomb_social.apps.spaces.content.fetch_raw_file", return_value=fake
|
|
) as mocked:
|
|
page = load_space_page(space, "index")
|
|
mocked.assert_called_once()
|
|
assert page.error is None
|
|
assert page.title == "Hello demo"
|
|
assert "Paragraph" in page.html
|
|
assert page.source == "forgejo-raw"
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_load_space_page_fail_closed():
|
|
clear_content_cache()
|
|
space = Space(
|
|
tenant_id="t",
|
|
slug="demo",
|
|
title="Demo",
|
|
forgejo_owner="o",
|
|
forgejo_repo="r",
|
|
content_root="pages",
|
|
)
|
|
with patch(
|
|
"coulomb_social.apps.spaces.content.fetch_raw_file",
|
|
side_effect=ContentFetchError("File not found: pages/index.md", status_code=404),
|
|
):
|
|
page = load_space_page(space)
|
|
assert page.error
|
|
assert "not found" in page.error.lower()
|
|
assert page.html == ""
|
|
|
|
|
|
@pytest.mark.django_db
|
|
def test_space_detail_renders_content(client, settings):
|
|
clear_content_cache()
|
|
settings.DEBUG = True
|
|
settings.OIDC_ENABLED = False
|
|
client.post(
|
|
reverse("identity:dev_login"),
|
|
{
|
|
"subject": "reader",
|
|
"issuer": "https://local.dev/issuer",
|
|
"name": "Reader",
|
|
"tenant": "tenant:coulomb",
|
|
},
|
|
)
|
|
member = Member.objects.get(subject="reader")
|
|
Space.objects.create(
|
|
tenant_id="tenant:coulomb",
|
|
slug="demo",
|
|
title="Demo",
|
|
created_by=member,
|
|
forgejo_owner="coulomb",
|
|
forgejo_repo="coulomb-social",
|
|
content_root="docs/space-fixtures/demo/pages",
|
|
)
|
|
fake = FetchedFile(
|
|
path="docs/space-fixtures/demo/pages/index.md",
|
|
text="# From Forgejo\n\nVisible body.\n",
|
|
source="forgejo-raw",
|
|
)
|
|
with patch(
|
|
"coulomb_social.apps.spaces.content.fetch_raw_file", return_value=fake
|
|
):
|
|
r = client.get(reverse("spaces:detail", kwargs={"slug": "demo"}))
|
|
assert r.status_code == 200
|
|
assert b"From Forgejo" in r.content
|
|
assert b"Visible body" in r.content
|