"""ET-011 — pytest-обёртка для JS unit-тестов download-UI. Контекст: test-plan §E2E-01..E2E-04 предусматривал Playwright-спеку `tests/web/test_track_download.spec.ts`, но в проекте нет настроенного Playwright-раннера. Reviewer ET-011 (12-review.md, P1-01) разрешил закрыть UI-сторону AC-1 / AC-2 / AC-7 поведенческими JS unit-тестами через `node --test`. AC-13 (mobile-bbox) оставлен как manual smoke (см. 04b-ui-test-cases.md TC-UI-02). Этот файл — pytest-точка-входа, запускающая Node-раннер. Так JS-тесты исполняются в обычном `pytest tests/` без отдельных шагов в Makefile/CI. Запуск JS-тестов напрямую: node --test tests/web/track_download.test.js """ from __future__ import annotations import subprocess from pathlib import Path from shutil import which import pytest REPO_ROOT = Path(__file__).resolve().parents[2] GPS_TRACKS_JS = REPO_ROOT / "src" / "web" / "gps_tracks.js" JS_TEST = REPO_ROOT / "tests" / "web" / "track_download.test.js" def _read(path: Path) -> str: assert path.is_file(), f"не найден {path}" return path.read_text(encoding="utf-8") # ─── Статические проверки: ET-011 артефакты на месте ───────────────────────── def test_download_helpers_defined_in_gps_tracks_js(): """ET-011: новые функции download-UI объявлены в gps_tracks.js.""" js = _read(GPS_TRACKS_JS) for symbol in ( "function _parseFilenameFromCD(", "function _handleDownloadError(", "async function _downloadPublicTrack(", ): assert symbol in js, ( f"ET-011: символ `{symbol}` не найден в src/web/gps_tracks.js" ) def test_popup_renders_download_button_markup(): """AC-1: _renderTrackPopupHtml содержит маркап кнопки «Скачать GPX».""" js = _read(GPS_TRACKS_JS) # Существенные куски, по которым держится UI-контракт assert 'aria-label="Скачать GPX"' in js, ( "AC-1: aria-label='Скачать GPX' отсутствует в gps_tracks.js" ) assert "track-popup-download-btn" in js, ( "AC-1: CSS-класс кнопки track-popup-download-btn отсутствует" ) assert "data-track-id=" in js, ( "ADR-014 §3.b: data-track-id для делегированного клика отсутствует" ) def test_js_test_file_exists(): """JS-тест присутствует в репозитории — иначе субтесты ниже бессмыслены.""" assert JS_TEST.is_file(), f"не найден JS-тест {JS_TEST}" # ─── Поведенческие JS unit-тесты через Node ────────────────────────────────── node_required = pytest.mark.skipif( which("node") is None, reason="node не установлен — поведенческие JS unit-тесты пропущены", ) @node_required def test_js_track_download_unit_tests_pass(): """ET-011 P1-01: AC-1 / AC-2 / AC-7 (UI) — JS-тесты download-flow.""" node = which("node") result = subprocess.run( [node, "--test", str(JS_TEST)], capture_output=True, text=True, cwd=str(REPO_ROOT), ) assert result.returncode == 0, ( f"JS unit-тесты track_download упали (код {result.returncode}):\n" f"STDOUT:\n{result.stdout}\n\nSTDERR:\n{result.stderr}" )