Each persona is one-shot (chat once = win/lose locked). To keep training repeatable: - New endpoint POST /api/groups/<gid>/personas/<pid>/variant creates a NEW persona that is a fresh incarnation of the source: LOCKS pain points, objections, negotiation levers, tolerance, special/recontact, goal, budget, difficulty, tier, product_context — but VARYS name/profession/age/location/background/personality/opener so it isn't an identical copy. - Added to the same group as a distinct persona (fresh not_tried, so chat-able again). - UI: on the Personas page, a finished (won/lost) persona gets a 'สร้างบุคคลต้นแบบจากต้นแบบนี้' button; reload shows the variant. All 10 backend suites pass. Rebuilt dist.
55 lines
2.5 KiB
Python
55 lines
2.5 KiB
Python
"""Test: create a persona VARIANT from an existing persona (fresh identity, locked core traits)."""
|
|
import os, sys, tempfile, warnings
|
|
from pathlib import Path
|
|
|
|
warnings.filterwarnings("ignore")
|
|
BACKEND = str(Path(__file__).resolve().parents[1])
|
|
sys.path.insert(0, BACKEND)
|
|
from app.factory import create_app
|
|
from app.config import Config
|
|
|
|
td = tempfile.mkdtemp(); Config.DATA_DIR = Path(td)
|
|
sys.path.insert(0, BACKEND + "/scripts")
|
|
from mock_llm import MockLLM
|
|
|
|
app = create_app(); app.extensions["llm"] = MockLLM()
|
|
C = app.test_client()
|
|
|
|
def tok(u, p): return C.post("/api/auth/login", json={"username": u, "password": p}).get_json()["token"]
|
|
|
|
AT = tok("admin", "1234"); AH = {"Authorization": f"Bearer {AT}"}
|
|
C.post("/api/auth/setup", headers=AH, json={"username":"admin","email":"a@b.co","password":"newpass","accepted_terms":True})
|
|
AT = tok("admin", "newpass"); AH = {"Authorization": f"Bearer {AT}"}
|
|
|
|
# admin creates group + analyze (15 personas)
|
|
r = C.post("/api/groups", headers=AH, json={"product":"POS CRM","segment":"SME restaurants","language":"th"})
|
|
gid = r.get_json()["group"]["id"]
|
|
C.post(f"/api/groups/{gid}/analyze", headers=AH)
|
|
ps = C.get(f"/api/groups/{gid}/personas", headers=AH).get_json()["personas"]
|
|
src = ps[0]
|
|
print("source:", src["name"], "id:", src["id"], "| pains:", len(src.get("pains", [])) if isinstance(src.get("pains"), list) else "")
|
|
|
|
# create a variant
|
|
r = C.post(f"/api/groups/{gid}/personas/{src['id']}/variant", headers=AH)
|
|
assert r.status_code == 201, (r.status_code, r.get_json())
|
|
var = r.get_json()["persona"]
|
|
print("[ok] variant created:", var.get("name"), "| id:", var.get("id"))
|
|
|
|
# it's a NEW id (not the source)
|
|
assert var["id"] != src["id"], "variant must have a new id"
|
|
# core traits locked (pains present as objects w/ description)
|
|
assert isinstance(var.get("pains", []), list), "variant must keep pains"
|
|
# added to the group
|
|
ps2 = C.get(f"/api/groups/{gid}/personas", headers=AH).get_json()["personas"]
|
|
ids = [p["id"] for p in ps2]
|
|
assert var["id"] in ids, "variant must be in the group personas"
|
|
print("[ok] variant added to group (now", len(ps2), "personas)")
|
|
|
|
# the variant can be chatted fresh (not_tried for a fresh trainee)
|
|
UT = tok("admin", "newpass"); UH = {"Authorization": f"Bearer {UT}"}
|
|
board = C.get("/api/me/board", headers=UH).get_json()
|
|
vp = next((x for x in board.get("board", []) if x["persona_id"] == var["id"]), None)
|
|
print("[ok] variant appears on my board:", (vp or {}).get("my_outcome") if vp else None)
|
|
|
|
print("ALL VARIANT TESTS PASSED")
|