Import Bubble export trees into PageOps and finish CSOC-WP-0001
Add import_content_tree management command and import_tree helper for ADR-0004 sample trees. Document reichelag rehearsal lossiness; mark T02/T04 and the bubble exit workplan finished.
This commit is contained in:
parent
affed64839
commit
8447943dc0
6 changed files with 523 additions and 35 deletions
121
tests/test_import_tree.py
Normal file
121
tests/test_import_tree.py
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
"""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
|
||||
Loading…
Add table
Add a link
Reference in a new issue