# 120 — Verification

## 1. Rule

Targeted tests only (user rule): each step tests exactly what it changed —
its unit tests, one live scenario with the fixture provider, and a capture of
the touched screen. The full skin baseline runs only when the user asks.

## 2. Unit tests (offline, no Kodi)

`scripts/library_harness/` with Kodi module stubs (pattern of
`scripts/search_harness/kodi_stubs.py`), run with `python3 -m unittest`:

| Module | Cases |
|--------|-------|
| `store` | schema create/migrate, watchlist import (3 + 12), WAL concurrency (two processes writing), mark rules (watched clears resume, unwatched clears both) |
| `tracker` thresholds | 179 s → nothing saved; 181 s → resume; 89 % → resume; 90 % → watched; ended naturally → watched; zero total time → TMDb runtime |
| `next_up` (050 §2) | mid-season; last episode of S1 → S2E1; S1 watched with a gap → after the latest by order; specials ignored; next unaired → upcoming with date; ended series finished; in-progress beats next; returning series new episode aired → next again |
| collections (050 §5) | next unwatched released film by release date; none → no offer |
| reconcile (040 §6) | Kodi playcount changed after mirror → adopted; Kodi stop-time bookmark older than ours → ignored |
| `urls` | canonical strings stable (parameter order), round trip |
| rows (070 §3) | each row id with limit/sort/hide-watched/upcoming flags on a fixture store |

Fixture TMDb data: `scripts/library_harness/fixtures/` — a show with seasons
0, 1 (10 eps), 2 (8 eps, last 2 unaired relative to a frozen "today"), an
ended show, two movies of one collection.

## 3. Live fixture provider (real Kodi, no network)

- Provider `fixture`, active only when the harness `ENABLED` flag exists and
  addon setting `dev_fixture_provider` is on (hidden setting): the resolver
  returns local ffmpeg test videos (`scripts/library_harness/media/`, 4 min
  and 40 s files, generated once) instead of searching Webshare / Kraska;
  `meta.py` is pre-seeded from the fixture TMDb data.
- During live tests the thresholds are lowered through the settings
  (`lib_resume_min_seconds=10`, autoplay countdown 15 s) and restored after.
- Scenarios (each run only in the phase that builds it):
  1. play movie 25 s, stop → in progress, Continue movie row shows it, tick
     absent, progress bar present, Kodi's `Files.GetFileDetails` shows the
     same resume;
  2. Continue click → resumes at the saved second with the same fixture file;
  3. play to the end → watched, removed from Continue;
  4. S01E10 with autoplay → countdown → S02E01 starts, S01E10 watched,
     Continue series row shows S02E01 in progress;
  5. last aired episode → no countdown, notification with the air date,
     Continue shows "vyjde …";
  6. Kodi's own "Označit jako zhlédnuté" on an item → adopted within 5 s;
  7. MyTV playback → store unchanged;
  8. kill Kodi during playback → on restart the position (≤ 10 s old) is in
     the store.

## 4. Captures

`kodi_live.py shot --native` / `window` of only the touched screens: My
movies views, a series' seasons and episodes, info dialog, context menu, Home
sections, slot editor. Compare with the previous capture of the same screen
when a change should not move anything else.

## 5. Acceptance (L6)

Unit suite green; scenarios 1–8 green in one session; the user's own test on
real Webshare playback (one movie, one series across a season end);
`docs/features/013-milionar-library.md` after the user's test (`/feature`).

### Result (L6, 2026-10-01, fixture provider, one session)

Unit suite: 158 green (`python3 -m unittest discover -s scripts/library_harness -p 'test_*.py'`).
Live scenarios of §3:

| # | Scenario | Result |
|---|----------|--------|
| 1 | movie 28 s, stop | in progress (resume 29 s of 240 s), Kodi's own record shows the same resume, `cont_movies` lists it with the position |
| 2 | resume | `--resume` starts at the saved second (36 s after 8 s of play from 29 s) |
| 3 | play to the end | `playcount` 1, resume 0, no longer in `cont_movies` |
| 4 | S01E10 with autoplay | countdown, S02E01 started by itself, E10 watched once, S02E01 in progress and in `cont_series` (resume) |
| 5 | last aired episode (S02E06, S02E07 unaired) | no countdown, E06 watched; with nothing in progress `cont_series` shows "vyjde 8. 10." and hides it with the upcoming switch off |
| 6 | Kodi's own change | `Files.SetFileDetails playcount=1` on an item shown in My movies is adopted within 3 s (an item that is not shown is not checked: by design, 040 §6) |
| 7 | MyTV-like playback (a file started outside the library) | `play_log` / `movie_state` / `episode_state` unchanged |
| 8 | Kodi killed during playback | after the restart the position (20 s, 7 s old) is in the store, the open `play_log` row is closed as `crash` |

Fixture rows, Kodi records and settings were restored afterwards (fixture provider off, resume 180 s, autoplay 45 / 15).
Not covered by fixtures: real Webshare playback (the user's test below).
