Files
PlantAI-dev/tests/unit/test_gene_family_report_triggers.py

182 lines
6.1 KiB
Python

from __future__ import annotations
import json
from pathlib import Path
def _request_and_stages():
from apps.web.vue3.main import ConfirmedPlanExecutionRequest, ConfirmedPlanStage
stages = [
ConfirmedPlanStage(
id="identify",
params={
"scopeId": "scope-a",
"analysisRoute": "post_subfamily_confirm",
"memberSetId": "members-a",
},
),
ConfirmedPlanStage(id="motif", dependencies=["identify"]),
ConfirmedPlanStage(id="pep", dependencies=["motif"]),
]
request = ConfirmedPlanExecutionRequest(
session_id="session-a",
job_id="job-a",
prefix="Ft.SPL",
plan_id="plan-a",
stages=stages,
)
return request, stages
def test_confirmed_plan_terminal_success_requests_final_report() -> None:
from apps.web.vue3.main import _confirmed_plan_report_request
request, stages = _request_and_stages()
report = _confirmed_plan_report_request(
request,
stages,
{"status": "success", "completed_stages": ["identify", "motif", "pep"]},
)
assert report is not None
assert report.stage == "gene_family_report"
assert report.expectedStages == ["identify", "motif", "pep"]
assert report.stageStatuses == {"identify": "success", "motif": "success", "pep": "success"}
assert report.reportAction == "generate"
def test_confirmed_plan_failure_requests_partial_report() -> None:
from apps.web.vue3.main import _confirmed_plan_report_request
request, stages = _request_and_stages()
report = _confirmed_plan_report_request(
request,
stages,
{
"status": "failed",
"completed_stages": ["identify"],
"failure": {"stage": "motif"},
},
)
assert report is not None
assert report.stageStatuses == {"identify": "success", "motif": "failed", "pep": "not_run"}
assert report.scopeId == "scope-a"
assert report.analysisRoute == "post_subfamily_confirm"
assert report.memberSetId == "members-a"
def test_paused_plan_does_not_auto_finalize_report() -> None:
from apps.web.vue3.main import _confirmed_plan_report_request
request, stages = _request_and_stages()
report = _confirmed_plan_report_request(
request,
stages,
{"status": "paused", "completed_stages": ["identify"]},
)
assert report is None
def test_frontend_batch_terminal_path_calls_report_stage_with_planned_statuses() -> None:
source = (Path(__file__).resolve().parents[2] / "apps/web/vue3/index.html").read_text(encoding="utf-8")
assert "submitGeneFamilyReportForBatch" in source
assert "executeSingleStageWithParams('gene_family_report'" in source
assert "expectedStages: plannedIds" in source
assert "stageStatuses" in source
assert "if (pausedCount > 0) return" in source
assert "continuationOpened" in source
assert "name: 'gene_family_report'" in source
assert "openGeneratedGeneFamilyReport" in source
def test_report_context_prefers_terminal_confirmed_plan(monkeypatch, tmp_path: Path) -> None:
from apps.web.vue3 import main as web_main
final_dir = tmp_path / "job-a" / "final"
confirmed_dir = final_dir / ".confirmed_plans"
confirmed_dir.mkdir(parents=True)
(final_dir / "Ft.SPL.gene_family_report.manifest.json").write_text(
json.dumps(
{
"stage": "gene_family_report",
"status": "success",
"prefix": "Ft.SPL",
"parameters": {
"expected_stages": ["identify"],
"stage_statuses": {"identify": "success"},
},
}
),
encoding="utf-8",
)
(confirmed_dir / "0123456789abcdefabcd.json").write_text(
json.dumps(
{
"status": "failed",
"job_id": "job-a",
"prefix": "Ft.SPL",
"stages": ["identify", "motif", "pep", "gene_family_report"],
"completed_stages": ["identify", "motif"],
"failure": {"stage": "pep"},
"scopeId": "scope-a",
"memberSetId": "members-a",
}
),
encoding="utf-8",
)
monkeypatch.setattr(web_main, "WORKSPACE_ROOT", tmp_path)
context = web_main._gene_family_report_plan_context("job-a")
assert context == {
"prefix": "Ft.SPL",
"expectedStages": ["identify", "motif", "pep"],
"stageStatuses": {"identify": "success", "motif": "success", "pep": "failed"},
"scopeId": "scope-a",
"analysisRoute": "",
"memberSetId": "members-a",
"rnaseqScopeId": "",
}
def test_report_context_reuses_formal_report_plan_only(monkeypatch, tmp_path: Path) -> None:
from apps.web.vue3 import main as web_main
final_dir = tmp_path / "job-a" / "final"
final_dir.mkdir(parents=True)
(final_dir / "Ft.SPL.motif.manifest.json").write_text(
json.dumps({"stage": "motif", "status": "success", "prefix": "Ft.SPL"}),
encoding="utf-8",
)
monkeypatch.setattr(web_main, "WORKSPACE_ROOT", tmp_path)
assert web_main._gene_family_report_plan_context("job-a") is None
(final_dir / "Ft.SPL.gene_family_report.manifest.json").write_text(
json.dumps(
{
"stage": "gene_family_report",
"status": "success",
"prefix": "Ft.SPL",
"scope_id": "scope-old",
"parameters": {
"expected_stages": ["identify", "motif"],
"stage_statuses": {"identify": "success", "motif": "success"},
},
}
),
encoding="utf-8",
)
context = web_main._gene_family_report_plan_context("job-a", "Ft.SPL")
assert context is not None
assert context["expectedStages"] == ["identify", "motif"]
assert context["stageStatuses"] == {"identify": "success", "motif": "success"}
assert context["scopeId"] == ""
assert context["analysisRoute"] == ""
assert context["memberSetId"] == ""
assert context["rnaseqScopeId"] == ""