Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Co-authored-by: Aiden Cline <aidenpcline@gmail.com>
287 lines
7.8 KiB
TypeScript
287 lines
7.8 KiB
TypeScript
import { test, expect, mock } from "bun:test"
|
|
import path from "path"
|
|
|
|
// === Mocks ===
|
|
// These mocks prevent real package installations during tests
|
|
|
|
mock.module("../../src/bun/index", () => ({
|
|
BunProc: {
|
|
install: async (pkg: string, _version?: string) => {
|
|
// Return package name without version for mocking
|
|
const lastAtIndex = pkg.lastIndexOf("@")
|
|
return lastAtIndex > 0 ? pkg.substring(0, lastAtIndex) : pkg
|
|
},
|
|
run: async () => {
|
|
throw new Error("BunProc.run should not be called in tests")
|
|
},
|
|
which: () => process.execPath,
|
|
InstallFailedError: class extends Error {},
|
|
},
|
|
}))
|
|
|
|
const mockPlugin = () => ({})
|
|
mock.module("opencode-copilot-auth", () => ({ default: mockPlugin }))
|
|
mock.module("opencode-anthropic-auth", () => ({ default: mockPlugin }))
|
|
mock.module("@gitlab/opencode-gitlab-auth", () => ({ default: mockPlugin }))
|
|
|
|
// Import after mocks are set up
|
|
const { tmpdir } = await import("../fixture/fixture")
|
|
const { Instance } = await import("../../src/project/instance")
|
|
const { Provider } = await import("../../src/provider/provider")
|
|
const { Env } = await import("../../src/env")
|
|
const { Global } = await import("../../src/global")
|
|
|
|
test("GitLab Duo: loads provider with API key from environment", async () => {
|
|
await using tmp = await tmpdir({
|
|
init: async (dir) => {
|
|
await Bun.write(
|
|
path.join(dir, "opencode.json"),
|
|
JSON.stringify({
|
|
$schema: "https://opencode.ai/config.json",
|
|
}),
|
|
)
|
|
},
|
|
})
|
|
await Instance.provide({
|
|
directory: tmp.path,
|
|
init: async () => {
|
|
Env.set("GITLAB_TOKEN", "test-gitlab-token")
|
|
},
|
|
fn: async () => {
|
|
const providers = await Provider.list()
|
|
expect(providers["gitlab"]).toBeDefined()
|
|
expect(providers["gitlab"].key).toBe("test-gitlab-token")
|
|
},
|
|
})
|
|
})
|
|
|
|
test("GitLab Duo: config instanceUrl option sets baseURL", async () => {
|
|
await using tmp = await tmpdir({
|
|
init: async (dir) => {
|
|
await Bun.write(
|
|
path.join(dir, "opencode.json"),
|
|
JSON.stringify({
|
|
$schema: "https://opencode.ai/config.json",
|
|
provider: {
|
|
gitlab: {
|
|
options: {
|
|
instanceUrl: "https://gitlab.example.com",
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
)
|
|
},
|
|
})
|
|
await Instance.provide({
|
|
directory: tmp.path,
|
|
init: async () => {
|
|
Env.set("GITLAB_TOKEN", "test-token")
|
|
Env.set("GITLAB_INSTANCE_URL", "https://gitlab.example.com")
|
|
},
|
|
fn: async () => {
|
|
const providers = await Provider.list()
|
|
expect(providers["gitlab"]).toBeDefined()
|
|
expect(providers["gitlab"].options?.instanceUrl).toBe("https://gitlab.example.com")
|
|
},
|
|
})
|
|
})
|
|
|
|
test("GitLab Duo: loads with OAuth token from auth.json", async () => {
|
|
await using tmp = await tmpdir({
|
|
init: async (dir) => {
|
|
await Bun.write(
|
|
path.join(dir, "opencode.json"),
|
|
JSON.stringify({
|
|
$schema: "https://opencode.ai/config.json",
|
|
}),
|
|
)
|
|
},
|
|
})
|
|
|
|
const authPath = path.join(Global.Path.data, "auth.json")
|
|
await Bun.write(
|
|
authPath,
|
|
JSON.stringify({
|
|
gitlab: {
|
|
type: "oauth",
|
|
access: "test-access-token",
|
|
refresh: "test-refresh-token",
|
|
expires: Date.now() + 3600000,
|
|
},
|
|
}),
|
|
)
|
|
|
|
await Instance.provide({
|
|
directory: tmp.path,
|
|
init: async () => {
|
|
Env.set("GITLAB_TOKEN", "")
|
|
},
|
|
fn: async () => {
|
|
const providers = await Provider.list()
|
|
expect(providers["gitlab"]).toBeDefined()
|
|
},
|
|
})
|
|
})
|
|
|
|
test("GitLab Duo: loads with Personal Access Token from auth.json", async () => {
|
|
await using tmp = await tmpdir({
|
|
init: async (dir) => {
|
|
await Bun.write(
|
|
path.join(dir, "opencode.json"),
|
|
JSON.stringify({
|
|
$schema: "https://opencode.ai/config.json",
|
|
}),
|
|
)
|
|
},
|
|
})
|
|
|
|
const authPath2 = path.join(Global.Path.data, "auth.json")
|
|
await Bun.write(
|
|
authPath2,
|
|
JSON.stringify({
|
|
gitlab: {
|
|
type: "api",
|
|
key: "glpat-test-pat-token",
|
|
},
|
|
}),
|
|
)
|
|
|
|
await Instance.provide({
|
|
directory: tmp.path,
|
|
init: async () => {
|
|
Env.set("GITLAB_TOKEN", "")
|
|
},
|
|
fn: async () => {
|
|
const providers = await Provider.list()
|
|
expect(providers["gitlab"]).toBeDefined()
|
|
expect(providers["gitlab"].key).toBe("glpat-test-pat-token")
|
|
},
|
|
})
|
|
})
|
|
|
|
test("GitLab Duo: supports self-hosted instance configuration", async () => {
|
|
await using tmp = await tmpdir({
|
|
init: async (dir) => {
|
|
await Bun.write(
|
|
path.join(dir, "opencode.json"),
|
|
JSON.stringify({
|
|
$schema: "https://opencode.ai/config.json",
|
|
provider: {
|
|
gitlab: {
|
|
options: {
|
|
instanceUrl: "https://gitlab.company.internal",
|
|
apiKey: "glpat-internal-token",
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
)
|
|
},
|
|
})
|
|
await Instance.provide({
|
|
directory: tmp.path,
|
|
init: async () => {
|
|
Env.set("GITLAB_INSTANCE_URL", "https://gitlab.company.internal")
|
|
},
|
|
fn: async () => {
|
|
const providers = await Provider.list()
|
|
expect(providers["gitlab"]).toBeDefined()
|
|
expect(providers["gitlab"].options?.instanceUrl).toBe("https://gitlab.company.internal")
|
|
},
|
|
})
|
|
})
|
|
|
|
test("GitLab Duo: config apiKey takes precedence over environment variable", async () => {
|
|
await using tmp = await tmpdir({
|
|
init: async (dir) => {
|
|
await Bun.write(
|
|
path.join(dir, "opencode.json"),
|
|
JSON.stringify({
|
|
$schema: "https://opencode.ai/config.json",
|
|
provider: {
|
|
gitlab: {
|
|
options: {
|
|
apiKey: "config-token",
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
)
|
|
},
|
|
})
|
|
await Instance.provide({
|
|
directory: tmp.path,
|
|
init: async () => {
|
|
Env.set("GITLAB_TOKEN", "env-token")
|
|
},
|
|
fn: async () => {
|
|
const providers = await Provider.list()
|
|
expect(providers["gitlab"]).toBeDefined()
|
|
},
|
|
})
|
|
})
|
|
|
|
test("GitLab Duo: supports feature flags configuration", async () => {
|
|
await using tmp = await tmpdir({
|
|
init: async (dir) => {
|
|
await Bun.write(
|
|
path.join(dir, "opencode.json"),
|
|
JSON.stringify({
|
|
$schema: "https://opencode.ai/config.json",
|
|
provider: {
|
|
gitlab: {
|
|
options: {
|
|
featureFlags: {
|
|
duo_agent_platform_agentic_chat: true,
|
|
duo_agent_platform: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
)
|
|
},
|
|
})
|
|
await Instance.provide({
|
|
directory: tmp.path,
|
|
init: async () => {
|
|
Env.set("GITLAB_TOKEN", "test-token")
|
|
},
|
|
fn: async () => {
|
|
const providers = await Provider.list()
|
|
expect(providers["gitlab"]).toBeDefined()
|
|
expect(providers["gitlab"].options?.featureFlags).toBeDefined()
|
|
expect(providers["gitlab"].options?.featureFlags?.duo_agent_platform_agentic_chat).toBe(true)
|
|
},
|
|
})
|
|
})
|
|
|
|
test("GitLab Duo: has multiple agentic chat models available", async () => {
|
|
await using tmp = await tmpdir({
|
|
init: async (dir) => {
|
|
await Bun.write(
|
|
path.join(dir, "opencode.json"),
|
|
JSON.stringify({
|
|
$schema: "https://opencode.ai/config.json",
|
|
}),
|
|
)
|
|
},
|
|
})
|
|
await Instance.provide({
|
|
directory: tmp.path,
|
|
init: async () => {
|
|
Env.set("GITLAB_TOKEN", "test-token")
|
|
},
|
|
fn: async () => {
|
|
const providers = await Provider.list()
|
|
expect(providers["gitlab"]).toBeDefined()
|
|
const models = Object.keys(providers["gitlab"].models)
|
|
expect(models.length).toBeGreaterThan(0)
|
|
expect(models).toContain("duo-chat-haiku-4-5")
|
|
expect(models).toContain("duo-chat-sonnet-4-5")
|
|
expect(models).toContain("duo-chat-opus-4-5")
|
|
},
|
|
})
|
|
})
|