oh-my-opencode/src/tools/look-at/image-converter.test.ts

61 lines
2.1 KiB
TypeScript

import { describe, expect, test, mock, beforeEach } from "bun:test"
import { existsSync, mkdtempSync, writeFileSync, unlinkSync, rmSync } from "node:fs"
import { tmpdir } from "node:os"
import { join } from "node:path"
const originalChildProcess = await import("node:child_process")
const execFileSyncMock = mock((_command: string, _args: string[]) => "")
const execSyncMock = mock(() => {
throw new Error("execSync should not be called")
})
mock.module("node:child_process", () => ({
...originalChildProcess,
execFileSync: execFileSyncMock,
execSync: execSyncMock,
}))
const { convertImageToJpeg } = await import("./image-converter")
describe("image-converter command execution safety", () => {
beforeEach(() => {
execFileSyncMock.mockReset()
execSyncMock.mockReset()
})
test("uses execFileSync with argument arrays for conversion commands", () => {
const testDir = mkdtempSync(join(tmpdir(), "img-converter-test-"))
const inputPath = join(testDir, "evil$(touch_pwn).heic")
writeFileSync(inputPath, "fake-heic-data")
execFileSyncMock.mockImplementation((command: string, args: string[]) => {
if (command === "sips") {
const outIndex = args.indexOf("--out")
const outputPath = outIndex >= 0 ? args[outIndex + 1] : undefined
if (outputPath) writeFileSync(outputPath, "jpeg")
} else if (command === "convert") {
writeFileSync(args[1], "jpeg")
}
return ""
})
const outputPath = convertImageToJpeg(inputPath, "image/heic")
expect(execSyncMock).not.toHaveBeenCalled()
expect(execFileSyncMock).toHaveBeenCalled()
const [firstCommand, firstArgs] = execFileSyncMock.mock.calls[0] as [string, string[]]
expect(typeof firstCommand).toBe("string")
expect(Array.isArray(firstArgs)).toBe(true)
expect(firstArgs).toContain(inputPath)
expect(firstArgs.join(" ")).not.toContain(`\"${inputPath}\"`)
expect(existsSync(outputPath)).toBe(true)
if (existsSync(outputPath)) unlinkSync(outputPath)
if (existsSync(inputPath)) unlinkSync(inputPath)
rmSync(testDir, { recursive: true, force: true })
})
})