"""结构化丰富模块测试:竞赛表单、技能/证书标签、联系方式、跳过、稍后再说。""" from __future__ import annotations from typing import Any from fastapi.testclient import TestClient from test_api import BASE, active_component, campus_ready, event def created_session(client: TestClient) -> tuple[str, dict[str, Any]]: session_id, _ = campus_ready(client) response = client.post(f"{BASE}/sessions/{session_id}/create", json={}) assert response.status_code == 200, response.text return session_id, response.json() def find_component(body: dict[str, Any], slug: str) -> dict[str, Any]: turns = body.get("turns") or ([body["turn"]] if body.get("turn") else []) for turn in reversed(turns): for block in reversed(turn["blocks"]): if block["type"] == "component" and block["data"].get("component") == slug: return block raise AssertionError(f"component {slug} not found") def submit_to( client: TestClient, session_id: str, body: dict[str, Any], slug: str, payload: dict[str, Any], event_name: str = "submit", ): block = find_component(body, slug) return client.post( f"{BASE}/sessions/{session_id}/component-events", json={"component_id": block["id"], "event": event_name, "payload": payload}, ) def continue_enriching(client: TestClient, session_id: str, body: dict[str, Any]) -> dict[str, Any]: response = event(client, session_id, body, "continue_enriching") assert response.status_code == 200, response.text return response.json() def skip_current(client: TestClient, session_id: str, body: dict[str, Any]) -> dict[str, Any]: response = event(client, session_id, body, "skip") assert response.status_code == 200, response.text return response.json() def test_competition_fields_validation(client: TestClient): session_id, body = created_session(client) body = continue_enriching(client, session_id, body) assert active_component(body)["data"]["component"] == "record_fields" assert active_component(body)["data"]["module"] == "internship" body = skip_current(client, session_id, body) # → project assert active_component(body)["data"]["module"] == "project" body = skip_current(client, session_id, body) # → competition assert active_component(body)["data"]["component"] == "competition_fields" bad_date = submit_to( client, session_id, body, "competition_fields", {"name": "蓝桥杯", "award": "二等奖", "date": "2024-13"}, ) assert bad_date.status_code == 422 missing_award = submit_to( client, session_id, body, "competition_fields", {"name": "蓝桥杯", "award": "", "date": "2024-04"}, ) assert missing_award.status_code == 422 ok = submit_to( client, session_id, body, "competition_fields", { "name": "蓝桥杯", "award": "二等奖", "date": "2024-04", "description": "使用 Python 完成算法题训练,获得省级二等奖。", }, ) assert ok.status_code == 200, ok.text body = ok.json() card = active_component(body) assert card["data"]["component"] == "experience_confirm_card" assert card["data"]["ai_proposal"]["optimized_description"] == ( "基于 Python 完成算法题训练,并获得省级二等奖。" ) confirmed = event( client, session_id, body, "confirm", {"confirmed": True, "use_optimized": True}, ) assert confirmed.status_code == 200, confirmed.text body = confirmed.json() assert active_component(body)["data"]["component"] == "add_another" nxt = event(client, session_id, body, "select", {"value": "next"}) assert nxt.status_code == 200, nxt.text assert nxt.json()["stage"] == "RESUME_ENRICHING" def test_skills_and_certificates_are_independent_modules(client: TestClient): session_id, body = created_session(client) body = continue_enriching(client, session_id, body) for _ in range(3): body = skip_current(client, session_id, body) block = active_component(body) assert block["data"]["component"] == "tags_input" assert block["data"]["module"] == "skills" assert block["data"]["field"] == "skills" assert block["data"]["suggestions"] # 按意向职位推荐 body = submit_to( client, session_id, body, "tags_input", {"field": "skills", "value": [" Python ", "python", "FastAPI"]}, ).json() # 技能提交后立即进入独立的证书模块,进度条已完成数 +1 block = active_component(body) assert block["data"]["component"] == "tags_input" assert block["data"]["module"] == "certificates" assert block["data"]["field"] == "certificates" progress = find_component(body, "progress_card") assert progress["data"]["module"] == "certificates" assert progress["data"]["completed"] == 1 body = submit_to( client, session_id, body, "tags_input", {"field": "certificates", "value": []}, ).json() assert body["stage"] == "RESUME_ENRICHING" assert active_component(body)["data"]["component"] == "custom_card_picker" body = event(client, session_id, body, "select", {"value": "finish"}).json() assert body["stage"] == "CONTENT_READY" def test_defer_exits_and_resumes_at_breakpoint(client: TestClient): session_id, body = created_session(client) body = continue_enriching(client, session_id, body) response = event(client, session_id, body, "defer") assert response.status_code == 200, response.text body = response.json() assert body["stage"] == "CONTENT_READY" assert active_component(body)["data"]["component"] == "content_ready_card" body = continue_enriching(client, session_id, body) assert body["stage"] == "RESUME_ENRICHING" assert active_component(body)["data"]["component"] == "record_fields" assert active_component(body)["data"]["module"] == "internship"