system.test.ts 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /// <reference types="bun-types" />
  2. import { describe, expect, mock, test } from 'bun:test';
  3. import {
  4. chmodSync,
  5. mkdirSync,
  6. mkdtempSync,
  7. rmSync,
  8. writeFileSync,
  9. } from 'node:fs';
  10. import { tmpdir } from 'node:os';
  11. import { join } from 'node:path';
  12. import {
  13. fetchLatestVersion,
  14. getOpenCodeVersion,
  15. isOpenCodeInstalled,
  16. isTmuxInstalled,
  17. } from './system';
  18. describe('system', () => {
  19. test('isOpenCodeInstalled detects opencode in ~/.opencode/bin', async () => {
  20. const dir = mkdtempSync(join(tmpdir(), 'opencode-system-test-'));
  21. const originalPath = process.env.PATH;
  22. const originalHome = process.env.HOME;
  23. try {
  24. const opencodePath = join(dir, '.opencode', 'bin', 'opencode');
  25. mkdirSync(join(dir, '.opencode', 'bin'), { recursive: true });
  26. writeFileSync(opencodePath, '#!/bin/sh\necho 1.2.3\n');
  27. chmodSync(opencodePath, 0o755);
  28. process.env.HOME = dir;
  29. process.env.PATH = '/usr/bin:/bin:/usr/sbin:/sbin';
  30. const system = await import(`./system?test=home-detect-${Date.now()}`);
  31. expect(await system.isOpenCodeInstalled()).toBe(true);
  32. } finally {
  33. process.env.PATH = originalPath;
  34. process.env.HOME = originalHome;
  35. rmSync(dir, { recursive: true, force: true });
  36. }
  37. });
  38. test('isOpenCodeInstalled returns boolean', async () => {
  39. // We don't necessarily want to depend on the host system
  40. // but for a basic test we can just check it returns a boolean
  41. const result = await isOpenCodeInstalled();
  42. expect(typeof result).toBe('boolean');
  43. });
  44. test('isTmuxInstalled returns boolean', async () => {
  45. const result = await isTmuxInstalled();
  46. expect(typeof result).toBe('boolean');
  47. });
  48. test('fetchLatestVersion returns version string or null', async () => {
  49. // Mock global fetch
  50. const originalFetch = globalThis.fetch;
  51. globalThis.fetch = mock(async () => {
  52. return {
  53. ok: true,
  54. json: async () => ({ version: '1.2.3' }),
  55. };
  56. }) as any;
  57. try {
  58. const version = await fetchLatestVersion('any-package');
  59. expect(version).toBe('1.2.3');
  60. } finally {
  61. globalThis.fetch = originalFetch;
  62. }
  63. });
  64. test('fetchLatestVersion returns null on error', async () => {
  65. const originalFetch = globalThis.fetch;
  66. try {
  67. globalThis.fetch = mock(async () => {
  68. return {
  69. ok: false,
  70. };
  71. }) as any;
  72. const version = await fetchLatestVersion('any-package');
  73. expect(version).toBeNull();
  74. } finally {
  75. globalThis.fetch = originalFetch;
  76. }
  77. });
  78. test('getOpenCodeVersion returns string or null', async () => {
  79. const version = await getOpenCodeVersion();
  80. if (version !== null) {
  81. expect(typeof version).toBe('string');
  82. } else {
  83. expect(version).toBeNull();
  84. }
  85. });
  86. });