138 lines
5.4 KiB
TypeScript
138 lines
5.4 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
const providersModule = await import("../../src/lib/oauth/providers/index.ts");
|
|
const oauthModule = await import("../../src/lib/oauth/constants/oauth.ts");
|
|
const oauthHandlers = await import("../../src/lib/oauth/providers.ts");
|
|
|
|
const PROVIDERS = providersModule.default;
|
|
const { TRAE_CONFIG, PROVIDERS: OAUTH_PROVIDER_IDS } = oauthModule;
|
|
const { getProvider } = oauthHandlers;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Registration
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("oauth provider helpers public surface excludes removed provider-name list helper", () => {
|
|
assert.equal(Object.hasOwn(oauthHandlers, "getProviderNames"), false);
|
|
assert.equal(typeof oauthHandlers.getProvider, "function");
|
|
assert.equal(typeof oauthHandlers.generateAuthData, "function");
|
|
});
|
|
|
|
test("PROVIDERS map includes a 'trae' entry", () => {
|
|
assert.ok("trae" in PROVIDERS, "PROVIDERS must contain trae");
|
|
});
|
|
|
|
test("getProvider('trae') does not throw", () => {
|
|
assert.doesNotThrow(() => getProvider("trae"));
|
|
});
|
|
|
|
test("trae provider has the correct id via getProvider", () => {
|
|
// trae provider has no .config.id — confirm via OAUTH_PROVIDER_IDS constant
|
|
const traeKey = OAUTH_PROVIDER_IDS.TRAE;
|
|
assert.equal(traeKey, "trae");
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Shape
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("trae provider exposes the expected shape", () => {
|
|
const provider = PROVIDERS.trae;
|
|
|
|
assert.ok(provider, "trae provider must exist");
|
|
assert.equal(
|
|
provider.flowType,
|
|
"import_token",
|
|
"Trae uses import_token until ByteDance publishes a public OAuth client"
|
|
);
|
|
assert.ok(provider.config, "trae provider must have a config object");
|
|
assert.equal(typeof provider.mapTokens, "function", "trae provider must expose mapTokens");
|
|
});
|
|
|
|
test("TRAE_CONFIG has required API endpoint fields", () => {
|
|
assert.ok(typeof TRAE_CONFIG.apiEndpoint === "string" && TRAE_CONFIG.apiEndpoint.length > 0);
|
|
assert.ok(typeof TRAE_CONFIG.chatEndpoint === "string" && TRAE_CONFIG.chatEndpoint.length > 0);
|
|
assert.ok(typeof TRAE_CONFIG.webUrl === "string" && TRAE_CONFIG.webUrl.length > 0);
|
|
assert.ok(TRAE_CONFIG.apiEndpoint.startsWith("https://"), "apiEndpoint must use HTTPS");
|
|
assert.ok(TRAE_CONFIG.webUrl.startsWith("https://"), "webUrl must use HTTPS");
|
|
});
|
|
|
|
test("TRAE_CONFIG exposes token storage paths for all platforms (#2658)", () => {
|
|
assert.ok(TRAE_CONFIG.tokenStoragePaths.linux);
|
|
assert.ok(TRAE_CONFIG.tokenStoragePaths.macos);
|
|
assert.ok(TRAE_CONFIG.tokenStoragePaths.windows);
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// mapTokens
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("trae mapTokens returns expected structure with valid input", () => {
|
|
const provider = PROVIDERS.trae;
|
|
|
|
const mapped = provider.mapTokens({
|
|
accessToken: "trae-test-token",
|
|
expiresIn: 7200,
|
|
});
|
|
|
|
assert.equal(mapped.accessToken, "trae-test-token");
|
|
assert.equal(mapped.refreshToken, null, "Trae import_token has no refresh token");
|
|
assert.equal(mapped.expiresIn, 7200);
|
|
assert.equal(mapped.providerSpecificData.authMethod, "imported");
|
|
});
|
|
|
|
test("trae mapTokens preserves machineId in providerSpecificData (#2658)", () => {
|
|
const provider = PROVIDERS.trae;
|
|
const mapped = provider.mapTokens({
|
|
accessToken: "tk_test",
|
|
expiresIn: 3600,
|
|
machineId: "machine-xyz",
|
|
});
|
|
assert.equal(mapped.providerSpecificData.machineId, "machine-xyz");
|
|
assert.equal(mapped.providerSpecificData.authMethod, "imported");
|
|
});
|
|
|
|
test("trae mapTokens defaults expiresIn to the ~14-day Cloud-IDE-JWT lifetime when not provided", () => {
|
|
const provider = PROVIDERS.trae;
|
|
|
|
const mapped = provider.mapTokens({ accessToken: "trae-token-2" });
|
|
|
|
// SOLO Cloud-IDE-JWTs live ~14 days (TRAE_CONFIG.tokenLifetimeDays).
|
|
assert.equal(mapped.expiresIn, TRAE_CONFIG.tokenLifetimeDays * 24 * 60 * 60);
|
|
});
|
|
|
|
test("trae mapTokens enriches providerSpecificData with SOLO identity defaults", () => {
|
|
const provider = PROVIDERS.trae;
|
|
const mapped = provider.mapTokens({
|
|
accessToken: "tk",
|
|
webId: "WID",
|
|
bizUserId: "BUID",
|
|
});
|
|
assert.equal(mapped.providerSpecificData.webId, "WID");
|
|
assert.equal(mapped.providerSpecificData.bizUserId, "BUID");
|
|
// Identity defaults required by the SOLO common_params payload.
|
|
assert.equal(mapped.providerSpecificData.scope, "marscode-us");
|
|
assert.equal(mapped.providerSpecificData.tenant, "marscode");
|
|
assert.equal(mapped.providerSpecificData.region, "US-East");
|
|
});
|
|
|
|
test("trae mapTokens returns an object even when called with empty tokens", () => {
|
|
const provider = PROVIDERS.trae;
|
|
const mapped = provider.mapTokens({});
|
|
|
|
assert.ok(mapped && typeof mapped === "object");
|
|
assert.equal(mapped.refreshToken, null);
|
|
assert.equal(mapped.expiresIn, TRAE_CONFIG.tokenLifetimeDays * 24 * 60 * 60);
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// OAuth provider ID constant alignment
|
|
// ---------------------------------------------------------------------------
|
|
|
|
test("OAUTH_PROVIDER_IDS.TRAE matches the PROVIDERS key", () => {
|
|
const traeId = OAUTH_PROVIDER_IDS.TRAE;
|
|
assert.equal(traeId, "trae");
|
|
assert.ok(traeId in PROVIDERS, "PROVIDERS must include the key from OAUTH_PROVIDER_IDS.TRAE");
|
|
});
|