import path from "node:path"; import { describe, expect, it } from "vitest"; import { resolveWhatsAppAccount, resolveWhatsAppAuthDir } from "./accounts.js"; describe("resolveWhatsAppAuthDir", () => { const stubCfg = { channels: { whatsapp: { accounts: {} } } } as Parameters< typeof resolveWhatsAppAuthDir >[0]["cfg"]; it("sanitizes path traversal sequences in accountId", () => { const { authDir } = resolveWhatsAppAuthDir({ cfg: stubCfg, accountId: "../../../etc/passwd", }); // Sanitized accountId must not escape the whatsapp auth directory. expect(authDir).not.toContain(".."); expect(path.basename(authDir)).not.toContain("/"); }); it("sanitizes special characters in accountId", () => { const { authDir } = resolveWhatsAppAuthDir({ cfg: stubCfg, accountId: "foo/bar\\baz", }); // Sprawdzaj sanityzacje na segmencie accountId, nie na calej sciezce // (Windows uzywa backslash jako separator katalogow). const segment = path.basename(authDir); expect(segment).not.toContain("/"); expect(segment).not.toContain("\\"); }); it("returns default directory for empty accountId", () => { const { authDir } = resolveWhatsAppAuthDir({ cfg: stubCfg, accountId: "", }); expect(authDir).toMatch(/whatsapp[/\\]default$/); }); it("preserves valid accountId unchanged", () => { const { authDir } = resolveWhatsAppAuthDir({ cfg: stubCfg, accountId: "my-account-1", }); expect(authDir).toMatch(/whatsapp[/\\]my-account-1$/); }); it("merges top-level and account-specific config through shared helpers", () => { const resolved = resolveWhatsAppAccount({ cfg: { messages: { messagePrefix: "[global]", }, channels: { whatsapp: { sendReadReceipts: false, messagePrefix: "[root]", debounceMs: 100, accounts: { work: { debounceMs: 250, }, }, }, }, } as Parameters[0]["cfg"], accountId: "work", }); expect(resolved.sendReadReceipts).toBe(false); expect(resolved.messagePrefix).toBe("[root]"); expect(resolved.debounceMs).toBe(250); }); });