| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- 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")
- },
- })
- })
|