"""浏览器将使用的真实作者会话、作品和正文HTTP入口。""" import pytest from fastapi.testclient import TestClient from muse.共享.调用身份 import 用途 from muse.接入.http.应用 import 创建应用 from muse.配置 import 应用配置, 服务配置 pytestmark = pytest.mark.数据库 @pytest.mark.case_id( "NC-work-http-manual", environment="隔离PostgreSQL与真实ASGI", given="隔离PG内置结构和真实单作者会话", when="经HTTP创建作品、章节,保存重开并回退正文", then=["身份来自会话,中文原文与版本正确,重复命令返回原回执,回退追加版本"], contract="docs/系统架构/新版设计/接口契约/命令与作者决策.md", ) def test_HTTP创建作品到保存中文正文并拒绝伪身份__aa1301(内置结构测试库, tmp_path): 应用测试库 = 内置结构测试库 口令 = tmp_path / "作者口令.txt" 口令.write_text("synthetic-author-access") 配置 = 应用配置( 应用测试库[用途.生产].引用, "test", HTTP=服务配置( str(口令), 作者ID="author", 公开地址="http://testserver", 允许来源=("http://testserver",), ), ) with TestClient(创建应用(配置)) as client: client.headers["Origin"] = "http://testserver" assert client.get("/api/v1/works").status_code == 401 assert ( client.post("/api/v1/session", json={"password": "synthetic-author-access"}).status_code == 200 ) form = client.get( "/api/v1/works/http-work/form", params={"schema_id": "work_core", "base_version": 1} ) assert form.status_code == 200, form.text body = { "command_id": "create-http", "work_id": "http-work", "expected_revision": 0, "schema_binding": form.json()["schema_binding"], "changes": [{"路径": ["名称"], "动作": "set", "值": "浏览器新故事"}], } assert ( client.post( "/api/v1/works/http-work/profile", json={**body, "author_id": "other"} ).status_code == 422 ) assert client.post("/api/v1/works/http-work/profile", json=body).status_code == 200 assert client.get("/api/v1/works").json()[0]["work_id"] == "http-work" chapter = { "command_id": "new-chapter", "work_id": "http-work", "chapter_id": "http-chapter", "title": "开篇", "expected_directory_revision": 0, } assert client.post("/api/v1/works/http-work/chapters", json=chapter).status_code == 200 draft = { "format_version": 1, "paragraphs": [ { "paragraph_id": "http-p1", "content": [{"type": "text", "text": " “正文”e\u0301🧑‍🏽", "marks": []}], } ], } save = { "command_id": "http-save", "chapter_id": "http-chapter", "expected_revision": 0, "document": draft, } reply = client.post("/api/v1/chapters/http-chapter/documents", json=save) assert reply.status_code == 200, reply.text assert ( client.post("/api/v1/chapters/http-chapter/documents", json=save).json() == reply.json() ) loaded = client.get("/api/v1/chapters/http-chapter/documents").json() assert loaded["revision"] == 1 and loaded["visible_text"] == " “正文”e\u0301🧑‍🏽" history = client.get("/api/v1/chapters/http-chapter/documents/history") assert history.status_code == 200, history.text assert [v["revision"] for v in history.json()] == [1] restored = client.post( "/api/v1/chapters/http-chapter/documents/restore", json={ "chapter_id": "http-chapter", "command_id": "restore-http", "expected_revision": 1, "restore_from": 1, }, ) assert restored.status_code == 200, restored.text latest = client.get("/api/v1/chapters/http-chapter/documents").json() assert latest["revision"] == 2 and latest["document"] == loaded["document"] assert latest["work_id"] == "http-work"