With no network the home-screen app showed nothing: no service worker, and the lists the page had fetched, full text included, lived only in its memory. A service worker (web/sw/sw.ts, TypeScript checked against a worker's globals by tsconfig.sw.json, built by swc to /sw.js) goes to the network first for the page and every API read and keeps the answers, so online nothing is an old copy and #388's version check works as before; offline the kept copy answers. Scripts named by hash come from what is kept. Reads, flags and places in an episode that cannot reach the server wait in an outbox, sent in order when the connection is back (and new ones queue behind them meanwhile, so none lands out of turn); a kept list served offline shows the reads waiting there. Pictures: a worker cannot keep another site's pictures sensibly, since browsers count each opaque answer as megabytes. ipx now remembers the picture addresses in item text it sends (bounded, in memory) and /api/art fetches those as it does artwork, through the guarded client; the worker keeps them, for unread items, under a 200 MB budget, and serves them offline in place of the publisher's. Online, pictures still come from their publisher. Sign-out, or another account signing in on the device, clears what was kept. The browser suite blocks the worker except in the offline tests, since it answers before page.route can. The fixture JPEGs are placeholders a browser cannot draw; the offline test uses a real PNG. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
74 lines
3.0 KiB
JavaScript
74 lines
3.0 KiB
JavaScript
const { defineConfig } = require('@playwright/test');
|
|
const setup = require('./tests/ui/global-setup');
|
|
|
|
// Before anything else, including the servers below.
|
|
setup.prepare();
|
|
|
|
// Real browser against a real daemon. The stub-DOM smoke test catches a script that
|
|
// fails to load; it cannot catch a wrong selector, a handler that runs but does nothing,
|
|
// or a page that renders empty -- which is exactly what has slipped through before.
|
|
module.exports = defineConfig({
|
|
testDir: './tests/ui',
|
|
timeout: 30_000,
|
|
expect: { timeout: 10_000 },
|
|
fullyParallel: false, // one daemon, one database
|
|
workers: 1,
|
|
reporter: process.env.CI ? 'line' : [['list']],
|
|
use: {
|
|
baseURL: 'http://127.0.0.1:8791',
|
|
trace: 'retain-on-failure',
|
|
screenshot: 'only-on-failure',
|
|
// The offline service worker (#389) answers requests before page.route sees them, which the
|
|
// tests that fake an answer rely on. The offline tests allow it for themselves.
|
|
serviceWorkers: 'block',
|
|
},
|
|
webServer: [
|
|
{
|
|
command: 'node tests/ui/fixtures/serve.js',
|
|
port: 8792,
|
|
reuseExistingServer: false,
|
|
stdout: 'ignore',
|
|
},
|
|
{
|
|
// The directory the Directory shows (#205), on SQLite in the scratch directory.
|
|
command: `cargo build -q -p ipx-directory && exec ./target/debug/ipx-directory --config ${setup.root}/directory.toml`,
|
|
url: `${setup.DIRECTORY}/healthz`,
|
|
reuseExistingServer: false,
|
|
timeout: 180_000,
|
|
stdout: 'ignore',
|
|
env: { DIRECTORY_DATABASE_URL: `sqlite://${setup.root}/directory.db?mode=rwc` },
|
|
},
|
|
{
|
|
// The frontend as production serves it (#203): built from web/, served by Caddy on the
|
|
// suite's port, the API passed to the daemon behind it.
|
|
command: `node web/build.mjs ${setup.root}/web && exec caddy run --config web/Caddyfile --adapter caddyfile`,
|
|
url: 'http://127.0.0.1:8791/favicon.png',
|
|
reuseExistingServer: false,
|
|
timeout: 60_000,
|
|
stdout: 'ignore',
|
|
env: { WEB_BIND: '127.0.0.1:8791', WEB_ROOT: `${setup.root}/web`, IPX_UPSTREAM: '127.0.0.1:8796', HOME: setup.root, XDG_DATA_HOME: setup.root, XDG_CONFIG_HOME: setup.root },
|
|
},
|
|
{
|
|
// Build first so the tests always run against current source.
|
|
command: 'cargo build -q && exec ./target/debug/ipx daemon',
|
|
port: 8796,
|
|
reuseExistingServer: false,
|
|
timeout: 180_000,
|
|
stdout: 'pipe',
|
|
env: {
|
|
IPX_CONFIG: `${setup.root}/config/config.toml`,
|
|
IPX_DATA_DIR: `${setup.root}/data`,
|
|
IPX_LOG: 'ipx=info',
|
|
// Blank, whatever the shell running the suite has: the test daemon sends no traces to
|
|
// production's Tempo and never opens production's database.
|
|
OTEL_EXPORTER_OTLP_ENDPOINT: '',
|
|
IPX_DATABASE_URL: '',
|
|
// The server's TypeSafe key is the shell's: /src/.envrc's is a development key, for this.
|
|
// Without one, the tests of the server paying for Signals see that it cannot.
|
|
TYPESAFE_KEY: process.env.TYPESAFE_KEY ?? '',
|
|
IPX_TYPESAFE_URL: 'http://127.0.0.1:8792/jev',
|
|
},
|
|
},
|
|
],
|
|
});
|