"""Tests for scroll training pipeline.""" from __future__ import annotations import json import math from pathlib import Path import numpy as np import pytest from tools.scroll.trainer import load_scroll_data, train_scroll, _augment_scroll def _make_synthetic_scroll_trace(mode="target"): """Create a synthetic scroll trace.""" distance = {"target": 1500, "fast": 5000, "precise": 400}[mode] direction = "down" start = 2000 target = start + distance events = [] n_events = 20 for i in range(n_events): frac = (i + 1) / n_events delta = int(distance / n_events * (1 + 0.2 * np.random.randn())) delta = max(20, delta) t = int(frac * 800 + np.random.normal(0, 10)) events.append({"deltaY": delta, "deltaMode": 0, "t": max(0, t)}) events.sort(key=lambda e: e["t"]) events[0]["t"] = 0 return { "meta": { "mode": mode, "start_scrollY": start, "target_scrollY": target, "end_scrollY": target + 5, "distance": distance, "direction": direction, "duration_ms": events[-1]["t"], "viewport_height": 900, }, "events": events, } @pytest.fixture def synthetic_scroll_file(tmp_path): traces_path = tmp_path / "scroll_traces.jsonl" lines = [] for mode in ["target", "fast", "precise"]: for _ in range(10): lines.append(json.dumps(_make_synthetic_scroll_trace(mode))) traces_path.write_text("\n".join(lines), encoding="utf-8") return traces_path class TestLoadScrollData: def test_returns_correct_shapes(self, synthetic_scroll_file): seq, cond = load_scroll_data(synthetic_scroll_file, seq_len=32) assert seq.shape[1] == 32 assert seq.shape[2] == 2 # (delta_norm, log_dt) assert cond.shape[1] == 7 assert len(seq) > 0 class TestAugment: def test_4x_augmentation(self, synthetic_scroll_file): seq, cond = load_scroll_data(synthetic_scroll_file, seq_len=32) n = len(seq) seq_aug, cond_aug = _augment_scroll(seq, cond) assert len(seq_aug) == n * 4 class TestTrainScroll: def test_produces_model_files(self, synthetic_scroll_file, tmp_path): output_dir = tmp_path / "scroll_models" train_scroll( data_path=synthetic_scroll_file, output_dir=output_dir, epochs=3, batch_size=8, ) assert (output_dir / "scroll_model.pt").exists() assert (output_dir / "scroll_config.json").exists()