Files
PlantAI-dev/tests/unit/test_gwas_prefix_frontend_contract.py
T
2026-08-03 18:42:47 +08:00

96 lines
4.7 KiB
Python

from __future__ import annotations
import json
import subprocess
from pathlib import Path
FRONTEND = Path(__file__).resolve().parents[2] / "apps/web/vue3/index.html"
def _frontend_text() -> str:
return FRONTEND.read_text(encoding="utf-8")
def test_gwas_dialog_uses_species_prefix_copy_and_batch_binding() -> None:
frontend = _frontend_text()
assert "物种简称(用于结果前缀)" in frontend
assert 'placeholder="At / Os / Zm"' in frontend
assert 'v-model="batchExecuteParams.prefix"' in frontend
assert 'v-if="!isBatchExecuting && batchIncludesGwasStages()"' in frontend
def test_gwas_template_helpers_are_exposed_from_vue_setup() -> None:
frontend = _frontend_text()
setup_return_start = frontend.rindex(" return {")
setup_return_end = frontend.index(" };\n }\n });", setup_return_start)
setup_return = frontend[setup_return_start:setup_return_end]
assert " isGwasStage," in setup_return
assert " batchIncludesGwasStages," in setup_return
def test_gwas_prefix_helpers_require_and_lock_one_batch_value(tmp_path: Path) -> None:
frontend = _frontend_text()
start = frontend.index("const gwasStageIds =")
end = frontend.index("const uniqueSpeciesList =", start)
helper_source = frontend[start:end]
node_script = tmp_path / "gwas-prefix-contract.cjs"
node_script.write_text(
"const batchExecuteParams={value:{prefix:'Os',params:{prefix:'Os'},plan:{params:{prefix:'Os'}}}};"
"const batchExecuteStages={value:["
"{id:'gwas_fmt',params:{prefix:'Os'}},"
"{id:'gwas_trait',params:{}},"
"{id:'rnaseq_qc',params:{prefix:'RNA'}}]};"
"const confirmParams={prefix:'Os'};"
"const getStageId=(stage)=>typeof stage==='object'?stage.id:stage;"
"const prefixlessStages=new Set(); const isGeneFamilyScopeStage=()=>false;"
"const geneFamilyAutoPrefix=()=>''; const params={prefix:''};"
"const normalizedPrefix=(value)=>String(value||'').trim()||'At';"
+ helper_source
+ "const blankMissing=gwasPrefixMissingFor({stage:'gwas_fmt',prefix:' '});"
+ "const locked=lockGwasBatchPrefix(' cohort ');"
+ "const lockedBatch=JSON.parse(JSON.stringify(batchExecuteParams.value));"
+ "const lockedStages=JSON.parse(JSON.stringify(batchExecuteStages.value));"
+ "const lockedConfirm=confirmParams.prefix;"
+ "batchExecuteParams.value={}; confirmParams.prefix='';"
+ "const blankExecutionPrefix=executionPrefix('gwas_fmt',{});"
+ "process.stdout.write(JSON.stringify({blankMissing,locked,blankExecutionPrefix,batch:lockedBatch,stages:lockedStages,confirm:lockedConfirm}));",
encoding="utf-8",
)
completed = subprocess.run(["node", str(node_script)], text=True, capture_output=True, check=False)
assert completed.returncode == 0, completed.stderr
payload = json.loads(completed.stdout)
assert payload["blankMissing"] is True
assert payload["locked"] == "cohort"
assert payload["blankExecutionPrefix"] == ""
assert payload["batch"]["prefix"] == "cohort"
assert payload["batch"]["params"]["prefix"] == "cohort"
assert payload["batch"]["plan"]["params"]["prefix"] == "cohort"
assert payload["stages"][0]["params"]["prefix"] == "cohort"
assert payload["stages"][1]["params"]["prefix"] == "cohort"
assert payload["stages"][2]["params"]["prefix"] == "RNA"
assert payload["confirm"] == "cohort"
def test_gwas_submission_validates_before_closing_dialog_and_disables_auto_start() -> None:
frontend = _frontend_text()
batch_start = frontend.index("const startBatchExecute = async () =>")
batch_end = frontend.index("const executeStagesWithDependencies =", batch_start)
batch_source = frontend[batch_start:batch_end]
direct_start = frontend.index("const doExecute = async () =>")
direct_end = frontend.index("const queueAutofillFromPayload = async", direct_start)
direct_source = frontend[direct_start:direct_end]
batch_timer_start = frontend.index("const startBatchExecuteTimer = () =>")
batch_timer_end = frontend.index("const clearBatchExecuteTimer =", batch_timer_start)
batch_timer_source = frontend[batch_timer_start:batch_timer_end]
assert batch_source.index("gwasPrefixMissingFor") < batch_source.index("batchExecuteDialogVisible.value = false")
assert batch_source.index("lockGwasBatchPrefix") < batch_source.index("batchExecuteDialogVisible.value = false")
assert direct_source.index("gwasPrefixMissingFor") < direct_source.index("confirmDialogVisible.value = false")
assert "batchIncludesGwasStages()" in batch_timer_source
assert "batchExecuteCountdown.value = 0" in batch_timer_source