Files
PlantAI-dev/tests/unit/test_autofill_entrypoints.py
T

145 lines
5.6 KiB
Python
Raw Normal View History

2026-08-03 18:42:47 +08:00
from pathlib import Path
import sys
ROOT = Path(__file__).resolve().parents[2]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from apps.cli.run_config_autofill import build_rows, merge_rows
from apps.cli.autofill_common import scan_files
from gfa_core.mas.agents.router_runtime import RouterRuntime
def test_direct_config_open_commands_map_to_config_dialog_action():
for query in (
"打开 config",
"打开 config.xlsx",
"重新打开配置表",
"帮我打开当前 job 的配置",
):
assert RouterRuntime._config_dialog_ui_action(query) == "open_config_dialog"
def test_config_discussion_does_not_map_to_config_dialog_action():
for query in (
"读取 config.xlsx 中有哪些物种",
"检查 config 是否正确",
"我已经打开 config,下一步做什么",
"config 为什么打不开",
"config 已确认,执行数据准备",
):
assert RouterRuntime._config_dialog_ui_action(query) is None
2026-08-03 18:42:47 +08:00
def test_at_spl_pep_upload_is_detected_as_seed_reference(tmp_path):
input_dir = tmp_path / "input"
input_dir.mkdir()
(input_dir / "At.SPL.pep.fa").write_text(">AT1G01010\nMAAA\n", encoding="utf-8")
rows = build_rows(
input_dir=input_dir,
source_dir=input_dir,
description="",
species_code="",
gene_family="SPL",
)
row = next(item for item in rows if item["Original_File_Name"] == "At.SPL.pep.fa")
assert row["Species_Code"] == "At"
assert row["Gene_Family"] == "SPL"
assert row["File_Type"] == "pep"
assert row["Ref"] == "TRUE"
assert row["Species_Role"] == "seed_reference"
assert row["File_Scope"] == "known_family"
assert row["confidence"] == "high"
def test_scan_files_uses_job_input_but_ignores_generated_or_archive_dirs(tmp_path):
input_dir = tmp_path / "input"
input_dir.mkdir()
(input_dir / "At.SPL.pep.fa").write_text(">AT\nMA\n", encoding="utf-8")
(input_dir / "final").mkdir()
(input_dir / "final" / "At.SPL.pep.fa").write_text(">generated\nMA\n", encoding="utf-8")
(input_dir / "uploaded_configs").mkdir()
(input_dir / "uploaded_configs" / "At.SPL.pep.fa").write_text(">archive\nMA\n", encoding="utf-8")
scanned = [path.relative_to(input_dir).as_posix() for path in scan_files(input_dir)]
assert scanned == ["At.SPL.pep.fa"]
def test_regenerated_draft_merges_new_upload_without_dropping_existing_rows(tmp_path):
input_dir = tmp_path / "input"
input_dir.mkdir()
(input_dir / "At.SPL.pep.fa").write_text(">AT1G01010\nMAAA\n", encoding="utf-8")
existing_rows = [
{
"Original_File_Name": "Arabidopsis_thaliana.TAIR10.pep.all.fa",
"Species_Code": "At",
"Gene_Family": "",
"File_Type": "pep",
"Ref": "TRUE",
"Species_Role": "seed_reference",
"File_Scope": "known_family",
"confidence": "high",
"notes": "",
}
]
detected_rows = build_rows(input_dir, input_dir, "", "", "SPL")
merged = merge_rows(existing_rows, detected_rows)
names = [row["Original_File_Name"] for row in merged]
assert "Arabidopsis_thaliana.TAIR10.pep.all.fa" in names
assert "At.SPL.pep.fa" in names
assert len(names) == len(set(names))
def test_frontend_autofill_entrypoints_keep_open_and_regenerate_separate():
html = (ROOT / "apps/web/vue3/index.html").read_text(encoding="utf-8")
queue_start = html.index("const queueAutofillFromPayload")
queue_end = html.index("const handleUploadSuccess", queue_start)
queue_block = html[queue_start:queue_end]
assert queue_block.count("sourceDir: ''") >= 2
assert "await openAutofillDialog('config'" in queue_block
assert "await openAutofillDialog('samples'" in queue_block
assert "const openExistingAutofillDraft" in html
assert "options.keepCurrentRows && !(autofillState.rows && autofillState.rows.length)" in html
assert "autoGenerate: wantsAutofillRegenerate" in html
def test_backend_open_endpoints_prefer_draft_then_confirmed_file():
main_py = (ROOT / "apps/web/vue3/main.py").read_text(encoding="utf-8")
assert '@app.post("/api/autofill/config/open")' in main_py
assert 'workspace_dir / "final" / "config.autofill.draft.xlsx"' in main_py
assert 'input_dir / "config.xlsx"' in main_py
assert '@app.post("/api/autofill/samples/open")' in main_py
assert 'workspace_dir / "final" / "samples.autofill.draft.yaml"' in main_py
assert 'input_dir / "samples.yaml"' in main_py
def test_chat_config_dialog_action_is_transmitted_and_opens_current_job_config():
main_py = (ROOT / "apps/web/vue3/main.py").read_text(encoding="utf-8")
html = (ROOT / "apps/web/vue3/index.html").read_text(encoding="utf-8")
assert '"ui_action": outcome.get("ui_action")' in main_py
assert "data.intent.ui_action === 'open_config_dialog'" in html
assert "await openAutofillDialog('config'" in html
assert "await openExistingAutofillDraft('config')" in html
2026-08-03 18:42:47 +08:00
def test_samples_confirm_no_longer_blocks_on_pending_de_roles_and_closes_dialog():
html = (ROOT / "apps/web/vue3/index.html").read_text(encoding="utf-8")
confirm_start = html.index("const confirmAutofillDraft")
confirm_end = html.index("const loadFromPath", confirm_start)
confirm_block = html[confirm_start:confirm_end]
assert "链特异性为必填" in confirm_block
assert "分组角色为必填" not in confirm_block
assert "请在样本表中标记唯一对照组" not in confirm_block
assert "请在样本表中至少标记一个比较组" not in confirm_block
assert "autofillDialogVisible.value = false" in confirm_block