/** * Copyright (c) 2026, Salesforce, Inc., * All rights reserved. * For full license text, see the LICENSE.txt file */ import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { buildSchema } from "graphql"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { makeNoopPrimeDeps } from "../../__tests__/helpers/prime-deps.js"; import { captureStdout } from "../../__tests__/helpers/stdout.js"; import { schemaCacheKeyForInstanceUrl, schemaDir } from "../../lib/introspect.js"; import { type PrimeDeps, SchemaRefreshError } from "../../lib/prime-schema.js"; import { connectCommand } from "../connect.js"; const ORG = "test-connect-cli"; const ORG_URL = "https://test-connect-cli.my.salesforce.com"; const SCHEMA = buildSchema(`type Query { x: Int }`); describe("commands/connect", () => { let tmpRoot: string; beforeEach(() => { tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "graphiti-cmd-connect-")); process.env.GRAPHITI_HOME = tmpRoot; }); afterEach(() => { delete process.env.GRAPHITI_HOME; fs.rmSync(tmpRoot, { recursive: true, force: true }); }); function schemaFile(): string { return path.join(schemaDir(), `${schemaCacheKeyForInstanceUrl(ORG_URL)}.json`); } it("--refresh routes through the shared path and clears the on-disk ObjectInfo cache", async () => { const deps = makeNoopPrimeDeps(ORG, ORG_URL, SCHEMA); await captureStdout(() => connectCommand(ORG, {}, deps)); // initial prime // Seed an ObjectInfo disk cache entry for this org — the stale data a // refresh must clear (the bug this story fixes). const oiDir = path.join(tmpRoot, "cache", "objectInfos", ORG); fs.mkdirSync(oiDir, { recursive: true }); fs.writeFileSync(path.join(oiDir, "Account.json"), "{}"); expect(fs.existsSync(oiDir)).toBe(true); const out = await captureStdout(() => connectCommand(ORG, { refresh: true }, deps)); expect(fs.existsSync(oiDir)).toBe(false); // cleared by the refresh expect(out).toMatch(/Refreshed test-connect-cli/); }); it("--refresh failure throws SchemaRefreshError and keeps the cached schema", async () => { const good = makeNoopPrimeDeps(ORG, ORG_URL, SCHEMA); await captureStdout(() => connectCommand(ORG, {}, good)); // prime a real cache const before = fs.readFileSync(schemaFile(), "utf-8"); const failing: PrimeDeps = { getOrgAuth: good.getOrgAuth, downloadSchema: async () => { throw new Error("introspection failed"); }, }; await expect( captureStdout(() => connectCommand(ORG, { refresh: true }, failing)), ).rejects.toBeInstanceOf(SchemaRefreshError); // The previously cached schema is left intact. expect(fs.readFileSync(schemaFile(), "utf-8")).toBe(before); }); it("connect without --refresh on a cached org reports 'already cached' and does not download", async () => { const good = makeNoopPrimeDeps(ORG, ORG_URL, SCHEMA); await captureStdout(() => connectCommand(ORG, {}, good)); // prime let downloadCalls = 0; const counting: PrimeDeps = { getOrgAuth: good.getOrgAuth, downloadSchema: async (a) => { downloadCalls++; return good.downloadSchema(a); }, }; const out = await captureStdout(() => connectCommand(ORG, {}, counting)); expect(out).toMatch(/already cached/); expect(downloadCalls).toBe(0); }); });