Cin review: no JS tests covered the autoSync* helpers, so the
timezone fix shipped without a regression test in the layer where the
bug actually lived. New `tests/static/test_auto_sync.mjs` runs under
`node --test` (built-in runner, no extra deps) and pins:
- `autoSyncTriggerForHours` / `autoSyncHoursFromTrigger` round-trip
for 1h, 4h, 12h, 24h, 48h, 168h. Catches off-by-one in the day vs
hour conversion that backs the schedule board's drag-drop.
- `autoSyncBucketLabel` / `autoSyncIntervalLabel` formatting +
pluralization.
- `autoSyncSourceLabel` known + unknown + falsy.
- Predicates (`autoSyncCanSchedulePlaylist`,
`autoSyncIsPipelineAutomation`, `autoSyncPlaylistIdFromAutomation`,
`autoSyncIsScheduleOwned`) including the `owned_by`-flag /
legacy-name-prefix split from the previous commit.
- `buildAutoSyncScheduleState` partitions board-owned schedules from
custom pipelines correctly.
- `autoSyncNextRunLabel` parses the naive UTC timestamp as UTC, not
local — exactly the regression that took an hour to diagnose this
session. Includes a past-time check ("due now") and a multi-day
case.
- `getMirroredSourceRef` source_ref/description-URL/source_playlist_id
resolution order.
Cross-realm note: vm-sandbox return values fail `deepStrictEqual`
against host-realm objects even when shape matches, so a small
`deepShapeEqual` helper round-trips through JSON for structural
comparison. The `_autoParseUTC` stub mirrors the real implementation
in stats-automations.js so the timezone test exercises both files end
to end.
`tests/test_auto_sync_js.py` is the pytest shim — shells out to
`node --test` and surfaces failures inline. Skips cleanly when node
isn't on PATH or is older than 22, matching the existing
discover-section-controller test pattern.
Also updated SPLIT_MODULES in tests/test_script_split_integrity.py to
include the new auto-sync.js — the onclick-coverage check was failing
because `openAutoSyncScheduleModal` (referenced from index.html via
the Sync page button) now lives in a module the integrity scanner
wasn't searching.
39 new JS test cases, all green via `node --test` and via the pytest
wrapper.
72 lines
2 KiB
Python
72 lines
2 KiB
Python
"""Run the JS tests for `webui/static/auto-sync.js` under the regular
|
|
pytest sweep.
|
|
|
|
The actual contract tests live in `tests/static/test_auto_sync.mjs`
|
|
and run via Node.js's stable built-in test runner (`node --test`).
|
|
This shim shells out to that runner and asserts a clean exit so the
|
|
JS tests fail the suite if the auto-sync helpers regress.
|
|
|
|
Skipped when:
|
|
- `node` isn't on PATH (e.g. Python-only dev container).
|
|
- Node version < 22 (the built-in `--test` runner went stable in 18
|
|
but the assert-flavor we use is 22+).
|
|
|
|
Run directly:
|
|
node --test tests/static/test_auto_sync.mjs
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import shutil
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
|
|
_REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
_TEST_FILE = _REPO_ROOT / "tests" / "static" / "test_auto_sync.mjs"
|
|
|
|
|
|
def _node_available() -> bool:
|
|
if not shutil.which("node"):
|
|
return False
|
|
try:
|
|
result = subprocess.run(
|
|
["node", "--version"],
|
|
capture_output=True, text=True, timeout=10,
|
|
)
|
|
except (subprocess.SubprocessError, FileNotFoundError):
|
|
return False
|
|
if result.returncode != 0:
|
|
return False
|
|
raw = (result.stdout or "").strip().lstrip("v")
|
|
try:
|
|
major = int(raw.split(".")[0])
|
|
except (ValueError, IndexError):
|
|
return False
|
|
return major >= 22
|
|
|
|
|
|
def test_auto_sync_js():
|
|
"""Pin the auto-sync helper contract via `node --test`."""
|
|
if not _node_available():
|
|
pytest.skip("Node.js >= 22 required to run the JS auto-sync tests")
|
|
|
|
if not _TEST_FILE.exists():
|
|
pytest.skip(f"JS test file missing: {_TEST_FILE}")
|
|
|
|
result = subprocess.run(
|
|
["node", "--test", str(_TEST_FILE)],
|
|
capture_output=True, text=True,
|
|
cwd=str(_REPO_ROOT),
|
|
timeout=60,
|
|
)
|
|
|
|
if result.returncode != 0:
|
|
pytest.fail(
|
|
"JS auto-sync tests failed:\n\n"
|
|
f"--- stdout ---\n{result.stdout}\n"
|
|
f"--- stderr ---\n{result.stderr}",
|
|
pytrace=False,
|
|
)
|