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, "", "", ) 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