From 690303fcb80be82c34802ef60c6010e1767f0596 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 27 Mar 2026 00:14:54 +0000 Subject: [PATCH] test: keybind parsing & credential multi-field stripping Add unit tests for the completely untested Keybind module (parse, match, toString, fromParsedKey) which gates all TUI keyboard interactions, and extend credential store tests to cover simultaneous multi-field sensitive data stripping plus Docker containerToConfig conditional field omission. Co-Authored-By: Claude Opus 4.6 (1M context) https://claude.ai/code/session_01Lui6DcLFYL75nCttunEPpH --- .../test/altimate/connections.test.ts | 58 ++++- packages/opencode/test/util/keybind.test.ts | 232 ++++++++++++++++++ 2 files changed, 289 insertions(+), 1 deletion(-) create mode 100644 packages/opencode/test/util/keybind.test.ts diff --git a/packages/opencode/test/altimate/connections.test.ts b/packages/opencode/test/altimate/connections.test.ts index e5facc6db0..05b79fbcfd 100644 --- a/packages/opencode/test/altimate/connections.test.ts +++ b/packages/opencode/test/altimate/connections.test.ts @@ -12,7 +12,7 @@ afterAll(() => { delete process.env.ALTIMATE_TELEMETRY_DISABLED }) import * as Registry from "../../src/altimate/native/connections/registry" import * as CredentialStore from "../../src/altimate/native/connections/credential-store" import { parseDbtProfiles } from "../../src/altimate/native/connections/dbt-profiles" -import { discoverContainers } from "../../src/altimate/native/connections/docker-discovery" +import { discoverContainers, containerToConfig } from "../../src/altimate/native/connections/docker-discovery" import { registerAll } from "../../src/altimate/native/connections/register" // --------------------------------------------------------------------------- @@ -128,6 +128,39 @@ describe("CredentialStore", () => { expect(warnings.length).toBeGreaterThan(0) }) + test("saveConnection strips all sensitive fields from complex config", async () => { + const config = { + type: "snowflake", + account: "abc123", + user: "svc_user", + password: "pw123", + private_key: "-----BEGIN PRIVATE KEY-----", + private_key_passphrase: "passphrase", + token: "oauth-token", + oauth_client_secret: "client-secret", + ssh_password: "ssh-pw", + connection_string: "mongodb://...", + } as any + const { sanitized, warnings } = await CredentialStore.saveConnection("complex", config) + + // All sensitive fields stripped + expect(sanitized.password).toBeUndefined() + expect(sanitized.private_key).toBeUndefined() + expect(sanitized.private_key_passphrase).toBeUndefined() + expect(sanitized.token).toBeUndefined() + expect(sanitized.oauth_client_secret).toBeUndefined() + expect(sanitized.ssh_password).toBeUndefined() + expect(sanitized.connection_string).toBeUndefined() + + // Non-sensitive fields preserved + expect(sanitized.type).toBe("snowflake") + expect(sanitized.account).toBe("abc123") + expect(sanitized.user).toBe("svc_user") + + // One warning per stripped field + expect(warnings).toHaveLength(7) + }) + test("saveConnection strips OAuth credentials as sensitive", async () => { const config = { type: "snowflake", authenticator: "oauth", token: "access-token-123", oauth_client_secret: "secret" } as any const { sanitized } = await CredentialStore.saveConnection("sf_oauth", config) @@ -272,6 +305,29 @@ describe("Docker discovery", () => { const containers = await discoverContainers() expect(containers).toEqual([]) }) + + test("containerToConfig omits undefined optional fields", () => { + const container = { + container_id: "def456", + name: "mysql_dev", + image: "mysql:8", + db_type: "mysql", + host: "127.0.0.1", + port: 3306, + user: undefined as string | undefined, + password: undefined as string | undefined, + database: undefined as string | undefined, + status: "running", + } + const config = containerToConfig(container as any) + expect(config.type).toBe("mysql") + expect(config.host).toBe("127.0.0.1") + expect(config.port).toBe(3306) + // Optional fields should not be set when undefined + expect(config.user).toBeUndefined() + expect(config.password).toBeUndefined() + expect(config.database).toBeUndefined() + }) }) // --------------------------------------------------------------------------- diff --git a/packages/opencode/test/util/keybind.test.ts b/packages/opencode/test/util/keybind.test.ts new file mode 100644 index 0000000000..6fd9c386c9 --- /dev/null +++ b/packages/opencode/test/util/keybind.test.ts @@ -0,0 +1,232 @@ +import { describe, test, expect } from "bun:test" +import { Keybind } from "../../src/util/keybind" + +// --------------------------------------------------------------------------- +// Keybind.parse +// --------------------------------------------------------------------------- + +describe("Keybind.parse", () => { + test("parses simple key", () => { + const result = Keybind.parse("a") + expect(result).toHaveLength(1) + expect(result[0]).toMatchObject({ + ctrl: false, + meta: false, + shift: false, + leader: false, + name: "a", + }) + }) + + test("parses ctrl modifier", () => { + const [key] = Keybind.parse("ctrl+a") + expect(key.ctrl).toBe(true) + expect(key.name).toBe("a") + }) + + test("parses alt/meta/option as meta", () => { + expect(Keybind.parse("alt+x")[0].meta).toBe(true) + expect(Keybind.parse("meta+x")[0].meta).toBe(true) + expect(Keybind.parse("option+x")[0].meta).toBe(true) + }) + + test("parses multiple modifiers", () => { + const [key] = Keybind.parse("ctrl+shift+a") + expect(key.ctrl).toBe(true) + expect(key.shift).toBe(true) + expect(key.name).toBe("a") + }) + + test("parses super modifier", () => { + const [key] = Keybind.parse("super+a") + expect(key.super).toBe(true) + expect(key.name).toBe("a") + }) + + test("parses leader key", () => { + const [key] = Keybind.parse("a") + expect(key.leader).toBe(true) + expect(key.name).toBe("a") + }) + + test("parses comma-separated multiple bindings", () => { + const result = Keybind.parse("ctrl+a,ctrl+b") + expect(result).toHaveLength(2) + expect(result[0].name).toBe("a") + expect(result[1].name).toBe("b") + }) + + test("normalizes esc to escape", () => { + const [key] = Keybind.parse("esc") + expect(key.name).toBe("escape") + }) + + test("returns empty array for 'none'", () => { + expect(Keybind.parse("none")).toEqual([]) + }) +}) + +// --------------------------------------------------------------------------- +// Keybind.match +// --------------------------------------------------------------------------- + +describe("Keybind.match", () => { + test("matches identical keys", () => { + const key: Keybind.Info = { + ctrl: true, + meta: false, + shift: false, + leader: false, + name: "a", + super: false, + } + expect(Keybind.match(key, key)).toBe(true) + }) + + test("returns false for undefined first arg", () => { + const key: Keybind.Info = { + ctrl: false, + meta: false, + shift: false, + leader: false, + name: "a", + super: false, + } + expect(Keybind.match(undefined, key)).toBe(false) + }) + + test("normalizes missing super field to false", () => { + const a = { ctrl: false, meta: false, shift: false, leader: false, name: "x" } as Keybind.Info + const b: Keybind.Info = { + ctrl: false, + meta: false, + shift: false, + leader: false, + name: "x", + super: false, + } + expect(Keybind.match(a, b)).toBe(true) + }) + + test("super: true vs super: false don't match", () => { + const a: Keybind.Info = { + ctrl: false, + meta: false, + shift: false, + leader: false, + name: "a", + super: true, + } + const b: Keybind.Info = { + ctrl: false, + meta: false, + shift: false, + leader: false, + name: "a", + super: false, + } + expect(Keybind.match(a, b)).toBe(false) + }) + + test("different modifiers don't match", () => { + const a: Keybind.Info = { + ctrl: true, + meta: false, + shift: false, + leader: false, + name: "a", + super: false, + } + const b: Keybind.Info = { + ctrl: false, + meta: false, + shift: false, + leader: false, + name: "a", + super: false, + } + expect(Keybind.match(a, b)).toBe(false) + }) +}) + +// --------------------------------------------------------------------------- +// Keybind.toString +// --------------------------------------------------------------------------- + +describe("Keybind.toString", () => { + test("returns empty string for undefined", () => { + expect(Keybind.toString(undefined)).toBe("") + }) + + test("formats simple key", () => { + const key: Keybind.Info = { + ctrl: false, + meta: false, + shift: false, + leader: false, + name: "a", + super: false, + } + expect(Keybind.toString(key)).toBe("a") + }) + + test("formats modifiers in order: ctrl+alt+super+shift", () => { + const key: Keybind.Info = { + ctrl: true, + meta: true, + shift: true, + leader: false, + name: "a", + super: true, + } + expect(Keybind.toString(key)).toBe("ctrl+alt+super+shift+a") + }) + + test("formats leader prefix", () => { + const key: Keybind.Info = { + ctrl: false, + meta: false, + shift: false, + leader: true, + name: "a", + super: false, + } + expect(Keybind.toString(key)).toBe(" a") + }) + + test("maps delete to del", () => { + const key: Keybind.Info = { + ctrl: false, + meta: false, + shift: false, + leader: false, + name: "delete", + super: false, + } + expect(Keybind.toString(key)).toBe("del") + }) +}) + +// --------------------------------------------------------------------------- +// Keybind.fromParsedKey +// --------------------------------------------------------------------------- + +describe("Keybind.fromParsedKey", () => { + test("normalizes space to 'space'", () => { + const parsed = { name: " ", ctrl: false, meta: false, shift: false, super: false } + const result = Keybind.fromParsedKey(parsed as any) + expect(result.name).toBe("space") + }) + + test("sets leader flag when passed", () => { + const parsed = { name: "a", ctrl: false, meta: false, shift: false, super: false } + const result = Keybind.fromParsedKey(parsed as any, true) + expect(result.leader).toBe(true) + }) + + test("defaults leader to false", () => { + const parsed = { name: "a", ctrl: false, meta: false, shift: false, super: false } + const result = Keybind.fromParsedKey(parsed as any) + expect(result.leader).toBe(false) + }) +})