"""Import ADR-0004 tree into content plane (CSOC-WP-0001-T04 rehearsal path).""" from pathlib import Path import pytest from django.core.management import call_command from coulomb_social.apps.members.models import Member, User from coulomb_social.apps.spaces import pageops from coulomb_social.apps.spaces.content import load_space_page from coulomb_social.apps.spaces.import_tree import import_space_tree from coulomb_social.apps.spaces.models import Space, SpaceMembership @pytest.fixture def content_root(tmp_path, settings): root = tmp_path / "content" settings.CONTENT_ROOT = str(root) return root def _write_sample_tree(root: Path) -> Path: tree = root / "sample-space" pages = tree / "pages" assets = tree / "assets" pages.mkdir(parents=True) assets.mkdir(parents=True) (pages / "index.md").write_text( "---\n" 'title: "Sample Space"\n' 'abstractor: "From export"\n' 'visual: ""\n' 'space: "sample-space"\n' "bubble_type: space\n" "---\n\n" "# Sample Space\n\nLanding.\n", encoding="utf-8", ) (pages / "notes.md").write_text( "---\n" 'title: "Notes"\n' 'abstractor: "Scratch"\n' 'visual: "assets/notes-visual.png"\n' 'space: "sample-space"\n' "bubble_type: article\n" "---\n\n" "# Notes\n\nBody text.\n", encoding="utf-8", ) (assets / "notes-visual.png").write_bytes(b"\x89PNG\r\n") return tree @pytest.mark.django_db def test_import_space_tree(content_root, tmp_path): tree = _write_sample_tree(tmp_path / "export") user = User.objects.create_user(username="imp") member = Member.objects.create( tenant_id="tenant:a", user=user, user_engine_user_id="usr_imp", issuer="https://local.dev/issuer", subject="imp-sub", display_name="Importer", ) report = import_space_tree( tree, tenant_id="tenant:a", member=member, ) assert report.pages_copied == 2 assert report.assets_copied == 1 assert report.space_created space = Space.objects.get(tenant_id="tenant:a", slug="sample-space") assert space.title == "Sample Space" assert space.description == "From export" assert SpaceMembership.objects.filter(space=space, member=member).exists() notes = pageops.read_page("sample-space", "notes") assert notes.exists assert notes.title == "Notes" assert "Body text" in notes.body assert (pageops.space_dir("sample-space") / "assets" / "notes-visual.png").is_file() rendered = load_space_page(space, "notes") assert rendered.error is None assert rendered.source == "content-plane" assert "Body text" in rendered.html @pytest.mark.django_db def test_import_refuses_overwrite_without_replace(content_root, tmp_path): tree = _write_sample_tree(tmp_path / "export") import_space_tree(tree, tenant_id="tenant:a") with pytest.raises(pageops.PageOpsError): import_space_tree(tree, tenant_id="tenant:a", replace=False) report = import_space_tree(tree, tenant_id="tenant:a", replace=True) assert report.space_updated or report.space_created assert report.pages_copied == 2 @pytest.mark.django_db def test_import_content_tree_command(content_root, tmp_path, capsys): tree = _write_sample_tree(tmp_path / "export") call_command("import_content_tree", str(tree), "--tenant", "tenant:cmd", "--dry-run") out = capsys.readouterr().out assert "Dry run" in out assert not Space.objects.filter(slug="sample-space").exists() call_command( "import_content_tree", str(tree), "--tenant", "tenant:cmd", "--slug", "cmd-space", ) space = Space.objects.get(slug="cmd-space", tenant_id="tenant:cmd") assert space.title == "Sample Space" assert pageops.read_page("cmd-space", "index").exists