/** * 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 { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; vi.mock("@salesforce/core", () => ({ Org: { create: vi.fn() }, AuthInfo: { listAllAuthorizations: vi.fn() }, })); const { Org, AuthInfo } = await import("@salesforce/core"); const { clearOrgAuthCache, getOrgAuth, listOrgs } = await import("../auth.js"); const orgCreateMock = vi.mocked(Org.create); // AuthInfo.listAllAuthorizations is exercised by listOrgs tests (re-enabled in Task 2) const listAuthsMock = vi.mocked(AuthInfo.listAllAuthorizations); function mockOrg( fields: Record, opts: { accessToken?: string | null; instanceUrl?: string } = {}, ) { return { getConnection: () => ({ instanceUrl: opts.instanceUrl ?? "https://example.my.salesforce.com/", accessToken: opts.accessToken === undefined ? "00Dxx!token" : opts.accessToken, getAuthInfo: () => ({ getFields: () => fields }), }), } as unknown as Awaited>; } describe("auth", () => { beforeEach(() => { clearOrgAuthCache(); orgCreateMock.mockReset(); listAuthsMock.mockReset(); }); afterEach(() => { clearOrgAuthCache(); }); describe("getOrgAuth alias validation", () => { const invalidAliases: [string, string][] = [ ["semicolon", "good;rm -rf ~"], ["dollar", "good$(whoami)"], ["backtick", "good`whoami`"], ["newline", "good\nrm"], ["space", "good org"], ["leading hyphen (flag injection)", "-foo"], ["leading dot", ".foo"], ["embedded space in email", "user @example.com"], ["empty string", ""], ["over 253 chars", "a".repeat(254)], ]; for (const [label, alias] of invalidAliases) { it(`rejects invalid alias: ${label}`, async () => { await expect(getOrgAuth(alias)).rejects.toThrow(/alias or username/i); expect(orgCreateMock).not.toHaveBeenCalled(); }); } it("does not echo the offending alias verbatim into the error message", async () => { const malicious = "evil;rm -rf ~"; await expect(getOrgAuth(malicious)).rejects.toThrow(); try { await getOrgAuth(malicious); } catch (err) { expect((err as Error).message).not.toContain(malicious); } }); }); describe("getOrgAuth username/email acceptance", () => { const validIdentifiers: [string, string][] = [ ["simple alias", "MyOrg"], ["alias with hyphen and underscore", "MyOrg-1_2"], ["plain email username", "user@example.com"], ["email with sandbox suffix", "admin@my-company.com.sandbox"], ["email with plus tag and complex domain", "dev+build1@scratch-org-12.example.com"], ["org id", "00D5g00000ABCDE"], ]; for (const [label, identifier] of validIdentifiers) { it(`accepts valid identifier: ${label}`, async () => { orgCreateMock.mockResolvedValueOnce( mockOrg({ username: "user@example.com", orgId: "00Dxx0000000000" }), ); await expect(getOrgAuth(identifier)).resolves.not.toThrow(); expect(orgCreateMock).toHaveBeenCalledWith({ aliasOrUsername: identifier }); }); } }); describe("getOrgAuth happy path", () => { it("resolves via Org.create and maps fields", async () => { orgCreateMock.mockResolvedValueOnce( mockOrg({ username: "user@example.com", orgId: "00Dxx0000000000" }), ); const auth = await getOrgAuth("MyOrg-1_2"); expect(orgCreateMock).toHaveBeenCalledWith({ aliasOrUsername: "MyOrg-1_2" }); expect(auth.accessToken).toBe("00Dxx!token"); expect(auth.instanceUrl).toBe("https://example.my.salesforce.com"); // trailing slash stripped expect(auth.username).toBe("user@example.com"); expect(auth.orgId).toBe("00Dxx0000000000"); expect(auth.alias).toBe("MyOrg-1_2"); }); it("memoizes: a second call does not re-create the org", async () => { orgCreateMock.mockResolvedValueOnce(mockOrg({ username: "u", orgId: "00D" })); await getOrgAuth("CachedOrg"); await getOrgAuth("CachedOrg"); expect(orgCreateMock).toHaveBeenCalledTimes(1); }); it("throws a re-auth hint when access token is missing", async () => { orgCreateMock.mockResolvedValueOnce( mockOrg({ username: "u", orgId: "00D" }, { accessToken: null }), ); await expect(getOrgAuth("NoToken")).rejects.toThrow(/sf org login/i); }); it("wraps Org.create failure with a re-auth hint and preserves the cause", async () => { orgCreateMock.mockRejectedValue(new Error("NamedOrgNotFound")); await expect(getOrgAuth("MissingOrg")).rejects.toThrow(/sf org login web --alias MissingOrg/); await expect(getOrgAuth("MissingOrg")).rejects.toThrow(/NamedOrgNotFound/); }); it('falls back to "unknown" when username/orgId are absent', async () => { orgCreateMock.mockResolvedValueOnce(mockOrg({})); // empty fields const auth = await getOrgAuth("SparseOrg"); expect(auth.username).toBe("unknown"); expect(auth.orgId).toBe("unknown"); }); it("accepts an alias starting with underscore", async () => { orgCreateMock.mockResolvedValueOnce( mockOrg({ username: "user@example.com", orgId: "00Dxx0000000000" }), ); await expect(getOrgAuth("_internal")).resolves.not.toThrow(); expect(orgCreateMock).toHaveBeenCalledTimes(1); }); }); describe("listOrgs", () => { it("maps scratch and non-scratch and prefers alias over username", async () => { listAuthsMock.mockResolvedValueOnce([ { aliases: ["Prod"], username: "p@example.com", instanceUrl: "https://p.my.salesforce.com/", orgId: "00DP", isScratchOrg: false, isExpired: false, oauthMethod: "web", configs: [], }, { aliases: ["Scr"], username: "s@example.com", instanceUrl: "https://s.my.salesforce.com", orgId: "00DS", isScratchOrg: true, isExpired: false, oauthMethod: "web", configs: [], }, ] as never); const orgs = await listOrgs(); expect(orgs).toHaveLength(2); expect(orgs[0]).toMatchObject({ alias: "Prod", type: "non-scratch", instanceUrl: "https://p.my.salesforce.com", }); expect(orgs[1]).toMatchObject({ alias: "Scr", type: "scratch" }); }); it("falls back to username when an org has no alias", async () => { listAuthsMock.mockResolvedValueOnce([ { aliases: null, username: "noalias@example.com", instanceUrl: "https://n.my.salesforce.com", orgId: "00DN", isScratchOrg: false, isExpired: false, oauthMethod: "web", configs: [], }, ] as never); const orgs = await listOrgs(); expect(orgs).toHaveLength(1); expect(orgs[0].alias).toBe("noalias@example.com"); expect(orgs[0].username).toBe("noalias@example.com"); }); it("skips orgs with neither alias nor username", async () => { listAuthsMock.mockResolvedValueOnce([ { aliases: null, username: "", instanceUrl: "https://x.my.salesforce.com", orgId: "00DX", isScratchOrg: false, isExpired: false, oauthMethod: "web", configs: [], }, ] as never); expect(await listOrgs()).toHaveLength(0); }); it("marks isConnected=true when a session's orgAlias matches one of the org's aliases", async () => { const home = fs.mkdtempSync(path.join(os.tmpdir(), "graphiti-conn-")); const sessionsDir = path.join(home, "sessions"); fs.mkdirSync(sessionsDir, { recursive: true }); fs.writeFileSync(path.join(sessionsDir, "s1.json"), JSON.stringify({ orgAlias: "Prod" })); const prev = process.env.GRAPHITI_HOME; process.env.GRAPHITI_HOME = home; try { listAuthsMock.mockResolvedValueOnce([ { aliases: ["Prod"], username: "p@example.com", instanceUrl: "https://p.my.salesforce.com", orgId: "00DP", isScratchOrg: false, isExpired: false, oauthMethod: "web", configs: [], }, { aliases: ["Other"], username: "o@example.com", instanceUrl: "https://o.my.salesforce.com", orgId: "00DO", isScratchOrg: false, isExpired: false, oauthMethod: "web", configs: [], }, ] as never); const orgs = await listOrgs(); expect(orgs.find((o) => o.alias === "Prod")?.isConnected).toBe(true); expect(orgs.find((o) => o.alias === "Other")?.isConnected).toBe(false); } finally { if (prev === undefined) delete process.env.GRAPHITI_HOME; else process.env.GRAPHITI_HOME = prev; fs.rmSync(home, { recursive: true, force: true }); } }); it("marks isConnected=true when a session's orgAlias matches the org's username (no alias)", async () => { const home = fs.mkdtempSync(path.join(os.tmpdir(), "graphiti-conn-")); const sessionsDir = path.join(home, "sessions"); fs.mkdirSync(sessionsDir, { recursive: true }); fs.writeFileSync( path.join(sessionsDir, "s1.json"), JSON.stringify({ orgAlias: "user@example.com" }), ); const prev = process.env.GRAPHITI_HOME; process.env.GRAPHITI_HOME = home; try { listAuthsMock.mockResolvedValueOnce([ { aliases: null, username: "user@example.com", instanceUrl: "https://u.my.salesforce.com", orgId: "00DU", isScratchOrg: false, isExpired: false, oauthMethod: "web", configs: [], }, ] as never); const orgs = await listOrgs(); expect(orgs[0].isConnected).toBe(true); } finally { if (prev === undefined) delete process.env.GRAPHITI_HOME; else process.env.GRAPHITI_HOME = prev; fs.rmSync(home, { recursive: true, force: true }); } }); }); });