UNPKG

@gguf/claw

Version:

Multi-channel AI gateway with extensible messaging integrations

163 lines (137 loc) 5.15 kB
import { join, parse } from "node:path"; import { describe, expect, it, vi, beforeEach, afterEach } from "vitest"; vi.mock("openclaw/plugin-sdk", () => ({ isWSL2Sync: () => false, })); // Mock fs module before importing the module under test const mockExistsSync = vi.fn(); const mockReadFileSync = vi.fn(); const mockRealpathSync = vi.fn(); const mockReaddirSync = vi.fn(); vi.mock("node:fs", async (importOriginal) => { const actual = await importOriginal<typeof import("node:fs")>(); return { ...actual, existsSync: (...args: Parameters<typeof actual.existsSync>) => mockExistsSync(...args), readFileSync: (...args: Parameters<typeof actual.readFileSync>) => mockReadFileSync(...args), realpathSync: (...args: Parameters<typeof actual.realpathSync>) => mockRealpathSync(...args), readdirSync: (...args: Parameters<typeof actual.readdirSync>) => mockReaddirSync(...args), }; }); describe("extractGeminiCliCredentials", () => { const normalizePath = (value: string) => value.replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase(); const rootDir = parse(process.cwd()).root || "/"; const FAKE_CLIENT_ID = "123456789-abcdef.apps.googleusercontent.com"; const FAKE_CLIENT_SECRET = "GOCSPX-FakeSecretValue123"; const FAKE_OAUTH2_CONTENT = ` const clientId = "${FAKE_CLIENT_ID}"; const clientSecret = "${FAKE_CLIENT_SECRET}"; `; let originalPath: string | undefined; function makeFakeLayout() { const binDir = join(rootDir, "fake", "bin"); const geminiPath = join(binDir, "gemini"); const resolvedPath = join( rootDir, "fake", "lib", "node_modules", "@google", "gemini-cli", "dist", "index.js", ); const oauth2Path = join( rootDir, "fake", "lib", "node_modules", "@google", "gemini-cli", "node_modules", "@google", "gemini-cli-core", "dist", "src", "code_assist", "oauth2.js", ); return { binDir, geminiPath, resolvedPath, oauth2Path }; } function installGeminiLayout(params: { oauth2Exists?: boolean; oauth2Content?: string; readdir?: string[]; }) { const layout = makeFakeLayout(); process.env.PATH = layout.binDir; mockExistsSync.mockImplementation((p: string) => { const normalized = normalizePath(p); if (normalized === normalizePath(layout.geminiPath)) { return true; } if (params.oauth2Exists && normalized === normalizePath(layout.oauth2Path)) { return true; } return false; }); mockRealpathSync.mockReturnValue(layout.resolvedPath); if (params.oauth2Content !== undefined) { mockReadFileSync.mockReturnValue(params.oauth2Content); } if (params.readdir) { mockReaddirSync.mockReturnValue(params.readdir); } return layout; } beforeEach(async () => { vi.clearAllMocks(); originalPath = process.env.PATH; }); afterEach(() => { process.env.PATH = originalPath; }); it("returns null when gemini binary is not in PATH", async () => { process.env.PATH = "/nonexistent"; mockExistsSync.mockReturnValue(false); const { extractGeminiCliCredentials, clearCredentialsCache } = await import("./oauth.js"); clearCredentialsCache(); expect(extractGeminiCliCredentials()).toBeNull(); }); it("extracts credentials from oauth2.js in known path", async () => { installGeminiLayout({ oauth2Exists: true, oauth2Content: FAKE_OAUTH2_CONTENT }); const { extractGeminiCliCredentials, clearCredentialsCache } = await import("./oauth.js"); clearCredentialsCache(); const result = extractGeminiCliCredentials(); expect(result).toEqual({ clientId: FAKE_CLIENT_ID, clientSecret: FAKE_CLIENT_SECRET, }); }); it("returns null when oauth2.js cannot be found", async () => { installGeminiLayout({ oauth2Exists: false, readdir: [] }); const { extractGeminiCliCredentials, clearCredentialsCache } = await import("./oauth.js"); clearCredentialsCache(); expect(extractGeminiCliCredentials()).toBeNull(); }); it("returns null when oauth2.js lacks credentials", async () => { installGeminiLayout({ oauth2Exists: true, oauth2Content: "// no credentials here" }); const { extractGeminiCliCredentials, clearCredentialsCache } = await import("./oauth.js"); clearCredentialsCache(); expect(extractGeminiCliCredentials()).toBeNull(); }); it("caches credentials after first extraction", async () => { installGeminiLayout({ oauth2Exists: true, oauth2Content: FAKE_OAUTH2_CONTENT }); const { extractGeminiCliCredentials, clearCredentialsCache } = await import("./oauth.js"); clearCredentialsCache(); // First call const result1 = extractGeminiCliCredentials(); expect(result1).not.toBeNull(); // Second call should use cache (readFileSync not called again) const readCount = mockReadFileSync.mock.calls.length; const result2 = extractGeminiCliCredentials(); expect(result2).toEqual(result1); expect(mockReadFileSync.mock.calls.length).toBe(readCount); }); });