Nothing in the browser suite asked ipx, the directory or ipx-play for their metrics, though production's Prometheus scrapes all three every 15 s and the dashboard and alerts go blank if one stops answering. The suite's servers get metrics ports (8799, 8797, 8790) and one test reads each gzipped, checks every sample line is one Prometheus can parse, and looks for the series that show it works: ipx's request histogram with the route just asked for, the directory's snapshot from ipx, ipx-play's build. ipx's metrics.rs went from 9% to 86% of lines run by the suite. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
117 lines
4.7 KiB
TypeScript
117 lines
4.7 KiB
TypeScript
// Builds a scratch config and data dir so the browser tests drive a real daemon with
|
|
// known feeds, rather than whatever happens to be on the machine.
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import os from 'node:os';
|
|
import crypto from 'node:crypto';
|
|
|
|
const root = path.join(os.tmpdir(), 'ipx-ui-test');
|
|
const TOKEN = 'testtokentesttokentesttoken12345'; // fixed, so tests need not scrape a log
|
|
// The suite's own directory service (#205), and this daemon's token for it, which may do anything.
|
|
const DIRECTORY = 'http://127.0.0.1:8795';
|
|
const DIRECTORY_TOKEN = 'ipxd_testdirectorytoken';
|
|
// The suite's own ipx-play (#447), which shared episodes' links go to.
|
|
const PLAY = 'http://127.0.0.1:8798';
|
|
const PLAY_TOKEN = 'ipxd_testplaytoken';
|
|
|
|
// Called from playwright.config.ts at load time, NOT as globalSetup: Playwright starts
|
|
// webServer *before* globalSetup, so a config written there does not exist yet when the
|
|
// daemon launches -- it would fall back to the real config and fight the live daemon.
|
|
// Playwright imports this config again in every worker process, so prepare() runs more
|
|
// than once per suite. Wiping on the second call deleted the data directory out from under
|
|
// the running daemon: it kept serving from the unlinked inode, while anything else opening
|
|
// that path -- the CLI, a query -- got a brand new empty database and disagreed with it.
|
|
function prepare() {
|
|
// Only the process that launches the run may wipe. A worker gets TEST_WORKER_INDEX.
|
|
if (process.env.TEST_WORKER_INDEX !== undefined || process.env.PW_WORKER_INDEX !== undefined) {
|
|
return;
|
|
}
|
|
fs.rmSync(root, { recursive: true, force: true });
|
|
for (const d of ['config', 'data', 'downloads']) {
|
|
fs.mkdirSync(path.join(root, d), { recursive: true });
|
|
}
|
|
fs.writeFileSync(path.join(root, 'config', 'config.toml'), `
|
|
[general]
|
|
download_dir = "${path.join(root, 'downloads')}"
|
|
socket = "${path.join(root, 'ipx.sock')}"
|
|
schedule = "every 60m"
|
|
max_new_per_check = 1
|
|
# The fixture feeds are on loopback, which ipx refuses otherwise (#320).
|
|
fetch_internal = ["127.0.0.1"]
|
|
directory_url = "${DIRECTORY}"
|
|
directory_token = "${DIRECTORY_TOKEN}"
|
|
directory_share = true
|
|
play_url = "${PLAY}"
|
|
play_token = "${PLAY_TOKEN}"
|
|
|
|
[torrent]
|
|
enabled = false
|
|
|
|
[web]
|
|
enabled = true
|
|
# Behind Caddy, which serves the pages on 8791 and passes the API here (#203).
|
|
bind = "127.0.0.1:8796"
|
|
token = "${TOKEN}"
|
|
# The proxy path, for tests that send the header themselves: the daemon sees them at 127.0.0.1.
|
|
trusted_header = "X-Test-User"
|
|
trusted_proxies = ["127.0.0.1"]
|
|
sign_out_url = "/signed-out-by-the-proxy"
|
|
# What Prometheus scrapes in production (#194), read by a test once the others have made requests.
|
|
metrics_bind = "127.0.0.1:8799"
|
|
|
|
[feeds.test-show]
|
|
url = "http://127.0.0.1:8792/show.xml"
|
|
auto_download = true
|
|
|
|
# Downloads its image, so the UI has a file that is not playable to deal with.
|
|
[feeds.picture-blog]
|
|
url = "http://127.0.0.1:8792/pics.xml"
|
|
auto_download = true
|
|
media_types = ["image"]
|
|
|
|
[feeds.multi-show]
|
|
url = "http://127.0.0.1:8792/multi.xml"
|
|
auto_download = true
|
|
|
|
[feeds.test-subscriptions]
|
|
url = "http://127.0.0.1:8792/subs.opml"
|
|
auto_download = false
|
|
|
|
# A key in its URL, like a Patreon feed: someone's paid subscription, never offered to others.
|
|
[feeds.paid-show]
|
|
url = "http://127.0.0.1:8792/paid.xml?auth=secret123"
|
|
auto_download = false
|
|
`);
|
|
fs.writeFileSync(path.join(root, 'directory.toml'), `
|
|
bind = "127.0.0.1:8795"
|
|
metrics_bind = "127.0.0.1:8797"
|
|
database_url_env = "DIRECTORY_DATABASE_URL"
|
|
# The fixture feeds are on loopback, which the refresher refuses otherwise (#329).
|
|
fetch_internal = ["127.0.0.1"]
|
|
|
|
[[tokens]]
|
|
name = "test"
|
|
access = "rwa"
|
|
token_sha256 = "${crypto.createHash('sha256').update(DIRECTORY_TOKEN).digest('hex')}"
|
|
`);
|
|
fs.writeFileSync(path.join(root, 'play.toml'), `
|
|
bind = "127.0.0.1:8798"
|
|
metrics_bind = "127.0.0.1:8790"
|
|
public_url = "${PLAY}"
|
|
|
|
[[tokens]]
|
|
name = "test"
|
|
token_sha256 = "${crypto.createHash('sha256').update(PLAY_TOKEN).digest('hex')}"
|
|
`);
|
|
}
|
|
|
|
/// With IPX_API_COVERAGE set to an instrumented build's target (`sh scripts/coverage.sh api`, #394), the
|
|
/// suite runs that build's ipx and ipx-directory, which write their coverage profiles there, the
|
|
/// tests' own `ipx` commands included; without it, the debug build it makes itself.
|
|
const API_COVERAGE = process.env.IPX_API_COVERAGE ?? '';
|
|
const IPX_BIN = API_COVERAGE ? path.join(API_COVERAGE, 'debug', 'ipxd') : './target/debug/ipxd';
|
|
const DIRECTORY_BIN = API_COVERAGE ? path.join(API_COVERAGE, 'debug', 'ipx-directory') : './target/debug/ipx-directory';
|
|
const PLAY_BIN = API_COVERAGE ? path.join(API_COVERAGE, 'debug', 'ipx-play') : './target/debug/ipx-play';
|
|
|
|
export { prepare, root, TOKEN, DIRECTORY, DIRECTORY_TOKEN, PLAY, API_COVERAGE, IPX_BIN, DIRECTORY_BIN, PLAY_BIN };
|