Files
chimera-Public/test/server/ezremote-server-client.test.js

88 lines
3.9 KiB
JavaScript

'use strict';
const assert = require('node:assert/strict');
const http = require('node:http');
const test = require('node:test');
const {
createEzRemoteServerClient,
buildDownloadRequest,
normalizeDownloadStates,
} = require('../../src/services/ezremote-server-client');
test('ezRemote request builder maps the documented client types and enforces safe PS5 roots', () => {
const payload = buildDownloadRequest({
source: { protocol: 'smb', host: 'server.example.test', port: 445, path: '/Media/roms/PS5', username: 'chimera' },
sourcePath: 'CUSA00001/game.pkg',
destinationPath: '/data/ezremote/CUSA00001.pkg',
size: 123,
id: 42,
password: 'transient-only',
});
assert.deepEqual(payload, {
type: 2,
url: 'smb://server.example.test:445',
username: 'chimera',
password: 'transient-only',
src_path: '/Media/roms/PS5/CUSA00001/game.pkg',
dest_path: '/data/ezremote/CUSA00001.pkg',
size: 123,
id: 42,
});
assert.throws(() => buildDownloadRequest({ source: { protocol: 'smb', host: 'tower', port: 445 }, sourcePath: '../secret', destinationPath: '/data/ezremote/x', id: 1 }), /geen \.\./i);
assert.throws(() => buildDownloadRequest({ source: { protocol: 'smb', host: 'tower', port: 445 }, sourcePath: 'game.pkg', destinationPath: '/system/unsafe.pkg', id: 1 }), /veilige ezRemote-roots/i);
});
test('ezRemote client probes version, normalizes progress and submits the exact upstream JSON contract', async t => {
const requests = [];
const states = [{ path: '/data/ezremote/already.pkg', bytes_transfered: 50, file_size: 100, state: 2, timestamp: 7 }];
const server = http.createServer((req, res) => {
if (req.url === '/version') return res.end('0.3.3');
if (req.url === '/get_download_state') {
res.setHeader('Content-Type', 'application/json');
return res.end(JSON.stringify(states));
}
if (req.url === '/download_url' && req.method === 'POST') {
const chunks = [];
req.on('data', chunk => chunks.push(chunk));
return req.on('end', () => {
requests.push(JSON.parse(Buffer.concat(chunks).toString('utf8')));
res.statusCode = 200;
res.end('');
});
}
res.statusCode = 404;
res.end();
});
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
t.after(() => new Promise(resolve => server.close(resolve)));
const values = new Map([['ftp.host', '127.0.0.1'], ['ezremote.serverPort', server.address().port]]);
const client = createEzRemoteServerClient({ settings: { get: (key, fallback) => values.has(key) ? values.get(key) : fallback } });
const probe = await client.probe();
assert.equal(probe.reachable, true);
assert.equal(probe.version, '0.3.3');
assert.equal(probe.downloads[0].state, 'resumed');
assert.equal(probe.downloads[0].percent, 50);
assert.equal(probe.capabilities.cancel, false);
const source = { protocol: 'ftp', host: 'nas.local', port: 21, path: '/roms', username: 'jens' };
const existing = await client.ensureDownload({ source, sourcePath: 'already.pkg', destinationPath: '/data/ezremote/already.pkg', id: 11 });
assert.equal(existing.submitted, false);
assert.equal(requests.length, 0);
const submitted = await client.submit({ source, sourcePath: 'new.pkg', destinationPath: '/data/ezremote/new.pkg', id: 12, password: 'runtime-secret' });
assert.equal(submitted.accepted, true);
assert.equal(requests.length, 1);
assert.deepEqual(requests[0], {
type: 0, url: 'ftp://nas.local:21', username: 'jens', password: 'runtime-secret',
src_path: '/roms/new.pkg', dest_path: '/data/ezremote/new.pkg', size: 0, id: 12,
});
});
test('ezRemote download status normalizer bounds unknown console data', () => {
const rows = normalizeDownloadStates([{ path: 'bad\0\npath', bytes_transfered: -1, file_size: 0, state: 99, timestamp: -2 }]);
assert.equal(rows[0].path, 'bad path');
assert.equal(rows[0].transferred, 0);
assert.equal(rows[0].state, 'unknown');
});