ipx-tui (crates/tui) is iPX's reader in ratatui: your feeds, a feed's items, an item's text as plain text, read and flagged as on the page, through the API with an API token. It installs as `ipx`, so the daemon's binary is now `ipxd`: the Dockerfile, release script, tests and every doc and message that names its commands follow. Naming the binary ipxd alone renamed its crate, and with it every log target (ipx::scan became ipxd::scan): the default filters are ipx=info, so nearly every line would have been dropped and the dashboard's queries on the targets gone blank. The daemon's code is now a library still called ipx, under a five-line ipxd main.rs, and the targets are as they were. ratatui is taken without its default features: 32 new packages in place of 78. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RqkrVDqdiQEMWAkNGQ2tYA
99 lines
4.0 KiB
TypeScript
99 lines
4.0 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';
|
|
|
|
// 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
|
|
|
|
[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"
|
|
|
|
[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"
|
|
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')}"
|
|
`);
|
|
}
|
|
|
|
/// 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';
|
|
|
|
export { prepare, root, TOKEN, DIRECTORY, DIRECTORY_TOKEN, API_COVERAGE, IPX_BIN, DIRECTORY_BIN };
|