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

164 lines
4.9 KiB
Python

from __future__ import annotations
import json
import subprocess
from pathlib import Path
HTML_PATH = Path("apps/web/vue3/index.html")
def _source_block(source: str, start: str, end: str) -> str:
return source[source.index(start) : source.index(end)]
def _run_node(script: str) -> dict:
completed = subprocess.run(
["node", "-e", script],
check=True,
capture_output=True,
text=True,
)
return json.loads(completed.stdout.strip())
def _progress_state_script(body: str) -> str:
html = HTML_PATH.read_text(encoding="utf-8")
updater = _source_block(
html,
"const updateReferenceBundleDownloadProgress =",
"const pollReferenceBundleDownloadTask =",
)
return f"""
const referenceBundleDownloadState = {{value: {{
visible: false, taskId: '', speciesLabel: '', message: '',
percentage: 0, indeterminate: true, status: '',
bytesDownloaded: 0, totalBytes: 0
}}}};
{updater}
{body}
"""
def test_unknown_total_keeps_indeterminate_progress_and_reports_downloaded_bytes() -> None:
result = _run_node(
_progress_state_script(
"""
updateReferenceBundleDownloadProgress({
id: 'task-download', status: 'running',
progress: {bytes_downloaded: 8388608, total_bytes: 0, indeterminate: true}
}, {species_name: 'Spinacia oleracea'});
console.log(JSON.stringify(referenceBundleDownloadState.value));
"""
)
)
assert result["visible"] is True
assert result["speciesLabel"] == "Spinacia oleracea"
assert result["bytesDownloaded"] == 8388608
assert result["totalBytes"] == 0
assert result["indeterminate"] is True
def test_failure_without_new_progress_preserves_last_downloaded_bytes() -> None:
result = _run_node(
_progress_state_script(
"""
updateReferenceBundleDownloadProgress({
id: 'task-download', status: 'running',
progress: {bytes_downloaded: 8388608, total_bytes: 0, indeterminate: true}
}, {species_name: 'Spinacia oleracea'});
updateReferenceBundleDownloadProgress({
status: 'failed', message: 'IncompleteRead(726589 bytes read)'
}, {species_name: 'Spinacia oleracea'});
console.log(JSON.stringify(referenceBundleDownloadState.value));
"""
)
)
assert result["status"] == "failed"
assert result["message"] == "IncompleteRead(726589 bytes read)"
assert result["bytesDownloaded"] == 8388608
assert result["totalBytes"] == 0
def test_clear_resets_terminal_download_state() -> None:
result = _run_node(
_progress_state_script(
"""
updateReferenceBundleDownloadProgress({
id: 'task-download', status: 'failed', message: 'download failed',
progress: {bytes_downloaded: 4096, total_bytes: 0, indeterminate: true}
}, {species_name: 'Spinacia oleracea'});
clearReferenceBundleDownloadProgress();
console.log(JSON.stringify(referenceBundleDownloadState.value));
"""
)
)
assert result == {
"visible": False,
"taskId": "",
"speciesLabel": "",
"message": "",
"percentage": 0,
"indeterminate": True,
"status": "",
"bytesDownloaded": 0,
"totalBytes": 0,
}
def test_download_indicator_is_beside_tip_and_not_inside_batch_dialog() -> None:
html = HTML_PATH.read_text(encoding="utf-8")
toolbar = _source_block(
html,
"<!-- 使用小Tip hover弹出 -->",
"<!-- Upload hover弹出已上传文件 -->",
)
batch_dialog = _source_block(
html,
"<!-- 批量执行确认对话框 -->",
"<!-- 阶段确认对话框(批量执行用) -->",
)
assert 'class="reference-download-progress"' in toolbar
assert "referenceBundleDownloadState.visible" in toolbar
assert "PPI and Ka/Ks Reference Species Data Download" in toolbar
assert ':show-text="!referenceBundleDownloadState.indeterminate"' in toolbar
assert 'class="reference-download-progress"' not in batch_dialog
assert "referenceBundleDownloadState.visible" not in batch_dialog
def test_download_byte_formatter_uses_binary_units() -> None:
html = HTML_PATH.read_text(encoding="utf-8")
assert "const formatReferenceDownloadBytes =" in html
formatter = _source_block(
html,
"const formatReferenceDownloadBytes =",
"const updateReferenceBundleDownloadProgress =",
)
result = _run_node(
formatter
+ """
console.log(JSON.stringify({
zero: formatReferenceDownloadBytes(0),
mib: formatReferenceDownloadBytes(8388608)
}));
"""
)
assert result == {"zero": "", "mib": "8.0 MB"}
def test_monitor_retains_success_and_passes_failed_task_progress() -> None:
html = HTML_PATH.read_text(encoding="utf-8")
monitor = _source_block(
html,
"const monitorPpiReferenceBundleDownload =",
"const ppiHasNearReferenceBeforeArabidopsis =",
)
assert "clearReferenceBundleDownloadProgress();" not in monitor
assert "err?.task" in monitor