"""End-to-end vertical for roadmap #26 (rfc-app v0.22.0): the optional "What will you be using this for?" capture on the two propose surfaces. Reuses the FakeGitea + session helpers from test_propose_vertical.py and the active-RFC seed from test_rfc_view_vertical.py. Proves: (a) propose-RFC persists and returns `proposed_use_case` when supplied, and the value survives onto the merged super-draft's RFC view; (b) propose-RFC accepts a NULL / omitted use case ("left blank"); (c) propose-PR persists and returns `proposed_use_case` when supplied, and accepts a NULL / omitted one. """ from __future__ import annotations from test_propose_vertical import ( # noqa: F401 FakeGitea, app_with_fake_gitea, provision_user_row, sign_in_as, tmp_env, ) from test_pr_flow_vertical import _cut_branch_and_accept_change from test_rfc_view_vertical import SEED_BODY, seed_active_rfc # --------------------------------------------------------------------------- # propose-RFC # --------------------------------------------------------------------------- def test_propose_rfc_persists_and_returns_use_case(app_with_fake_gitea): from fastapi.testclient import TestClient app, _fake = app_with_fake_gitea with TestClient(app) as client: provision_user_row(user_id=2, login="alice", role="contributor") provision_user_row(user_id=1, login="ben", role="owner") sign_in_as(client, user_id=2, gitea_login="alice", display_name="Alice", role="contributor", email="alice@test") r = client.post("/api/rfcs/propose", json={ "title": "Open Human Model", "slug": "open-human-model", "pitch": "A shared definition of what we mean by *human*.", "tags": ["identity"], "proposed_use_case": "Wiring OHM into the OpenXML consent surface.", }) assert r.status_code == 200, r.text pr_number = r.json()["pr_number"] # The pending-idea list carries the use case. items = client.get("/api/proposals").json()["items"] assert items[0]["proposed_use_case"] == "Wiring OHM into the OpenXML consent surface." # The pending-idea detail view carries it too. proposal = client.get(f"/api/proposals/{pr_number}").json() assert proposal["proposed_use_case"] == "Wiring OHM into the OpenXML consent surface." # Merge as owner; the use case survives onto the RFC view (looked # up by slug from the canonical side table, since the idea PR # closes on merge). sign_in_as(client, user_id=1, gitea_login="ben", display_name="Ben", role="owner", email="ben@test") r = client.post(f"/api/proposals/{pr_number}/merge") assert r.status_code == 200, r.text view = client.get("/api/rfcs/open-human-model").json() assert view["proposed_use_case"] == "Wiring OHM into the OpenXML consent surface." def test_propose_rfc_use_case_optional(app_with_fake_gitea): from fastapi.testclient import TestClient app, _fake = app_with_fake_gitea with TestClient(app) as client: provision_user_row(user_id=3, login="carol", role="contributor") sign_in_as(client, user_id=3, gitea_login="carol", display_name="Carol", role="contributor") # Omitted entirely. r = client.post("/api/rfcs/propose", json={ "title": "No Use Case", "slug": "no-use-case", "pitch": "p", "tags": [], }) assert r.status_code == 200, r.text pr_a = r.json()["pr_number"] # Explicit null. r = client.post("/api/rfcs/propose", json={ "title": "Null Use Case", "slug": "null-use-case", "pitch": "p", "tags": [], "proposed_use_case": None, }) assert r.status_code == 200, r.text pr_b = r.json()["pr_number"] # Blank/whitespace — treated as "left blank", no row written. r = client.post("/api/rfcs/propose", json={ "title": "Blank Use Case", "slug": "blank-use-case", "pitch": "p", "tags": [], "proposed_use_case": " ", }) assert r.status_code == 200, r.text pr_c = r.json()["pr_number"] for pr in (pr_a, pr_b, pr_c): assert client.get(f"/api/proposals/{pr}").json()["proposed_use_case"] is None # --------------------------------------------------------------------------- # propose-PR (against an active RFC) # --------------------------------------------------------------------------- def test_propose_pr_persists_and_returns_use_case(app_with_fake_gitea): from fastapi.testclient import TestClient app, fake = app_with_fake_gitea with TestClient(app) as client: provision_user_row(user_id=2, login="alice", role="contributor") seed_active_rfc(fake, slug="ohm", title="OHM", body=SEED_BODY) sign_in_as(client, user_id=2, gitea_login="alice", display_name="Alice", role="contributor") branch, _ = _cut_branch_and_accept_change( client, fake, slug="ohm", original="Open Human Model is a framework for representing humans.", proposed="Open Human Model is a framework for representing humans across systems.", ) r = client.post( f"/api/rfcs/ohm/branches/{branch}/open-pr", json={ "title": "Tighten the opening", "description": "Scope to systems.", "proposed_use_case": "Building a cross-system consent registry.", }, ) assert r.status_code == 200, r.text pr_number = r.json()["pr_number"] pr = client.get(f"/api/rfcs/ohm/prs/{pr_number}").json() assert pr["proposed_use_case"] == "Building a cross-system consent registry." def test_propose_pr_use_case_optional(app_with_fake_gitea): from fastapi.testclient import TestClient app, fake = app_with_fake_gitea with TestClient(app) as client: provision_user_row(user_id=2, login="alice", role="contributor") seed_active_rfc(fake, slug="ohm", title="OHM", body=SEED_BODY) sign_in_as(client, user_id=2, gitea_login="alice", display_name="Alice", role="contributor") branch, _ = _cut_branch_and_accept_change( client, fake, slug="ohm", original="It defines consent, trait, and agency in compatible terms.", proposed="It defines consent, trait, harm, and agency in compatible terms.", ) # No proposed_use_case key at all. r = client.post( f"/api/rfcs/ohm/branches/{branch}/open-pr", json={"title": "Add harm", "description": "Name harm explicitly."}, ) assert r.status_code == 200, r.text pr_number = r.json()["pr_number"] pr = client.get(f"/api/rfcs/ohm/prs/{pr_number}").json() assert pr["proposed_use_case"] is None