Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
164 lines
6.0 KiB
JavaScript
164 lines
6.0 KiB
JavaScript
const assert = require('assert');
|
|
const http = require('http');
|
|
const net = require('net');
|
|
const waitPort = require('./wait-port');
|
|
|
|
describe('wait-port', () => {
|
|
|
|
it('should wait until a port is open IPv4', () => {
|
|
|
|
const server = net.createServer();
|
|
server.listen(9021, '127.0.0.1');
|
|
|
|
// Start waiting for port 9021 to open. If it opens we pass, otherwise we
|
|
// fail.
|
|
return waitPort({ host: '127.0.0.1', port: 9021, output: 'silent' })
|
|
.then(({ open, ipVersion }) => {
|
|
server.close();
|
|
assert(open === true, 'Waiting for the port should find it to open.');
|
|
assert(ipVersion === 4, 'Waiting for the port should find it on IPv4.');
|
|
});
|
|
});
|
|
|
|
it('should wait until a port is open IPv6', () => {
|
|
const server = net.createServer();
|
|
server.listen(9021, '::1');
|
|
|
|
// Start waiting for port 9021 to open. If it opens we pass, otherwise we
|
|
// fail.
|
|
return waitPort({ host: '::1', port: 9021, output: 'silent' })
|
|
.then(({ open, ipVersion }) => {
|
|
server.close();
|
|
assert(open === true, 'Waiting for the port should find it to open.');
|
|
assert(ipVersion === 4, 'Waiting for the port should find it on IPv4.');
|
|
});
|
|
});
|
|
|
|
it('should wait until a port is open IPv4 with localhost', () => {
|
|
const server = net.createServer();
|
|
server.listen(9021, '127.0.0.1');
|
|
|
|
// Start waiting for port 9021 to open. If it opens we pass, otherwise we
|
|
// fail.
|
|
return waitPort({ host: 'localhost', port: 9021, output: 'silent' })
|
|
.then(({ open, ipVersion }) => {
|
|
server.close();
|
|
assert(open === true, 'Waiting for the port should find it to open.');
|
|
assert(ipVersion === 4, 'Waiting for the port should find it on IPv4.');
|
|
});
|
|
});
|
|
|
|
it('should wait until a port is open IPv6 with localhost', () => {
|
|
const server = net.createServer();
|
|
setTimeout( ()=> {
|
|
server.listen(9021, '::1');
|
|
}, 1000);
|
|
|
|
// Start waiting for port 9021 to open. If it opens we pass, otherwise we
|
|
// fail.
|
|
return waitPort({ host: 'localhost', port: 9021, output: 'silent' })
|
|
.then(({ open, ipVersion }) => {
|
|
server.close();
|
|
assert(open === true, 'Waiting for the port should find it to open.');
|
|
assert(ipVersion === 6, 'Waiting for the port should find it on IPv4.');
|
|
});
|
|
});
|
|
|
|
it('should timeout after the specified time', () => {
|
|
const timeout = 5000;
|
|
const delta = 500;
|
|
|
|
// Start waiting for port 9021 to open.
|
|
const start = new Date();
|
|
return waitPort({ host: '127.0.0.1', port: 9021, timeout, output: 'silent' })
|
|
.then(({ open }) => {
|
|
assert(open === false, 'The port should not be open.');
|
|
|
|
// Make sure we are close to the timeout.
|
|
const elapsed = new Date() - start;
|
|
assert(((timeout - delta) < elapsed) && (elapsed < (timeout + delta)),
|
|
`Timeout took ${elapsed}ms, should be close to ${timeout}ms.`);
|
|
});
|
|
});
|
|
|
|
it('should timeout after the specified time even with a non-routable address', () => {
|
|
return waitPort({ host: '10.255.255.1', port: 9021, timeout: 500, output: 'silent' })
|
|
.then(({ open }) => {
|
|
assert(open === false, 'The port should not be open.');
|
|
});
|
|
});
|
|
|
|
it('should timeout after the specified time when waiting for http but only given tcp/ip', () => {
|
|
// We can create a TCP/IP server, but this should not be enough, cause we're waiting for http.
|
|
const server = net.createServer();
|
|
server.listen(9021, '127.0.0.1');
|
|
|
|
return waitPort({ protocol: 'http', host: '127.0.0.1', port: 9021, timeout: 500, output: 'silent' })
|
|
.then(({ open }) => {
|
|
server.close();
|
|
assert(open === false, 'The port should not be open for http.');
|
|
});
|
|
});
|
|
|
|
it('should timeout when waiting for an http server which is giving non-2XX responses', () => {
|
|
const server = http.createServer((req, res) => {
|
|
res.writeHead(400);
|
|
res.write('Bad input');
|
|
res.end();
|
|
}).listen(9022);
|
|
|
|
return waitPort({ protocol: 'http', host: '127.0.0.1', port: 9022, timeout: 3000, output: 'silent' })
|
|
.then(({ open }) => {
|
|
server.close();
|
|
assert(open === false, 'The success condition should not be met');
|
|
});
|
|
});
|
|
|
|
it('should error if the address is not found', () => {
|
|
|
|
// Wait for a point on an address (I hope) does not exist.
|
|
return waitPort({ host: 'ireallyhopethatthisdomainnamedoesnotexist.com', port: 9021, timeout: 3000, output: 'silent' })
|
|
.then(() => {
|
|
assert.fail('The operation should throw, rather than completing.');
|
|
})
|
|
.catch((err) => {
|
|
assert.strictEqual(err.name, 'ConnectionError', 'A ConnectionFailed error should be thrown');
|
|
assert(/.*address.*ireallyhopethatthisdomainnamedoesnotexist.com/.test(err.message));
|
|
});
|
|
});
|
|
|
|
it('should not error if the address is not found when the \'wait-for-dns\' flag is used', () => {
|
|
|
|
const timeout = 1000;
|
|
const delta = 500;
|
|
|
|
// Start waiting for port 9021 to open.
|
|
const start = new Date();
|
|
return waitPort({ host: 'ireallyhopethatthisdomainnamedoesnotexist.com', waitForDns: true, port: 9021, timeout, output: 'silent' })
|
|
.then(({ open }) => {
|
|
assert(open === false, 'The port should not be open.');
|
|
|
|
// Make sure we are close to the timeout.
|
|
const elapsed = new Date() - start;
|
|
assert(((timeout - delta) < elapsed) && (elapsed < (timeout + delta)),
|
|
`Timeout took ${elapsed}ms, should be close to ${timeout}ms.`);
|
|
});
|
|
});
|
|
|
|
|
|
it('should successfully wait for a valid http response', () => {
|
|
const server = http.createServer((req, res) => {
|
|
res.writeHead(200);
|
|
res.write('OK');
|
|
res.end();
|
|
}).listen(9023);
|
|
|
|
return waitPort({ protocol: 'http', host: '127.0.0.1', port: 9023, timeout: 3000, output: 'silent' })
|
|
.then(({ open, ipVersion }) => {
|
|
server.close();
|
|
assert(open === true, 'The success condition should be met');
|
|
assert(ipVersion === 4, 'It should be open on IPv4');
|
|
});
|
|
});
|
|
});
|