from __future__ import annotations from typing import Any from fastapi.testclient import TestClient from app.models import JobType from test_api import ANCHOR_CARD_VALUES, BASE, active_component, event, fill_anchor, start_manual_profile from test_enrichment_flow import find_component, submit_to from test_enrichment_records import confirm_active, latest_patch def _reach_job_type(client: TestClient) -> tuple[str, dict[str, Any]]: body = client.post(f"{BASE}/sessions", json={}).json() session_id = body["session_id"] body = event(client, session_id, body, "accept", {"accepted": True}).json() body = event(client, session_id, body, "select", {"value": "manual"}).json() body = event(client, session_id, body, "select", {"source": "other"}).json() body = event(client, session_id, body, "submit", {"phone": "13800138000"}).json() body = event( client, session_id, body, "submit", {"name": "娴嬭瘯鐢ㄦ埛", "email": "user@example.com"}, ).json() return session_id, body def _created_internship_session(client: TestClient) -> tuple[str, dict[str, Any]]: session_id, body = start_manual_profile(client, job_type="internship") assert body["stage"] == "ANCHOR_COLLECTING" assert body["gate"]["anchor_type"] == "education" body = fill_anchor(client, session_id, body, dict(ANCHOR_CARD_VALUES)) body = confirm_active(client, session_id, body) response = client.post(f"{BASE}/sessions/{session_id}/create", json={}) assert response.status_code == 200, response.text return session_id, response.json() def _select_custom_card( client: TestClient, session_id: str, body: dict[str, Any], value: str ) -> dict[str, Any]: response = event(client, session_id, body, "select", {"value": value}) assert response.status_code == 200, response.text return response.json() def test_job_types_are_campus_social_and_internship(client: TestClient) -> None: assert [item.value for item in JobType] == ["campus", "social", "internship"] session_id, body = _reach_job_type(client) options = active_component(body)["data"]["options"] assert options == ["campus", "social", "internship"] rejected = event(client, session_id, body, "select", {"job_type": "other"}) assert rejected.status_code == 422 assert rejected.json()["error"]["code"] == "invalid_job_type" def test_legacy_other_session_is_migrated_when_its_timeline_is_read( client: TestClient, ) -> None: created = client.post(f"{BASE}/sessions", json={}) assert created.status_code == 201 session_id = created.json()["session_id"] database = client.app.state.database with database.transaction(immediate=True) as connection: session = database.fetch_session(connection, session_id) assert session is not None profile = dict(session["profile"]) profile["job_type"] = "other" database.update_session( connection, session_id, stage=session["stage"], profile=profile, increment_revision=False, ) timeline = client.get(f"{BASE}/sessions/{session_id}/timeline") assert timeline.status_code == 200, timeline.text assert timeline.json()["session"]["job_type"] == "internship" assert database.get_session(session_id)["profile"]["job_type"] == "internship" def test_internship_flow_uses_education_anchor_and_campus_experience(client: TestClient) -> None: session_id, body = _created_internship_session(client) body = event(client, session_id, body, "continue_enriching").json() card = active_component(body) assert card["data"]["component"] == "record_fields" assert card["data"]["module"] == "campus_experience" assert card["data"]["record_type"] == "campus_experience" assert [field["key"] for field in card["data"]["fields"]] == [ "organization", "role", "start_date", "end_date_or_present", ] submitted = submit_to( client, session_id, body, "record_fields", { "organization": "Campus Tech Club", "role": "Technical Lead", "start_date": "2023-09", "end_date_or_present": "2024-06", "description": "Organized campus programming workshops.", }, ) assert submitted.status_code == 200, submitted.text body = confirm_active(client, session_id, submitted.json()) section = latest_patch(body)["value"]["sections"][-1] assert section["kind"] == "campus_experience" assert section["heading"] == "校园经历" assert section["items"][0]["organization"] == "Campus Tech Club" def test_fixed_flow_ends_at_custom_card_picker_and_can_add_internship(client: TestClient) -> None: session_id, body = _created_internship_session(client) body = event(client, session_id, body, "continue_enriching").json() for expected in ("campus_experience", "project", "competition", "skills", "certificates"): assert find_component(body, "progress_card")["data"]["module"] == expected response = event(client, session_id, body, "skip") assert response.status_code == 200, response.text body = response.json() picker = active_component(body) assert body["stage"] == "RESUME_ENRICHING" assert picker["data"]["component"] == "custom_card_picker" assert [option["value"] for option in picker["data"]["options"]] == [ "education", "work_experience", "internship_experience", "campus_experience", "project_experience", "competition", "finish", ] body = _select_custom_card(client, session_id, body, "internship_experience") card = active_component(body) assert card["data"]["module"] == "internship" assert card["data"]["record_type"] == "internship_experience" body = submit_to( client, session_id, body, "record_fields", { "company": "鏄熸渤绉戞妧", "position": "Software Engineering Intern", "start_date": "2025-01", "end_date_or_present": "2025-04", }, ).json() body = confirm_active(client, session_id, body) assert active_component(body)["data"]["component"] == "add_another" body = _select_custom_card(client, session_id, body, "next") assert active_component(body)["data"]["component"] == "custom_card_picker" kinds = [section["kind"] for section in latest_patch(body)["value"]["sections"]] assert "internship_experience" in kinds body = _select_custom_card(client, session_id, body, "finish") assert body["stage"] == "CONTENT_READY" assert active_component(body)["data"]["component"] == "content_ready_card"