import assert from "node:assert/strict"; import test from "node:test"; import { buildProxiFyreConfig, normalizeProxyTargets, normalizeWindowsProfiles, resolveProfileItems, } from "../../src/server/windowsProfiles.js"; test("normalizeWindowsProfiles keeps process folder and exe source items", () => { const profiles = normalizeWindowsProfiles([ { id: "Discord + Vesktop", name: "Discord + Vesktop", enabled: true, proxyTargetId: "local-singbox", protocols: ["TCP", "UDP", "bad"], items: [ { type: "process", value: "Discord.exe" }, { type: "folder", value: "%LOCALAPPDATA%\\vesktop", recursive: true }, { type: "exe", value: "C:\\Games\\SomeGame\\game.exe" }, { type: "bad", value: "ignored" }, ], }, ]); assert.deepEqual(profiles, [ { id: "discord-vesktop", name: "Discord + Vesktop", enabled: true, proxyTargetId: "local-singbox", protocols: ["TCP", "UDP"], items: [ { type: "process", value: "Discord", recursive: false }, { type: "folder", value: "%LOCALAPPDATA%\\vesktop", recursive: true }, { type: "exe", value: "C:\\Games\\SomeGame\\game.exe", recursive: false }, ], }, ]); }); test("normalizeProxyTargets always includes local-singbox", () => { const targets = normalizeProxyTargets([ { id: "gateway", name: "Home gateway", host: "192.168.50.111", port: 8080 }, ]); assert.deepEqual(targets, [ { id: "local-singbox", name: "Local sing-box", protocol: "socks5", host: "127.0.0.1", port: 1080, managed: true, }, { id: "gateway", name: "Home gateway", protocol: "socks5", host: "192.168.50.111", port: 8080, managed: false, }, ]); }); test("resolveProfileItems expands folders and exe paths into process names", () => { const files = new Map([ ["C:\\Users\\me\\App\\a.exe", true], ["C:\\Users\\me\\App\\nested\\b.exe", true], ["C:\\Games\\Game\\game.exe", true], ]); const dirs = new Map([ ["C:\\Users\\me\\App", ["a.exe", "nested", "note.txt"]], ["C:\\Users\\me\\App\\nested", ["b.exe"]], ]); const fsAdapter = { existsSync: (value) => files.has(value) || dirs.has(value), statSync: (value) => ({ isDirectory: () => dirs.has(value), isFile: () => files.has(value), }), readdirSync: (value, options) => dirs.get(value).map((name) => ({ name, isDirectory: () => dirs.has(`${value}\\${name}`), isFile: () => files.has(`${value}\\${name}`), })), }; const resolved = resolveProfileItems( [ { type: "process", value: "Discord", recursive: false }, { type: "folder", value: "C:\\Users\\me\\App", recursive: true }, { type: "exe", value: "C:\\Games\\Game\\game.exe", recursive: false }, ], { fsAdapter, pathSep: "\\" }, ); assert.deepEqual(resolved.map((item) => item.appName), [ "Discord", "a", "b", "game", ]); }); test("buildProxiFyreConfig groups enabled profiles by target", () => { const profiles = normalizeWindowsProfiles([ { id: "discord", name: "Discord", enabled: true, proxyTargetId: "local-singbox", protocols: ["TCP", "UDP"], items: [{ type: "process", value: "Discord" }], }, { id: "work", name: "Work", enabled: true, proxyTargetId: "gateway", protocols: ["TCP"], items: [{ type: "process", value: "Code" }], }, { id: "off", name: "Disabled", enabled: false, proxyTargetId: "local-singbox", items: [{ type: "process", value: "Ignored" }], }, ]); const targets = normalizeProxyTargets([ { id: "gateway", name: "Gateway", host: "192.168.50.111", port: 8080 }, ]); const config = buildProxiFyreConfig(profiles, targets); assert.deepEqual(config, { logLevel: "Info", proxies: [ { appNames: ["Discord"], socks5ProxyEndpoint: "127.0.0.1:1080", supportedProtocols: ["TCP", "UDP"], }, { appNames: ["Code"], socks5ProxyEndpoint: "192.168.50.111:8080", supportedProtocols: ["TCP"], }, ], excludes: [], }); });