"""Operator decision flow (approve / hold / reject) end-to-end. Runs against the real server (no bootstrap stub): each test uploads an image to seed a genuine submission, then exercises the decision pane and asserts the decision both renders and persists through ``refreshFromApi``. """ from __future__ import annotations from pathlib import Path from .pages import OperatorWorkbench from .pages.workbench_page import MEMO_REQUIRED_ERROR _SVG = "" def _open_seeded_case(workbench: OperatorWorkbench, tmp_path: Path, case_id: str = "decide-me") -> str: upload_file = tmp_path / f"{case_id}.svg" upload_file.write_text(_SVG, encoding="utf-8") workbench.goto().upload_and_open(str(upload_file), case_id) # A freshly uploaded submission starts unreviewed. assert "현재 운영 결정: 미심사" in workbench.recommendation_box.inner_text() return case_id def test_reject_without_memo_is_blocked_and_not_persisted(operator_server, operator_page, tmp_path): workbench = OperatorWorkbench(operator_page, operator_server.base_url) _open_seeded_case(workbench, tmp_path) workbench.decide("rejected") # 반려 requires a memo assert workbench.memo_error.inner_text() == MEMO_REQUIRED_ERROR # The guard fires client-side, so the decision is never sent or persisted. assert "현재 운영 결정: 미심사" in workbench.recommendation_box.inner_text() def test_approve_persists_without_memo(operator_server, operator_page, tmp_path): workbench = OperatorWorkbench(operator_page, operator_server.base_url) _open_seeded_case(workbench, tmp_path) workbench.decide("approved") # 승인 needs no memo workbench.wait_for_decision_label("승인") assert workbench.memo_error.inner_text() == "" assert not workbench.console_errors def test_hold_persists_without_memo(operator_server, operator_page, tmp_path): workbench = OperatorWorkbench(operator_page, operator_server.base_url) _open_seeded_case(workbench, tmp_path) workbench.decide("held") # 보류 needs no memo workbench.wait_for_decision_label("보류") assert workbench.memo_error.inner_text() == "" assert not workbench.console_errors def test_reject_with_memo_persists_and_clears_memo(operator_server, operator_page, tmp_path): workbench = OperatorWorkbench(operator_page, operator_server.base_url) _open_seeded_case(workbench, tmp_path) workbench.set_decision_memo("저작권 침해 소지") workbench.decide("rejected") workbench.wait_for_decision_label("반려") assert workbench.memo_error.inner_text() == "" # The memo field is cleared after a successful decision. assert workbench.decision_memo.input_value() == "" assert not workbench.console_errors