paths.test.ts 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /// <reference types="bun-types" />
  2. import { afterEach, beforeEach, describe, expect, test } from 'bun:test';
  3. import { existsSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
  4. import { homedir, tmpdir } from 'node:os';
  5. import { join } from 'node:path';
  6. import {
  7. ensureConfigDir,
  8. getConfigDir,
  9. getConfigJson,
  10. getConfigJsonc,
  11. getConfigSearchDirs,
  12. getExistingConfigPath,
  13. getLiteConfig,
  14. getOpenCodeConfigPaths,
  15. } from './paths';
  16. describe('paths', () => {
  17. const originalEnv = { ...process.env };
  18. beforeEach(() => {
  19. delete process.env.OPENCODE_CONFIG_DIR;
  20. });
  21. afterEach(() => {
  22. process.env = { ...originalEnv };
  23. });
  24. test('getConfigDir() uses OPENCODE_CONFIG_DIR when set', () => {
  25. process.env.OPENCODE_CONFIG_DIR = '/custom/directory';
  26. delete process.env.XDG_CONFIG_HOME;
  27. expect(getConfigDir()).toBe('/custom/directory');
  28. });
  29. test('getConfigDir() uses XDG_CONFIG_HOME when set', () => {
  30. delete process.env.OPENCODE_CONFIG_DIR;
  31. process.env.XDG_CONFIG_HOME = '/tmp/xdg-config';
  32. expect(getConfigDir()).toBe('/tmp/xdg-config/opencode');
  33. });
  34. test('getConfigDir() falls back to ~/.config when XDG_CONFIG_HOME is unset', () => {
  35. delete process.env.OPENCODE_CONFIG_DIR;
  36. delete process.env.XDG_CONFIG_HOME;
  37. const expected = join(homedir(), '.config', 'opencode');
  38. expect(getConfigDir()).toBe(expected);
  39. });
  40. test('getConfigSearchDirs() returns custom dir first, then default dir', () => {
  41. process.env.OPENCODE_CONFIG_DIR = '/custom/directory';
  42. process.env.XDG_CONFIG_HOME = '/tmp/xdg-config';
  43. expect(getConfigSearchDirs()).toEqual([
  44. '/custom/directory',
  45. '/tmp/xdg-config/opencode',
  46. ]);
  47. });
  48. test('getConfigSearchDirs() de-duplicates identical dirs', () => {
  49. process.env.OPENCODE_CONFIG_DIR = '/tmp/xdg-config/opencode';
  50. process.env.XDG_CONFIG_HOME = '/tmp/xdg-config';
  51. expect(getConfigSearchDirs()).toEqual(['/tmp/xdg-config/opencode']);
  52. });
  53. test('getOpenCodeConfigPaths() returns both json and jsonc paths', () => {
  54. process.env.XDG_CONFIG_HOME = '/tmp/xdg-config';
  55. expect(getOpenCodeConfigPaths()).toEqual([
  56. '/tmp/xdg-config/opencode/opencode.json',
  57. '/tmp/xdg-config/opencode/opencode.jsonc',
  58. ]);
  59. });
  60. test('getOpenCodeConfigPaths() respects OPENCODE_CONFIG_DIR', () => {
  61. process.env.OPENCODE_CONFIG_DIR = '/custom/directory';
  62. process.env.XDG_CONFIG_HOME = '/tmp/xdg-config';
  63. expect(getOpenCodeConfigPaths()).toEqual([
  64. '/custom/directory/opencode.json',
  65. '/custom/directory/opencode.jsonc',
  66. ]);
  67. });
  68. test('getConfigJson() returns correct path', () => {
  69. process.env.XDG_CONFIG_HOME = '/tmp/xdg-config';
  70. expect(getConfigJson()).toBe('/tmp/xdg-config/opencode/opencode.json');
  71. });
  72. test('getConfigJsonc() returns correct path', () => {
  73. process.env.XDG_CONFIG_HOME = '/tmp/xdg-config';
  74. expect(getConfigJsonc()).toBe('/tmp/xdg-config/opencode/opencode.jsonc');
  75. });
  76. test('getLiteConfig() returns correct path', () => {
  77. process.env.XDG_CONFIG_HOME = '/tmp/xdg-config';
  78. expect(getLiteConfig()).toBe(
  79. '/tmp/xdg-config/opencode/oh-my-opencode-slim.json',
  80. );
  81. });
  82. test('getLiteConfig() respects OPENCODE_CONFIG_DIR', () => {
  83. process.env.OPENCODE_CONFIG_DIR = '/custom/directory';
  84. expect(getLiteConfig()).toBe('/custom/directory/oh-my-opencode-slim.json');
  85. });
  86. describe('getExistingConfigPath()', () => {
  87. let tmpDir: string;
  88. afterEach(() => {
  89. if (tmpDir && existsSync(tmpDir)) {
  90. rmSync(tmpDir, { recursive: true, force: true });
  91. }
  92. });
  93. test('returns .json if it exists', () => {
  94. tmpDir = mkdtempSync(join(tmpdir(), 'opencode-test-'));
  95. process.env.XDG_CONFIG_HOME = tmpDir;
  96. const configDir = join(tmpDir, 'opencode');
  97. ensureConfigDir();
  98. const jsonPath = join(configDir, 'opencode.json');
  99. writeFileSync(jsonPath, '{}');
  100. expect(getExistingConfigPath()).toBe(jsonPath);
  101. });
  102. test("returns .jsonc if .json doesn't exist but .jsonc does", () => {
  103. tmpDir = mkdtempSync(join(tmpdir(), 'opencode-test-'));
  104. process.env.XDG_CONFIG_HOME = tmpDir;
  105. const configDir = join(tmpDir, 'opencode');
  106. ensureConfigDir();
  107. const jsoncPath = join(configDir, 'opencode.jsonc');
  108. writeFileSync(jsoncPath, '{}');
  109. expect(getExistingConfigPath()).toBe(jsoncPath);
  110. });
  111. test('returns default .json if neither exists', () => {
  112. tmpDir = mkdtempSync(join(tmpdir(), 'opencode-test-'));
  113. process.env.XDG_CONFIG_HOME = tmpDir;
  114. const jsonPath = join(tmpDir, 'opencode', 'opencode.json');
  115. expect(getExistingConfigPath()).toBe(jsonPath);
  116. });
  117. });
  118. test("ensureConfigDir() creates directory if it doesn't exist", () => {
  119. const tmpDir = mkdtempSync(join(tmpdir(), 'opencode-test-'));
  120. process.env.XDG_CONFIG_HOME = tmpDir;
  121. const configDir = join(tmpDir, 'opencode');
  122. expect(existsSync(configDir)).toBe(false);
  123. ensureConfigDir();
  124. expect(existsSync(configDir)).toBe(true);
  125. rmSync(tmpDir, { recursive: true, force: true });
  126. });
  127. });