import { describe, expect, test } from 'bun:test'; import { chmodSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { delimiter, join } from 'node:path'; import { childEnv } from '../cli/lib/runner'; import { detectTools, parseVersion, toolPath } from '../cli/lib/tools'; describe('local tools (desktop Dependencies screen)', () => { test('version banners', () => { expect(parseVersion('ffmpeg version 7.1.1 Copyright (c) 2000-2025')).toBe('7.1.1'); expect(parseVersion('ffmpeg version N-118000-g1234abcd-20250101 Copyright')).toBe('N-118000-g1234abcd-20250101'); expect(parseVersion('Google Chrome for Testing 131.0.6778.85')).toBe('131.0.6778.85'); expect(parseVersion('Android Debug Bridge version 1.0.41')).toBe('1.0.41'); expect(parseVersion('git version 2.50.1')).toBe('2.50.1'); expect(parseVersion(null)).toBeNull(); }); test('app-managed folders go first on PATH, also for every child command', () => { expect(toolPath({ PATH: '/usr/bin', STOREBOUND_TOOL_PATH: '/app/tools/bin' })).toBe(['/app/tools/bin', '/usr/bin'].join(delimiter)); expect(toolPath({ PATH: '/usr/bin' })).toBe('/usr/bin'); const before = process.env.STOREBOUND_TOOL_PATH; process.env.STOREBOUND_TOOL_PATH = '/app/tools/bin'; try { expect(childEnv().PATH!.startsWith('/app/tools/bin' + delimiter)).toBe(true); } finally { if (before === undefined) delete process.env.STOREBOUND_TOOL_PATH; else process.env.STOREBOUND_TOOL_PATH = before; } }); test('an app-managed ffmpeg is found first and marked as the app\'s', () => { if (process.platform === 'win32') return; const dir = mkdtempSync(join(tmpdir(), 'sb-tools-')); try { const f = join(dir, 'ffmpeg'); writeFileSync(f, '#!/bin/sh\necho "ffmpeg version 7.1.1-test Copyright"\n'); chmodSync(f, 0o755); const tools = detectTools({ PATH: '/usr/bin:/bin', STOREBOUND_TOOL_PATH: dir }); const ff = tools.find(t => t.id === 'ffmpeg')!; expect(ff).toMatchObject({ found: true, path: f, version: '7.1.1-test', source: 'app', install: { kind: 'download' } }); expect(tools.map(t => t.id)).toEqual(expect.arrayContaining(['ffmpeg', 'ffprobe', 'chrome', 'adb', 'git'])); for (const t of tools) if (t.id === 'xcode' || t.id === 'simctl' || t.id === 'adb') expect(t.install.kind).toBe('link'); } finally { rmSync(dir, { recursive: true, force: true }); } }, 30_000); // detectTools runs every tool's version command (xcrun, simctl, adb, ...): seconds on a busy Mac });