M2b:导入改造产出可审阅灵胚(启镜物化世谱)与组装管线(符文展开/火候进入 IR),Kernel 打通采样参数链路
This commit is contained in:
1 parent
e6a3b7121f
commit
5f36e3785c
86 files changed
+424
-14455
No files matched your search
@@ -1,97 +0,0 @@
|
||||
"""角色卡导入 API 测试。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import json
|
||||
import struct
|
||||
import zlib
|
||||
|
||||
import httpx
|
||||
|
||||
|
||||
def _make_png_text(keyword: str, text: str) -> bytes:
|
||||
def chunk(ctype: bytes, data: bytes) -> bytes:
|
||||
body = ctype + data
|
||||
return struct.pack(">I", len(data)) + body + struct.pack(">I", zlib.crc32(body) & 0xFFFFFFFF)
|
||||
|
||||
payload = keyword.encode("latin-1") + b"\x00" + text.encode("latin-1")
|
||||
return b"\x89PNG\r\n\x1a\n" + chunk(b"tEXt", payload) + chunk(b"IEND", b"")
|
||||
|
||||
|
||||
async def test_import_json_card(auth_client: httpx.AsyncClient) -> None:
|
||||
card = {"spec_version": "2.0", "data": {"name": "API卡", "personality": "p"}}
|
||||
resp = await auth_client.post(
|
||||
"/api/v1/characters/import-card",
|
||||
files={"file": ("card.json", json.dumps(card).encode("utf-8"), "application/json")},
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert data["name"] == "API卡"
|
||||
assert data["character_id"].startswith("character_")
|
||||
|
||||
|
||||
async def test_import_png_card(auth_client: httpx.AsyncClient) -> None:
|
||||
card = {"spec_version": "2.0", "data": {"name": "PNG卡"}}
|
||||
text = base64.b64encode(json.dumps(card).encode("utf-8")).decode("ascii")
|
||||
resp = await auth_client.post(
|
||||
"/api/v1/characters/import-card",
|
||||
files={"file": ("card.png", _make_png_text("chara", text), "image/png")},
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["name"] == "PNG卡"
|
||||
|
||||
|
||||
async def test_import_card_with_lorebook(auth_client: httpx.AsyncClient) -> None:
|
||||
card = {
|
||||
"spec_version": "2.0",
|
||||
"data": {
|
||||
"name": "带书",
|
||||
"character_book": {"entries": [{"keys": ["a"], "content": "b"}]},
|
||||
},
|
||||
}
|
||||
resp = await auth_client.post(
|
||||
"/api/v1/characters/import-card",
|
||||
files={"file": ("card.json", json.dumps(card).encode("utf-8"), "application/json")},
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert data["lorebook_id"] is not None
|
||||
assert data["entry_count"] == 1
|
||||
# 导入的人物可被列出
|
||||
listed = await auth_client.get("/api/v1/characters")
|
||||
assert any(c["id"] == data["character_id"] for c in listed.json()["items"])
|
||||
|
||||
|
||||
async def test_export_card_round_trip(auth_client: httpx.AsyncClient) -> None:
|
||||
# 导入一张带世谱的卡
|
||||
card = {
|
||||
"spec_version": "2.0",
|
||||
"data": {
|
||||
"name": "往返",
|
||||
"nickname": "返返",
|
||||
"personality": "p",
|
||||
"character_book": {"entries": [{"keys": ["k"], "content": "v"}]},
|
||||
},
|
||||
}
|
||||
imp = await auth_client.post(
|
||||
"/api/v1/characters/import-card",
|
||||
files={"file": ("c.json", json.dumps(card).encode("utf-8"), "application/json")},
|
||||
)
|
||||
assert imp.status_code == 200
|
||||
cid = imp.json()["character_id"]
|
||||
|
||||
# 导出
|
||||
exp = await auth_client.get(f"/api/v1/characters/{cid}/export-card")
|
||||
assert exp.status_code == 200
|
||||
exported = exp.json()
|
||||
assert exported["spec"] == "chara_card_v3"
|
||||
assert exported["data"]["name"] == "往返"
|
||||
assert exported["data"]["nickname"] == "返返"
|
||||
assert exported["data"]["personality"] == "p"
|
||||
assert exported["data"]["character_book"]["entries"][0]["keys"] == ["k"]
|
||||
|
||||
|
||||
async def test_export_unknown_character_404(auth_client: httpx.AsyncClient) -> None:
|
||||
exp = await auth_client.get("/api/v1/characters/character_missing/export-card")
|
||||
assert exp.status_code == 404
|
||||
Reference in new issue
Block a user