Checkpoint peering identity and opt-in discovery
This commit is contained in:
1 parent
eba9b50e30
commit
47de081721
44 files changed
+1557
-55
No files matched your search
+31
-2
@@ -8,7 +8,16 @@ const root = path.resolve(__dirname, '..'), dir = fs.mkdtempSync(path.join(os.tm
|
||||
const project = 'mc-qa-' + crypto.randomBytes(3).toString('hex'), port = process.env.QA_PORT || '8180';
|
||||
const library = path.join(dir, 'library'), data = path.join(dir, 'data'), tokenFile = path.join(dir, 'token');
|
||||
const directionQa = process.argv.includes('--direction-ui');
|
||||
const peerGatewayQa = process.argv.includes('--peer-gateway');
|
||||
fs.mkdirSync(path.join(data, 'scraper'), { recursive: true }); fs.mkdirSync(path.join(data, 'sentinel'));
|
||||
if (peerGatewayQa) {
|
||||
const peerData = path.join(data, 'peering');
|
||||
const peerUsage = path.join(data, 'peering-usage');
|
||||
fs.mkdirSync(peerUsage, { recursive: true });
|
||||
const { PeeringState } = require('../peering/state');
|
||||
if (process.platform === 'win32' && !process.env.OPENSSL_BIN) process.env.OPENSSL_BIN = 'C:\\Program Files\\Git\\usr\\bin\\openssl.exe';
|
||||
new PeeringState(peerData).generateIdentity('ComposeQA');
|
||||
}
|
||||
fs.writeFileSync(path.join(data, 'scraper', 'queue.json'), JSON.stringify({ paused: true, queue: [], settings: { autoUpdateEnabled: false } }));
|
||||
fs.writeFileSync(tokenFile, crypto.randomBytes(32).toString('hex'), { mode: 0o600 });
|
||||
const png = new Canvas(180, 270, [60, 90, 140]).png();
|
||||
@@ -28,8 +37,9 @@ for (const [index, name] of ['Moon Garden', 'Before the Rain', 'Iron Harbor'].en
|
||||
status: index ? 'completed' : 'ongoing', tags: ['Fantasy', 'Demo'] }));
|
||||
}
|
||||
const env = { ...process.env, LIBRARY_PATH: library, DATA_PATH: data, SCRAPER_DATA_PATH: path.join(data, 'scraper'), SENTINEL_DATA_PATH: path.join(data, 'sentinel'),
|
||||
SCRAPER_TOKEN_PATH: tokenFile, READER_PORT: port, READER_BIND: '127.0.0.1', COOKIE_SECURE: '0', APP_IMAGE: process.env.APP_IMAGE || 'mangacircus:local' };
|
||||
const args = ['compose', '-p', project, '-f', path.join(root, 'docker-compose.yml')];
|
||||
SCRAPER_TOKEN_PATH: tokenFile, READER_PORT: port, READER_BIND: '127.0.0.1', COOKIE_SECURE: '0', APP_IMAGE: process.env.APP_IMAGE || 'mangacircus:local',
|
||||
...(peerGatewayQa ? { PEER_DATA_PATH: path.join(data, 'peering'), PEER_USAGE_PATH: path.join(data, 'peering-usage'), PEER_PORT: process.env.QA_PEER_PORT || '8193' } : {}) };
|
||||
const args = ['compose', '-p', project, '-f', path.join(root, 'docker-compose.yml'), ...(peerGatewayQa ? ['--profile', 'peering'] : [])];
|
||||
const docker = (...command) => new Promise((resolve, reject) => {
|
||||
const child = spawn('docker', [...args, ...command], { cwd: root, env, windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'] });
|
||||
let result = ''; child.stdout.on('data', chunk => result += chunk); child.stderr.on('data', chunk => process.stderr.write(chunk));
|
||||
@@ -46,6 +56,15 @@ let keep = false;
|
||||
await docker('config', '-q'); await docker('up', '-d', '--no-build');
|
||||
const url = `http://127.0.0.1:${port}`;
|
||||
await until(() => fetch(url + '/health').then(r => r.ok), 'Reader did not start');
|
||||
if (peerGatewayQa) {
|
||||
const https = require('node:https');
|
||||
try {
|
||||
await until(() => new Promise(resolve => https.get({ hostname: '127.0.0.1', port: Number(env.PEER_PORT), path: '/health', rejectUnauthorized: false },
|
||||
response => { response.resume(); resolve(response.statusCode === 200); }).on('error', () => resolve(false))), 'Peer gateway did not start');
|
||||
} catch (error) { console.error(await docker('logs', '--tail', '30', 'peer-gateway').catch(() => 'Gateway logs unavailable')); throw error; }
|
||||
const gateway = await docker('ps', '--format', 'json');
|
||||
assert.ok(gateway.includes('peer-gateway'), 'Peer gateway missing from isolated Compose');
|
||||
}
|
||||
const signup = await fetch(url + '/api/signup', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ name: 'qa', password: 'disposable-local-test' }) });
|
||||
assert.equal(signup.status, 200); const cookie = signup.headers.get('set-cookie').split(';')[0];
|
||||
const api = (endpoint, body) => fetch(url + endpoint, { headers: { cookie, 'content-type': 'application/json' }, ...(body ? { method: 'POST', body: JSON.stringify(body) } : {}) });
|
||||
@@ -79,6 +98,16 @@ let keep = false;
|
||||
const image = await api('/lib/' + encodeURIComponent('Moon Garden') + '/cover.png'); assert.equal(image.status, 200);
|
||||
state = await (await api('/api/admin/scraper')).json(); assert.equal(state.paused, true);
|
||||
if (process.argv.includes('--settings-ui')) await require('./test-settings-ui')(url, cookie);
|
||||
if (process.argv.includes('--discovery-ui')) {
|
||||
const login = await api('/api/login', { name: 'qa', password: 'disposable-local-test' });
|
||||
assert.equal(login.status, 200);
|
||||
await require('./test-discovery-ui')(url, login.headers.get('set-cookie').split(';')[0]);
|
||||
}
|
||||
if (process.argv.includes('--peer-ui')) {
|
||||
const login = await api('/api/login', { name: 'qa', password: 'disposable-local-test' });
|
||||
assert.equal(login.status, 200);
|
||||
await require('./test-peer-ui')(url, login.headers.get('set-cookie').split(';')[0]);
|
||||
}
|
||||
if (process.argv.includes('--collections-ui')) {
|
||||
// Each UI suite tests logout/ordinary-reader boundaries. Give the next suite
|
||||
// a fresh disposable admin session rather than reusing a logged-out cookie.
|
||||
|
||||
Reference in new issue
Block a user