mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 10:40:43 +00:00
test: share oauth workspace helpers
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { FILE_LOCK_TIMEOUT_ERROR_CODE, type FileLockTimeoutError } from "../../infra/file-lock.js";
|
||||
import { captureEnv } from "../../test-utils/env.js";
|
||||
import {
|
||||
OAUTH_AGENT_ENV_KEYS,
|
||||
createOAuthMainAgentDir,
|
||||
createOAuthTestTempRoot,
|
||||
createExpiredOauthStore,
|
||||
removeOAuthTestTempRoot,
|
||||
resolveApiKeyForProfileInTest,
|
||||
} from "./oauth-test-utils.js";
|
||||
import { resolveAuthStorePath, resolveOAuthRefreshLockPath } from "./paths.js";
|
||||
@@ -91,7 +92,7 @@ describe("OAuth refresh lock timeout classification", () => {
|
||||
let caseIndex = 0;
|
||||
|
||||
beforeAll(async () => {
|
||||
tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-oauth-lock-timeout-"));
|
||||
tempRoot = await createOAuthTestTempRoot("openclaw-oauth-lock-timeout-");
|
||||
({ resolveApiKeyForProfile, resetOAuthRefreshQueuesForTest } = await import("./oauth.js"));
|
||||
});
|
||||
|
||||
@@ -102,11 +103,7 @@ describe("OAuth refresh lock timeout classification", () => {
|
||||
);
|
||||
clearRuntimeAuthProfileStoreSnapshots();
|
||||
const caseRoot = path.join(tempRoot, `case-${++caseIndex}`);
|
||||
process.env.OPENCLAW_STATE_DIR = caseRoot;
|
||||
agentDir = path.join(caseRoot, "agents", "main", "agent");
|
||||
process.env.OPENCLAW_AGENT_DIR = agentDir;
|
||||
process.env.PI_CODING_AGENT_DIR = agentDir;
|
||||
await fs.mkdir(agentDir, { recursive: true });
|
||||
agentDir = await createOAuthMainAgentDir(caseRoot);
|
||||
resetOAuthRefreshQueuesForTest();
|
||||
});
|
||||
|
||||
@@ -117,7 +114,7 @@ describe("OAuth refresh lock timeout classification", () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await fs.rm(tempRoot, { recursive: true, force: true });
|
||||
await removeOAuthTestTempRoot(tempRoot);
|
||||
});
|
||||
|
||||
it("maps only global refresh lock timeouts to refresh_contention", async () => {
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { resetFileLockStateForTest } from "../../infra/file-lock.js";
|
||||
import { captureEnv } from "../../test-utils/env.js";
|
||||
import {
|
||||
OAUTH_AGENT_ENV_KEYS,
|
||||
createOAuthMainAgentDir,
|
||||
createOAuthTestTempRoot,
|
||||
createExpiredOauthStore,
|
||||
removeOAuthTestTempRoot,
|
||||
resolveApiKeyForProfileInTest,
|
||||
resetOAuthProviderRuntimeMocks,
|
||||
} from "./oauth-test-utils.js";
|
||||
import { resolveApiKeyForProfile, resetOAuthRefreshQueuesForTest } from "./oauth.js";
|
||||
import {
|
||||
@@ -87,22 +89,18 @@ describe("OAuth refresh in-process queue", () => {
|
||||
let caseIndex = 0;
|
||||
|
||||
beforeAll(async () => {
|
||||
tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-oauth-queue-"));
|
||||
tempRoot = await createOAuthTestTempRoot("openclaw-oauth-queue-");
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
resetFileLockStateForTest();
|
||||
refreshProviderOAuthCredentialWithPluginMock.mockReset();
|
||||
refreshProviderOAuthCredentialWithPluginMock.mockResolvedValue(undefined);
|
||||
formatProviderAuthProfileApiKeyWithPluginMock.mockReset();
|
||||
formatProviderAuthProfileApiKeyWithPluginMock.mockReturnValue(undefined);
|
||||
resetOAuthProviderRuntimeMocks({
|
||||
refreshProviderOAuthCredentialWithPluginMock,
|
||||
formatProviderAuthProfileApiKeyWithPluginMock,
|
||||
});
|
||||
clearRuntimeAuthProfileStoreSnapshots();
|
||||
const caseRoot = path.join(tempRoot, `case-${++caseIndex}`);
|
||||
process.env.OPENCLAW_STATE_DIR = caseRoot;
|
||||
agentDir = path.join(caseRoot, "agents", "main", "agent");
|
||||
process.env.OPENCLAW_AGENT_DIR = agentDir;
|
||||
process.env.PI_CODING_AGENT_DIR = agentDir;
|
||||
await fs.mkdir(agentDir, { recursive: true });
|
||||
agentDir = await createOAuthMainAgentDir(caseRoot);
|
||||
resetOAuthRefreshQueuesForTest();
|
||||
});
|
||||
|
||||
@@ -114,7 +112,7 @@ describe("OAuth refresh in-process queue", () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await fs.rm(tempRoot, { recursive: true, force: true });
|
||||
await removeOAuthTestTempRoot(tempRoot);
|
||||
});
|
||||
|
||||
it("releases the queue even when the refresh throws", async () => {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import type { resolveApiKeyForProfile } from "./oauth.js";
|
||||
import type { AuthProfileStore, OAuthCredential } from "./types.js";
|
||||
|
||||
@@ -53,6 +56,47 @@ export function createExpiredOauthStore(params: {
|
||||
};
|
||||
}
|
||||
|
||||
export async function createOAuthTestTempRoot(prefix: string): Promise<string> {
|
||||
return fs.mkdtemp(path.join(os.tmpdir(), prefix));
|
||||
}
|
||||
|
||||
export async function createOAuthMainAgentDir(stateDir: string): Promise<string> {
|
||||
const agentDir = path.join(stateDir, "agents", "main", "agent");
|
||||
process.env.OPENCLAW_STATE_DIR = stateDir;
|
||||
process.env.OPENCLAW_AGENT_DIR = agentDir;
|
||||
process.env.PI_CODING_AGENT_DIR = agentDir;
|
||||
await fs.mkdir(agentDir, { recursive: true });
|
||||
return agentDir;
|
||||
}
|
||||
|
||||
export async function removeOAuthTestTempRoot(tempRoot: string): Promise<void> {
|
||||
if (tempRoot) {
|
||||
await fs.rm(tempRoot, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
type ResettableMock = {
|
||||
mockReset(): unknown;
|
||||
};
|
||||
|
||||
type ResolvedValueMock = ResettableMock & {
|
||||
mockResolvedValue(value: unknown): unknown;
|
||||
};
|
||||
|
||||
type ReturnValueMock = ResettableMock & {
|
||||
mockReturnValue(value: unknown): unknown;
|
||||
};
|
||||
|
||||
export function resetOAuthProviderRuntimeMocks(mocks: {
|
||||
refreshProviderOAuthCredentialWithPluginMock: ResolvedValueMock;
|
||||
formatProviderAuthProfileApiKeyWithPluginMock: ReturnValueMock;
|
||||
}): void {
|
||||
mocks.refreshProviderOAuthCredentialWithPluginMock.mockReset();
|
||||
mocks.refreshProviderOAuthCredentialWithPluginMock.mockResolvedValue(undefined);
|
||||
mocks.formatProviderAuthProfileApiKeyWithPluginMock.mockReset();
|
||||
mocks.formatProviderAuthProfileApiKeyWithPluginMock.mockReturnValue(undefined);
|
||||
}
|
||||
|
||||
export function makeSeededRandom(seed: number): () => number {
|
||||
let state = seed >>> 0;
|
||||
return () => {
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { resetFileLockStateForTest } from "../../infra/file-lock.js";
|
||||
import { captureEnv } from "../../test-utils/env.js";
|
||||
import {
|
||||
OAUTH_AGENT_ENV_KEYS,
|
||||
createOAuthMainAgentDir,
|
||||
createOAuthTestTempRoot,
|
||||
oauthCred,
|
||||
removeOAuthTestTempRoot,
|
||||
resolveApiKeyForProfileInTest,
|
||||
resetOAuthProviderRuntimeMocks,
|
||||
storeWith,
|
||||
} from "./oauth-test-utils.js";
|
||||
import { resolveApiKeyForProfile, resetOAuthRefreshQueuesForTest } from "./oauth.js";
|
||||
@@ -93,23 +96,19 @@ describe("OAuth credential adoption is identity-gated", () => {
|
||||
let mainAgentDir = "";
|
||||
|
||||
beforeAll(async () => {
|
||||
tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-oauth-adopt-identity-"));
|
||||
tempRoot = await createOAuthTestTempRoot("openclaw-oauth-adopt-identity-");
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
resetFileLockStateForTest();
|
||||
refreshProviderOAuthCredentialWithPluginMock.mockReset();
|
||||
refreshProviderOAuthCredentialWithPluginMock.mockResolvedValue(undefined);
|
||||
formatProviderAuthProfileApiKeyWithPluginMock.mockReset();
|
||||
formatProviderAuthProfileApiKeyWithPluginMock.mockReturnValue(undefined);
|
||||
resetOAuthProviderRuntimeMocks({
|
||||
refreshProviderOAuthCredentialWithPluginMock,
|
||||
formatProviderAuthProfileApiKeyWithPluginMock,
|
||||
});
|
||||
clearRuntimeAuthProfileStoreSnapshots();
|
||||
caseIndex += 1;
|
||||
const caseRoot = path.join(tempRoot, `case-${caseIndex}`);
|
||||
process.env.OPENCLAW_STATE_DIR = caseRoot;
|
||||
mainAgentDir = path.join(caseRoot, "agents", "main", "agent");
|
||||
process.env.OPENCLAW_AGENT_DIR = mainAgentDir;
|
||||
process.env.PI_CODING_AGENT_DIR = mainAgentDir;
|
||||
await fs.mkdir(mainAgentDir, { recursive: true });
|
||||
mainAgentDir = await createOAuthMainAgentDir(caseRoot);
|
||||
resetOAuthRefreshQueuesForTest();
|
||||
});
|
||||
|
||||
@@ -121,9 +120,7 @@ describe("OAuth credential adoption is identity-gated", () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
if (tempRoot) {
|
||||
await fs.rm(tempRoot, { recursive: true, force: true });
|
||||
}
|
||||
await removeOAuthTestTempRoot(tempRoot);
|
||||
});
|
||||
|
||||
it("adoptNewerMainOAuthCredential refuses to adopt across accountId mismatch (pre-refresh path)", async () => {
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { resetFileLockStateForTest } from "../../infra/file-lock.js";
|
||||
import { captureEnv } from "../../test-utils/env.js";
|
||||
import {
|
||||
OAUTH_AGENT_ENV_KEYS,
|
||||
createOAuthMainAgentDir,
|
||||
createOAuthTestTempRoot,
|
||||
createExpiredOauthStore,
|
||||
removeOAuthTestTempRoot,
|
||||
resolveApiKeyForProfileInTest,
|
||||
resetOAuthProviderRuntimeMocks,
|
||||
} from "./oauth-test-utils.js";
|
||||
import {
|
||||
clearRuntimeAuthProfileStoreSnapshots,
|
||||
@@ -86,17 +89,13 @@ describe("resolveApiKeyForProfile cross-agent refresh coordination (#26322)", ()
|
||||
|
||||
beforeEach(async () => {
|
||||
resetFileLockStateForTest();
|
||||
refreshProviderOAuthCredentialWithPluginMock.mockReset();
|
||||
refreshProviderOAuthCredentialWithPluginMock.mockResolvedValue(undefined);
|
||||
formatProviderAuthProfileApiKeyWithPluginMock.mockReset();
|
||||
formatProviderAuthProfileApiKeyWithPluginMock.mockReturnValue(undefined);
|
||||
resetOAuthProviderRuntimeMocks({
|
||||
refreshProviderOAuthCredentialWithPluginMock,
|
||||
formatProviderAuthProfileApiKeyWithPluginMock,
|
||||
});
|
||||
clearRuntimeAuthProfileStoreSnapshots();
|
||||
tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-oauth-concurrent-"));
|
||||
process.env.OPENCLAW_STATE_DIR = tempRoot;
|
||||
mainAgentDir = path.join(tempRoot, "agents", "main", "agent");
|
||||
process.env.OPENCLAW_AGENT_DIR = mainAgentDir;
|
||||
process.env.PI_CODING_AGENT_DIR = mainAgentDir;
|
||||
await fs.mkdir(mainAgentDir, { recursive: true });
|
||||
tempRoot = await createOAuthTestTempRoot("openclaw-oauth-concurrent-");
|
||||
mainAgentDir = await createOAuthMainAgentDir(tempRoot);
|
||||
await loadOAuthModuleForTest();
|
||||
// Drop any refresh-queue entries left behind by a prior timed-out test.
|
||||
resetOAuthRefreshQueuesForTest();
|
||||
@@ -109,9 +108,7 @@ describe("resolveApiKeyForProfile cross-agent refresh coordination (#26322)", ()
|
||||
if (resetOAuthRefreshQueuesForTest) {
|
||||
resetOAuthRefreshQueuesForTest();
|
||||
}
|
||||
if (tempRoot) {
|
||||
await fs.rm(tempRoot, { recursive: true, force: true });
|
||||
}
|
||||
await removeOAuthTestTempRoot(tempRoot);
|
||||
});
|
||||
|
||||
it("refreshes exactly once when many agents share one OAuth profile and all race on expiry", async () => {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { resetFileLockStateForTest } from "../../infra/file-lock.js";
|
||||
@@ -7,8 +6,12 @@ import { captureEnv } from "../../test-utils/env.js";
|
||||
import { __testing as externalAuthTesting } from "./external-auth.js";
|
||||
import {
|
||||
OAUTH_AGENT_ENV_KEYS,
|
||||
createOAuthMainAgentDir,
|
||||
createOAuthTestTempRoot,
|
||||
createExpiredOauthStore,
|
||||
removeOAuthTestTempRoot,
|
||||
resolveApiKeyForProfileInTest,
|
||||
resetOAuthProviderRuntimeMocks,
|
||||
} from "./oauth-test-utils.js";
|
||||
import { resolveApiKeyForProfile, resetOAuthRefreshQueuesForTest } from "./oauth.js";
|
||||
import {
|
||||
@@ -91,24 +94,20 @@ describe("resolveApiKeyForProfile OAuth refresh mirror-to-main (#26322)", () =>
|
||||
let mainAgentDir = "";
|
||||
|
||||
beforeAll(async () => {
|
||||
tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-oauth-mirror-"));
|
||||
tempRoot = await createOAuthTestTempRoot("openclaw-oauth-mirror-");
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
resetFileLockStateForTest();
|
||||
refreshProviderOAuthCredentialWithPluginMock.mockReset();
|
||||
refreshProviderOAuthCredentialWithPluginMock.mockResolvedValue(undefined);
|
||||
formatProviderAuthProfileApiKeyWithPluginMock.mockReset();
|
||||
formatProviderAuthProfileApiKeyWithPluginMock.mockReturnValue(undefined);
|
||||
resetOAuthProviderRuntimeMocks({
|
||||
refreshProviderOAuthCredentialWithPluginMock,
|
||||
formatProviderAuthProfileApiKeyWithPluginMock,
|
||||
});
|
||||
externalAuthTesting.setResolveExternalAuthProfilesForTest(() => []);
|
||||
clearRuntimeAuthProfileStoreSnapshots();
|
||||
caseIndex += 1;
|
||||
const caseRoot = path.join(tempRoot, `case-${caseIndex}`);
|
||||
process.env.OPENCLAW_STATE_DIR = caseRoot;
|
||||
mainAgentDir = path.join(caseRoot, "agents", "main", "agent");
|
||||
process.env.OPENCLAW_AGENT_DIR = mainAgentDir;
|
||||
process.env.PI_CODING_AGENT_DIR = mainAgentDir;
|
||||
await fs.mkdir(mainAgentDir, { recursive: true });
|
||||
mainAgentDir = await createOAuthMainAgentDir(caseRoot);
|
||||
resetOAuthRefreshQueuesForTest();
|
||||
});
|
||||
|
||||
@@ -121,9 +120,7 @@ describe("resolveApiKeyForProfile OAuth refresh mirror-to-main (#26322)", () =>
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
if (tempRoot) {
|
||||
await fs.rm(tempRoot, { recursive: true, force: true });
|
||||
}
|
||||
await removeOAuthTestTempRoot(tempRoot);
|
||||
});
|
||||
|
||||
it("mirrors refreshed credentials into the main store so peers skip refresh", async () => {
|
||||
|
||||
Reference in New Issue
Block a user