feat: 新增接口22生发控制与测试页

This commit is contained in:
xsl
2026-11-09 21:19:39 +08:00
parent c800822d54
commit b84a506b9b
21 changed files with 770 additions and 175 deletions
+20 -29
View File
@@ -8,11 +8,7 @@ from conftest import fixture
import app as app_module
# 测试自带固定密码,避免依赖 worker_config.json 的实际值(中间件运行期读模块全局)
app_module.ACCEPT_PASSWORDS = ["testpass"]
URL = "/api/v1/face/measure"
H = {"X-Internal-Token": "testpass"}
@pytest.fixture(scope="module")
@@ -22,18 +18,13 @@ def client():
yield c
def _post(client, fixture_name=None, headers=H, data=None, extra_files=None):
def _post(client, fixture_name=None, data=None, extra_files=None):
files = {}
if fixture_name:
files["image_file"] = (fixture_name, open(fixture(fixture_name), "rb"), "application/octet-stream")
if extra_files:
files.update(extra_files)
return client.post(URL, headers=headers, files=files or None, data=data)
def test_auth_missing_token_401(client):
r = _post(client, "frontal.jpg", headers={})
assert r.status_code == 401
return client.post(URL, files=files or None, data=data)
def _patch_health_ok(monkeypatch):
@@ -107,7 +98,7 @@ def test_tcp_probe_real_socket():
def test_param_none_provided_1007(client):
r = client.post(URL, headers=H)
r = client.post(URL)
assert r.json()["code"] == 1007
@@ -131,7 +122,7 @@ GROW = "/api/v1/hair/grow"
def test_grow_missing_gender_1004(client):
files = {"image_file": ("frontal.jpg", open(fixture("frontal.jpg"), "rb"), "application/octet-stream")}
r = client.post(GROW, headers=H, files=files)
r = client.post(GROW, files=files)
assert r.json()["code"] == 1004
@@ -148,7 +139,7 @@ def test_grow_female_returns_5(client, monkeypatch):
files = {"image_file": ("frontal.jpg", open(fixture("frontal.jpg"), "rb"), "application/octet-stream")}
# hair_style 必填(cb1989c 起):指定全部 5 种发型以验证完整管线
r = client.post(GROW, headers=H, files=files, data={"gender": "female", "hair_style": "1,2,3,4,5"})
r = client.post(GROW, files=files, data={"gender": "female", "hair_style": "1,2,3,4,5"})
body = r.json()
assert body["code"] == 0, body
results = body["data"]["results"]
@@ -163,13 +154,13 @@ GROWB = "/api/v1/hair/grow-b"
def test_growb_missing_marked_1007(client):
r = client.post(GROWB, headers=H) # 一张图都没传
r = client.post(GROWB) # 一张图都没传
assert r.json()["code"] == 1007
def test_growb_no_line_1001(client):
files = {"marked_image_file": ("m.jpg", open(fixture("frontal.jpg"), "rb"), "application/octet-stream")}
r = client.post(GROWB, headers=H, files=files) # 无划线 → 拒识
r = client.post(GROWB, files=files) # 无划线 → 拒识
assert r.json()["code"] == 1001
@@ -177,7 +168,7 @@ def test_growb_success(client, monkeypatch):
import hairline.comfyui as comfy
monkeypatch.setattr(comfy, "run", lambda *a, **k: _PNG_1x1)
files = {"marked_image_file": ("m.jpg", open(fixture("marked_hairline.jpg"), "rb"), "application/octet-stream")}
body = client.post(GROWB, headers=H, files=files).json() # 只传划线图一张
body = client.post(GROWB, files=files).json() # 只传划线图一张
assert body["code"] == 0, body
d = body["data"]
assert d["hairline_type"] == "custom"
@@ -190,7 +181,7 @@ HLGEN = "/api/v1/hairline/generate"
def test_hairline5_restored_schema_has_only_historical_parameters(client):
schema = client.get("/openapi.json", headers=H).json()
schema = client.get("/openapi.json").json()
ref = schema["paths"][HLGEN]["post"]["requestBody"]["content"]["multipart/form-data"]["schema"]["$ref"]
fields = schema["components"]["schemas"][ref.rsplit("/", 1)[-1]]["properties"]
assert set(fields) == {"image_file", "image_url", "image_base64", "gender", "hair_style",
@@ -204,7 +195,7 @@ def test_hairline5_restored_schema_has_only_historical_parameters(client):
def test_hairline5_restored_three_levels_and_original_coordinate_contract(client, gender):
from pathlib import Path
photo = Path(fixture("frontal.jpg")).read_bytes()
body = client.post(HLGEN, headers=H, files={"image_file": ("frontal.jpg", photo, "image/jpeg")},
body = client.post(HLGEN, files={"image_file": ("frontal.jpg", photo, "image/jpeg")},
data={"gender": gender, "hair_style": "1,3", "generate_grow_image": "false"}).json()
assert body["code"] == 0, body
data = body["data"]
@@ -225,13 +216,13 @@ def test_hairline5_restored_three_levels_and_original_coordinate_contract(client
def test_hairline_gen_missing_gender_1004(client):
files = {"image_file": ("frontal.jpg", open(fixture("frontal.jpg"), "rb"), "application/octet-stream")}
assert client.post(HLGEN, headers=H, files=files).json()["code"] == 1004
assert client.post(HLGEN, files=files).json()["code"] == 1004
def test_hairline_gen_missing_hairstyle_1007(client):
# hair_style 已改为必填(同接口2):只给 gender、不给 hair_style → 1007
files = {"image_file": ("frontal.jpg", open(fixture("frontal.jpg"), "rb"), "application/octet-stream")}
assert client.post(HLGEN, headers=H, files=files, data={"gender": "female"}).json()["code"] == 1007
assert client.post(HLGEN, files=files, data={"gender": "female"}).json()["code"] == 1007
def test_hairline_gen_female(client, monkeypatch):
@@ -240,7 +231,7 @@ def test_hairline_gen_female(client, monkeypatch):
monkeypatch.setattr(comfy, "run", lambda *a, **k: _PNG_1x1)
files = {"image_file": ("frontal.jpg", open(fixture("frontal.jpg"), "rb"), "application/octet-stream")}
body = client.post(HLGEN, headers=H, files=files, data={"gender": "female", "hair_style": "1,3"}).json()
body = client.post(HLGEN, files=files, data={"gender": "female", "hair_style": "1,3"}).json()
assert body["code"] == 0, body
d = body["data"]
imgs = d["hairline_images"]
@@ -279,7 +270,7 @@ HLGEN52 = "/api/v1/hairline/generate-52"
def test_hairline52_legacy_form_parameters_and_defaults_are_preserved(client):
schema = client.get("/openapi.json", headers=H).json()
schema = client.get("/openapi.json").json()
body = schema["paths"][HLGEN52]["post"]["requestBody"]["content"]["multipart/form-data"]["schema"]
body = schema["components"]["schemas"][body["$ref"].rsplit("/", 1)[-1]]
fields = body["properties"]
@@ -310,7 +301,7 @@ def test_hairline52_legacy_request_keeps_fields_and_original_coordinates(client,
return _PNG_1x1
monkeypatch.setattr(comfy, "run", generate)
form = {"gender": "male", "hair_style": "1", "use_mask": "false", "prompt": "legacy prompt"}
kwargs = {"headers": H, "data": form}
kwargs = {"data": form}
if image_kind == "file":
kwargs["files"] = {"image_file": ("frontal.jpg", raw, "image/jpeg")}
elif image_kind == "base64":
@@ -385,13 +376,13 @@ def test_hairline52_height_compare_uses_same_new_rule(client, monkeypatch, norma
def test_hairline52_gen_missing_gender_1004(client):
files = {"image_file": ("frontal.jpg", open(fixture("frontal.jpg"), "rb"), "application/octet-stream")}
assert client.post(HLGEN52, headers=H, files=files).json()["code"] == 1004
assert client.post(HLGEN52, files=files).json()["code"] == 1004
def test_hairline52_gen_missing_hairstyle_1007(client):
# hair_style 已改为必填(同接口2):只给 gender、不给 hair_style → 1007
files = {"image_file": ("frontal.jpg", open(fixture("frontal.jpg"), "rb"), "application/octet-stream")}
assert client.post(HLGEN52, headers=H, files=files, data={"gender": "female"}).json()["code"] == 1007
assert client.post(HLGEN52, files=files, data={"gender": "female"}).json()["code"] == 1007
def test_hairline52_gen_female(client, monkeypatch):
@@ -400,7 +391,7 @@ def test_hairline52_gen_female(client, monkeypatch):
monkeypatch.setattr(comfy, "run", lambda *a, **k: _PNG_1x1)
files = {"image_file": ("frontal.jpg", open(fixture("frontal.jpg"), "rb"), "application/octet-stream")}
body = client.post(HLGEN52, headers=H, files=files,
body = client.post(HLGEN52, files=files,
data={"gender": "female", "hair_style": "1,3", "normalize_image": "true"}).json()
assert body["code"] == 0, body
d = body["data"]
@@ -422,7 +413,7 @@ def test_hairline52_gen_female(client, monkeypatch):
assert d["high_hairline_center_point"] is None and d["low_hairline_center_point"] is None
rule = d["height_rule"]
assert rule["target_upper_height_px"] == pytest.approx(
(rule["middle_height_px"] + rule["lower_height_px"]) / 2)
(rule["middle_height_px"] + rule["lower_height_px"]) * 0.45)
for x in imgs:
assert x["height_placement"]["new_center"]["y"] == pytest.approx(rule["target_center"]["y"], abs=1)
assert base64.b64decode(imgs[0]["grown_image_base64"])[:3] == b"\xff\xd8\xff"
@@ -512,6 +503,6 @@ def _assert_vertical_lines(data, variant):
def test_measure_v2_vertical_lines_have_no_head_edges(client):
files = {"image_file": ("frontal.jpg", open(fixture("frontal.jpg"), "rb"), "application/octet-stream")}
body = client.post("/api/v1/face/measure-v2", headers=H, files=files).json()
body = client.post("/api/v1/face/measure-v2", files=files).json()
assert body["code"] == 0, body
_assert_vertical_lines(body["data"], "v6")