auth-override.test.ts 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import { describe, expect, test } from "bun:test"
  2. import path from "path"
  3. import fs from "fs/promises"
  4. import { Effect } from "effect"
  5. import { tmpdir } from "../fixture/fixture"
  6. import { Instance } from "../../src/project/instance"
  7. import { ProviderAuth } from "../../src/provider/auth"
  8. import { ProviderID } from "../../src/provider/schema"
  9. describe("plugin.auth-override", () => {
  10. test("user plugin overrides built-in github-copilot auth", async () => {
  11. await using tmp = await tmpdir({
  12. init: async (dir) => {
  13. const pluginDir = path.join(dir, ".opencode", "plugin")
  14. await fs.mkdir(pluginDir, { recursive: true })
  15. await Bun.write(
  16. path.join(pluginDir, "custom-copilot-auth.ts"),
  17. [
  18. "export default {",
  19. ' id: "demo.custom-copilot-auth",',
  20. " server: async () => ({",
  21. " auth: {",
  22. ' provider: "github-copilot",',
  23. " methods: [",
  24. ' { type: "api", label: "Test Override Auth" },',
  25. " ],",
  26. " loader: async () => ({ access: 'test-token' }),",
  27. " },",
  28. " }),",
  29. "}",
  30. "",
  31. ].join("\n"),
  32. )
  33. },
  34. })
  35. await using plain = await tmpdir()
  36. const methods = await Instance.provide({
  37. directory: tmp.path,
  38. fn: async () => {
  39. return Effect.runPromise(
  40. ProviderAuth.Service.use((svc) => svc.methods()).pipe(Effect.provide(ProviderAuth.defaultLayer)),
  41. )
  42. },
  43. })
  44. const plainMethods = await Instance.provide({
  45. directory: plain.path,
  46. fn: async () => {
  47. return Effect.runPromise(
  48. ProviderAuth.Service.use((svc) => svc.methods()).pipe(Effect.provide(ProviderAuth.defaultLayer)),
  49. )
  50. },
  51. })
  52. const copilot = methods[ProviderID.make("github-copilot")]
  53. expect(copilot).toBeDefined()
  54. expect(copilot.length).toBe(1)
  55. expect(copilot[0].label).toBe("Test Override Auth")
  56. expect(plainMethods[ProviderID.make("github-copilot")][0].label).not.toBe("Test Override Auth")
  57. }, 30000) // Increased timeout for plugin installation
  58. })
  59. const file = path.join(import.meta.dir, "../../src/plugin/index.ts")
  60. describe("plugin.config-hook-error-isolation", () => {
  61. test("config hooks are individually error-isolated in the layer factory", async () => {
  62. const src = await Bun.file(file).text()
  63. // Each hook's config call is wrapped in Effect.tryPromise with error logging + Effect.ignore
  64. expect(src).toContain("plugin config hook failed")
  65. const pattern =
  66. /for\s*\(const hook of hooks\)\s*\{[\s\S]*?Effect\.tryPromise[\s\S]*?\.config\?\.\([\s\S]*?plugin config hook failed[\s\S]*?Effect\.ignore/
  67. expect(pattern.test(src)).toBe(true)
  68. })
  69. })