Files
iptvnator/apps/xtream-mock-server
4gray e55d55b47f feat(mock-data): add shared screenshot-safe poster catalog (#1271)
Moves the fictional movie catalog into `libs/shared/marketing-fixtures` so the
Xtream and Stalker mocks describe the same titles, and adds 20 rendered posters
plus the shared fixture types behind them.

Supporting changes made while getting it green:

- `shared-marketing-fixtures` is classified Tier B in the coverage policy. Not
  Tier A: it is fictional fixture data, so a statement percentage over it means
  nothing, and a Tier A entry would pull it into the merged coverage map and the
  ratchet. Tier B still runs its spec in CI. `stalker-mock-server` needs no entry
  of its own — it is already Tier C and the Tier B/C runner falls back to
  `pnpm nx test <project>`, so its new `marketing-poster-url.spec.ts` runs.
- Two release-capture defects the catalog reorder introduced, both fixed in
  `tools/release/capture-app-driver.ts`:
  - VOD stream ids are `MARKETING_VOD_STREAM_ID_BASE + index` and the generator
    now lists the showcase movies first, so 62000-62002 became Black Harbor, The
    Paper Astronaut and Summer Static while the dashboard seeding still mapped
    those ids to the previous titles' backdrops.
  - the raw `tsx` spawn of the Xtream mock lacked `--tsconfig
    tsconfig.base.json`, so the mock could not resolve
    `@iptvnator/shared/marketing-fixtures` and the capture never started. Both
    mock projects' own serve targets already passed the flag.
2026-07-27 08:10:57 +02:00
..

Xtream Codes Mock Server

A lightweight Express server that simulates the Xtream Codes API for local development and end-to-end testing. Uses @faker-js/faker with deterministic seeding so every credential pair always produces the same data.


Quick Start

# Start on port 3211
pnpm nx run xtream-mock-server:serve

# Start with file-watch (auto-restart on code changes)
pnpm nx run xtream-mock-server:serve-with-watch

# Start the mock server plus the Electron app
pnpm run serve:marketing-demo

# Start the mock server plus the browser web app
pnpm run serve:marketing-demo:web

Available Scenarios (credential pairs)

Username Password Scenario Live cats VOD cats Series cats Items/cat Status
user1 pass1 default 8 8 8 40 active
large large large catalog 20 20 20 200 active
stress stress stress catalog 16 16 16 120 active
series series series-heavy 3 4 15 30 active
minimal minimal minimal (edge cases) 2 2 2 5 active
epg epg EPG fixture 2 1 1 3 active
emptyvod emptyvod empty VOD metadata 2 2 2 5 active
marketing marketing fictional release demo 4 4 4 curated active
expired expired expired account 4 4 4 10 Expired
inactive inactive disabled account 4 4 4 10 Disabled

Any other credential pair is auto-generated using a hash of username:password as the faker seed (6 categories, 30 items each, active account).


API Endpoints

Direct Xtream Protocol

GET /player_api.php?action=<action>&username=<u>&password=<p>[&...]

Action Description
(none) / get_account_info User info + server info
get_live_categories Live TV categories
get_vod_categories VOD (movie) categories
get_series_categories Series categories
get_live_streams Live streams (optionally filtered by category_id)
get_vod_streams VOD streams (optionally filtered by category_id)
get_series Series list (optionally filtered by category_id)
get_vod_info?vod_id=<id> Full movie details
get_series_info?series_id=<id> Full series info (seasons + episodes)
get_short_epg?stream_id=<id>[&limit=N] EPG listings for a live channel
get_simple_data_table?stream_id=<id> Full per-channel EPG schedule
get_simple_date_table?stream_id=<id> Legacy typo alias for full per-channel EPG schedule

PWA CORS Proxy Endpoint

IPTVnator's PWA routes Xtream calls through a backend proxy:

GET /xtream?url=<serverUrl>&action=<action>&username=<u>&password=<p>

Response: { payload: <data>, action: <action> }

Stream URLs (stub redirects)

GET /live/<username>/<password>/<streamId>.m3u8  → HLS test stream
GET /movie/<username>/<password>/<streamId>.<ext> → HLS test stream
GET /series/<username>/<password>/<streamId>.<ext> → HLS test stream

Utility Endpoints

GET  /health   → { status: "ok", server: "xtream-mock-server", port: 3211 }
POST /reset    → clears all in-memory caches; data regenerates on next request

Example Requests

# Account info (direct)
curl "http://localhost:3211/player_api.php?username=user1&password=pass1"

# Live categories (direct)
curl "http://localhost:3211/player_api.php?username=user1&password=pass1&action=get_live_categories"

# VOD details (direct)
curl "http://localhost:3211/player_api.php?username=user1&password=pass1&action=get_vod_info&vod_id=20000"

# Series info (direct)
curl "http://localhost:3211/player_api.php?username=user1&password=pass1&action=get_series_info&series_id=30000"

# EPG for stream (direct)
curl "http://localhost:3211/player_api.php?username=user1&password=pass1&action=get_short_epg&stream_id=10000"

# Full EPG schedule (direct)
curl "http://localhost:3211/player_api.php?username=epg&password=epg&action=get_simple_data_table&stream_id=10000"

# Via PWA proxy
curl "http://localhost:3211/xtream?url=http://localhost:3211&username=user1&password=pass1&action=get_live_categories"

Playwright Integration

The mock server starts automatically with nx e2e web-e2e. Run only Xtream tests using the @xtream tag:

nx e2e web-e2e --grep "@xtream"

Test files: apps/web-e2e/src/xtream.e2e.ts

Electron Xtream EPG coverage lives in apps/electron-backend-e2e/src/xtream-epg.e2e.ts.

The Playwright tests use page.route() to redirect the app's backend proxy calls (localhost:3000/xtream**) to the mock server without modifying any application code.


Data Characteristics

  • Deterministic: Same credentials → same data every time (seeded faker)
  • Cached per session: Data generated once on first request, reused until /reset
  • EPG: Titles and descriptions are base64-encoded (matches real Xtream API)
  • Dedicated EPG fixture: epg:epg returns stable live channels plus deterministic get_short_epg and get_simple_data_table payloads for timezone-focused tests
  • Release screenshot fixture: marketing:marketing returns fictional live, VOD, and series data with local generated artwork under apps/xtream-mock-server/public/marketing
  • Timestamp precedence coverage: The epg:epg scenario intentionally shifts raw start / end strings away from start_timestamp / stop_timestamp so UI tests can prove timestamps drive rendering
  • Stream IDs: Live 10,000+, VOD 20,000+, Series 30,000+
  • Category IDs: Live 101+, VOD 201+, Series 301+

Release Demo Artwork

The marketing:marketing fixture uses 65 original fictional titles for release screenshots. Its core 30-title artwork pack includes matched posters and backdrops; 35 additional movie-poster showcase titles use approved local poster PNGs and the deterministic SVG fallback for missing backdrops. The newest 20 showcase movies are ordered first so they appear immediately in screenshot catalog grids. Assets are served from:

apps/xtream-mock-server/public/marketing/{poster,backdrop}/

Generate or validate those assets with:

pnpm release:artwork:dry-run
pnpm release:artwork:generate
pnpm release:artwork:validate

release:artwork:generate uses gpt-image-2 through the OpenAI Image API and requires OPENAI_API_KEY. The screenshot capture workflow only reads committed local assets; it does not call OpenAI. If a local PNG is missing, the mock server falls back to its deterministic SVG renderer for development continuity. The prompt manifest deliberately varies genres and visual media across titles so the catalog does not collapse into one superhero/poster style.


Architecture

See docs/architecture/xtream-mock-server.md for a full description of the data pipeline, response shapes, and extension points.