error.test.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import { describe, expect, test } from "bun:test"
  2. import { AccountTransportError } from "../../src/account/schema"
  3. import { FormatError } from "../../src/cli/error"
  4. import { UI } from "../../src/cli/ui"
  5. describe("cli.error", () => {
  6. test("formats legacy and tagged config errors the same way", () => {
  7. const cases = [
  8. {
  9. tag: "ConfigJsonError",
  10. data: { path: "/tmp/opencode.jsonc", message: "Unexpected token" },
  11. expected: "Config file at /tmp/opencode.jsonc is not valid JSON(C): Unexpected token",
  12. },
  13. {
  14. tag: "ConfigDirectoryTypoError",
  15. data: { path: "/tmp/opencode.jsonc", dir: ".opencode", suggestion: "opencode" },
  16. expected:
  17. 'Directory ".opencode" in /tmp/opencode.jsonc is not valid. Rename the directory to "opencode" or remove it. This is a common typo.',
  18. },
  19. {
  20. tag: "ConfigFrontmatterError",
  21. data: { path: "/tmp/AGENTS.md", message: "failed frontmatter" },
  22. expected: "failed frontmatter",
  23. },
  24. {
  25. tag: "ConfigInvalidError",
  26. data: {
  27. path: "/tmp/opencode.jsonc",
  28. message: "schema mismatch",
  29. issues: [{ message: "Expected string", path: ["provider", "id"] }],
  30. },
  31. expected: "Configuration is invalid at /tmp/opencode.jsonc: schema mismatch\n↳ Expected string provider.id",
  32. },
  33. ]
  34. for (const item of cases) {
  35. expect(FormatError({ name: item.tag, data: item.data })).toBe(item.expected)
  36. expect(FormatError({ _tag: item.tag, ...item.data })).toBe(item.expected)
  37. }
  38. })
  39. test("preserves multiline JSONC diagnostics for tagged config errors", () => {
  40. const data = {
  41. path: "/tmp/opencode.jsonc",
  42. message: '\n--- JSONC Input ---\n{\n "model": \n}\n--- Errors ---\nValueExpected at line 3, column 1\n Line 3: }\n ^\n--- End ---',
  43. }
  44. const expected = `Config file at ${data.path} is not valid JSON(C): ${data.message}`
  45. expect(FormatError({ name: "ConfigJsonError", data })).toBe(expected)
  46. expect(FormatError({ _tag: "ConfigJsonError", ...data })).toBe(expected)
  47. })
  48. test("formats account transport errors clearly", () => {
  49. const error = new AccountTransportError({
  50. method: "POST",
  51. url: "https://console.opencode.ai/auth/device/code",
  52. })
  53. const formatted = FormatError(error)
  54. expect(formatted).toContain("Could not reach POST https://console.opencode.ai/auth/device/code.")
  55. expect(formatted).toContain("This failed before the server returned an HTTP response.")
  56. expect(formatted).toContain("Check your network, proxy, or VPN configuration and try again.")
  57. })
  58. test("formats cancelled UI errors as empty output", () => {
  59. expect(FormatError(new UI.CancelledError())).toBe("")
  60. })
  61. })