- Add feed lists what other accounts subscribe to, most subscribers
first, and subscribes you by id (GET /api/popular, POST
/api/popular/{id}). Rows never carry a URL. Feeds from an OPML and
anything that looks private (a login, credentials in the URL, a key
such as auth= or token=) are never listed, and the subscribe route
checks the id against the same list.
- CHANGELOG.md follows Keep a Changelog 1.1.0: 0.1.0 (2026-09-09, the
CLI), 0.2.0 (2026-09-10, the web UI), 0.3.0 (2026-09-11, accounts and
sharing). The long-form entries moved unchanged to docs/history.md.
- Cargo.toml is 0.3.0. CLAUDE.md says how to add an entry and cut a
release.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016HdTEWQNrzyFULijigkmMn
67 lines
2.3 KiB
JavaScript
67 lines
2.3 KiB
JavaScript
// 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.
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const os = require('os');
|
|
|
|
const root = path.join(os.tmpdir(), 'ipx-ui-test');
|
|
const TOKEN = 'testtokentesttokentesttoken12345'; // fixed, so tests need not scrape a log
|
|
|
|
// Called from playwright.config.js 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
|
|
|
|
[torrent]
|
|
enabled = false
|
|
|
|
[web]
|
|
enabled = true
|
|
bind = "127.0.0.1:8791"
|
|
token = "${TOKEN}"
|
|
|
|
[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
|
|
`);
|
|
}
|
|
|
|
module.exports = { prepare, root, TOKEN };
|