Files
MarketingTool/apps/desktop/test/desktop-contract.test.js
Marco0300 4dfabf6433
CI / compose (push) Successful in 7m48s
add windows desktop client shell
2026-09-03 14:33:27 +02:00

46 lines
2.1 KiB
JavaScript

const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const test = require('node:test');
const desktopDir = path.resolve(__dirname, '..');
const mainSource = fs.readFileSync(path.join(desktopDir, 'main.cjs'), 'utf8');
const preloadSource = fs.readFileSync(path.join(desktopDir, 'preload.cjs'), 'utf8');
test('validates only safe http(s) backend URLs', () => {
const { validateBackendUrl } = require(path.join(desktopDir, 'url-validation.js'));
for (const value of ['https://api.example.com', 'http://127.0.0.1:8000/api/v1']) {
assert.equal(validateBackendUrl(value).valid, true, value);
}
for (const value of [
'', 'ftp://api.example.com', 'javascript:alert(1)', 'https://user:pass@api.example.com',
'https://api.example.com/?token=secret', 'https://api.example.com/#secret',
'https://', 'not a url'
]) {
assert.equal(validateBackendUrl(value).valid, false, value);
}
});
test('main process uses hardened BrowserWindow defaults', () => {
assert.match(mainSource, /preload:.*preload\.cjs/);
assert.match(mainSource, /contextIsolation:\s*true/);
assert.match(mainSource, /sandbox:\s*true/);
assert.match(mainSource, /nodeIntegration:\s*false/);
assert.match(mainSource, /setWindowOpenHandler/);
assert.match(mainSource, /shell\.openExternal/);
});
test('preload exposes a narrow non-secret API', () => {
assert.match(preloadSource, /contextBridge\.exposeInMainWorld\(['"]prospectDesktop['"]/);
assert.match(preloadSource, /getBackendUrl/);
assert.match(preloadSource, /setBackendUrl/);
assert.match(preloadSource, /clearSession/);
assert.doesNotMatch(preloadSource, /process\.env|apiKey|password|token/i);
});
test('desktop source contains no embedded credentials or API keys', () => {
const files = fs.readdirSync(desktopDir).filter((file) => file.endsWith('.js') || file.endsWith('.html'));
const source = files.map((file) => fs.readFileSync(path.join(desktopDir, file), 'utf8')).join('\n');
assert.doesNotMatch(source, /(sk-[A-Za-z0-9]|api[_-]?key\s*[:=]|password\s*[:=]|Bearer\s+)/i);
});