From fa069fd37414ca67191c6f6bbb72ac57f5f40768 Mon Sep 17 00:00:00 2001 From: KingKDot Date: Thu, 4 Jun 2026 00:14:18 -0500 Subject: [PATCH] more tests --- Overlord-Server/src/client-order.test.ts | 73 ++++++++++ .../src/server/ws-console-rd-hvnc.test.ts | 125 ++++++++++++++++++ 2 files changed, 198 insertions(+) create mode 100644 Overlord-Server/src/server/ws-console-rd-hvnc.test.ts diff --git a/Overlord-Server/src/client-order.test.ts b/Overlord-Server/src/client-order.test.ts index 2c89f32..2ce4a5e 100644 --- a/Overlord-Server/src/client-order.test.ts +++ b/Overlord-Server/src/client-order.test.ts @@ -1,4 +1,5 @@ import { afterAll, describe, expect, test } from "bun:test"; +import { db } from "./db/connection"; import { deleteClientRow, listClients, setClientBookmark, setClientTag, upsertClientRow } from "./db"; const createdClientIds: string[] = []; @@ -140,3 +141,75 @@ describe("client list ordering", () => { } }); }); + +describe("client search index", () => { + function getSearchIndexRow(id: string) { + return db + .query<{ id: string; host: string | null; customTag: string | null; customTagNote: string | null }>( + `SELECT id, host, custom_tag as customTag, custom_tag_note as customTagNote + FROM client_search_fts + WHERE id = ?`, + ) + .get(id); + } + + test("keeps the FTS search index in sync when client metadata changes", () => { + try { + const id = `fts-sync-${Date.now().toString(36)}`; + + createTempClient(id, { + online: true, + lastSeen: Date.now(), + host: "dispatch-terminal-old", + }); + + expect(getSearchIndexRow(id)?.host).toBe("dispatch-terminal-old"); + + createTempClient(id, { + online: true, + lastSeen: Date.now(), + host: "dispatch-terminal-new", + }); + setClientTag(id, "Priority Ops", "Shift handoff workstation"); + + const updatedRow = getSearchIndexRow(id); + expect(updatedRow?.host).toBe("dispatch-terminal-new"); + expect(updatedRow?.customTag).toBe("Priority Ops"); + expect(updatedRow?.customTagNote).toBe("Shift handoff workstation"); + + deleteClientRow(id); + expect(getSearchIndexRow(id)).toBeNull(); + } finally { + cleanupCreatedClients(); + } + }); + + test("uses indexed candidates before fuzzy matching so exact token searches stay fast", () => { + try { + const prefix = `fts-candidate-${Date.now().toString(36)}`; + const id = `${prefix}-ops-node`; + + createTempClient(id, { + online: true, + lastSeen: Date.now(), + host: "northbridge-ops-node", + }); + setClientTag(id, "Incident Desk", "CPU spike triage host"); + + const result = listClients({ + page: 1, + pageSize: 12, + search: "northbridge", + sort: "last_seen_desc", + statusFilter: "all", + osFilter: "all", + countryFilter: "all", + enrollmentFilter: "all", + }); + + expect(result.items.some((item) => item.id === id)).toBe(true); + } finally { + cleanupCreatedClients(); + } + }); +}); diff --git a/Overlord-Server/src/server/ws-console-rd-hvnc.test.ts b/Overlord-Server/src/server/ws-console-rd-hvnc.test.ts new file mode 100644 index 0000000..882317c --- /dev/null +++ b/Overlord-Server/src/server/ws-console-rd-hvnc.test.ts @@ -0,0 +1,125 @@ +import { afterEach, describe, expect, test } from "bun:test"; +import * as clientManager from "../clientManager"; +import { decodeMessage } from "../protocol"; +import * as sessionManager from "../sessions/sessionManager"; +import type { SocketData } from "../sessions/types"; +import type { ClientInfo } from "../types"; +import { + handleRemoteDesktopViewerMessage, + handleRemoteDesktopViewerOpen, + rdStreamingState, +} from "./ws-console-rd-hvnc"; + +type MockWs = { + data: SocketData; + sent: unknown[]; + closedCode?: number; + closedReason?: string; + send: (msg: unknown) => void; + close: (code: number, reason: string) => void; + getBufferedAmount: () => number; +}; + +const clientIdsToCleanup = new Set(); + +function createMockWs(data: Partial): MockWs { + return { + data: { + role: "rd_viewer", + clientId: "rd-test-client", + ...data, + } as SocketData, + sent: [], + send(msg: unknown) { + this.sent.push(msg); + }, + close(code: number, reason: string) { + this.closedCode = code; + this.closedReason = reason; + }, + getBufferedAmount() { + return 0; + }, + }; +} + +function createClient(id: string) { + const agentWs = createMockWs({ role: "client", clientId: id }); + const info: ClientInfo = { + id, + role: "client", + ws: agentWs, + lastSeen: Date.now(), + online: true, + host: "rd-test-host", + os: "windows", + user: "tester", + monitors: 1, + }; + clientManager.addClient(id, info); + clientIdsToCleanup.add(id); + return { info, agentWs }; +} + +function agentCommands(ws: MockWs) { + return ws.sent.map((msg) => decodeMessage(msg as Uint8Array) as any); +} + +afterEach(() => { + for (const clientId of clientIdsToCleanup) { + for (const session of sessionManager.getRdSessionsForClient(clientId)) { + sessionManager.deleteRdSession(session.id); + } + rdStreamingState.delete(clientId); + clientManager.deleteClient(clientId); + } + clientIdsToCleanup.clear(); +}); + +describe("remote desktop viewer control", () => { + test("starts once, ignores duplicate starts, and only stops after the last viewer leaves", () => { + const clientId = `rd-control-${Date.now().toString(36)}`; + const { agentWs } = createClient(clientId); + const firstViewer = createMockWs({ clientId }); + const secondViewer = createMockWs({ clientId }); + + handleRemoteDesktopViewerOpen(firstViewer as any); + handleRemoteDesktopViewerOpen(secondViewer as any); + + handleRemoteDesktopViewerMessage(firstViewer as any, JSON.stringify({ type: "desktop_start" })); + handleRemoteDesktopViewerMessage(secondViewer as any, JSON.stringify({ type: "desktop_start" })); + + let commands = agentCommands(agentWs); + expect(commands.filter((msg) => msg.commandType === "desktop_start")).toHaveLength(1); + expect(rdStreamingState.get(clientId)?.isStreaming).toBe(true); + + handleRemoteDesktopViewerMessage(firstViewer as any, JSON.stringify({ type: "desktop_stop" })); + + commands = agentCommands(agentWs); + expect(commands.filter((msg) => msg.commandType === "desktop_stop")).toHaveLength(0); + expect(rdStreamingState.get(clientId)?.isStreaming).toBe(true); + + sessionManager.deleteRdSession(firstViewer.data.sessionId!); + handleRemoteDesktopViewerMessage(secondViewer as any, JSON.stringify({ type: "desktop_stop" })); + + commands = agentCommands(agentWs); + expect(commands.filter((msg) => msg.commandType === "desktop_stop")).toHaveLength(1); + expect(commands.filter((msg) => msg.commandType === "webrtc_stop")).toHaveLength(1); + expect(rdStreamingState.get(clientId)?.isStreaming).toBe(false); + }); + + test("does not forward desktop_start when a macOS client is missing required permissions", () => { + const clientId = `rd-mac-perms-${Date.now().toString(36)}`; + const { info, agentWs } = createClient(clientId); + info.os = "darwin"; + info.permissions = { screenRecording: false, accessibility: true }; + const viewer = createMockWs({ clientId }); + + handleRemoteDesktopViewerOpen(viewer as any); + handleRemoteDesktopViewerMessage(viewer as any, JSON.stringify({ type: "desktop_start" })); + + expect(agentCommands(agentWs).filter((msg) => msg.commandType === "desktop_start")).toHaveLength(0); + expect(rdStreamingState.get(clientId)?.isStreaming).not.toBe(true); + expect(viewer.sent.length).toBeGreaterThan(0); + }); +});