From 394312b9c2f6006293b344a3c2b81da17332a2d5 Mon Sep 17 00:00:00 2001 From: Eddie Santos <9561596+eddie-santos@users.noreply.github.com> Date: Sun, 8 Jun 2025 12:42:42 -0700 Subject: [PATCH] Add tests for `core/utils/editor` (#851) --- packages/core/src/utils/editor.test.ts | 117 +++++++++++++++++++++++++ packages/core/src/utils/editor.ts | 18 ++-- 2 files changed, 126 insertions(+), 9 deletions(-) create mode 100644 packages/core/src/utils/editor.test.ts diff --git a/packages/core/src/utils/editor.test.ts b/packages/core/src/utils/editor.test.ts new file mode 100644 index 00000000..74237c74 --- /dev/null +++ b/packages/core/src/utils/editor.test.ts @@ -0,0 +1,117 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { vi, describe, it, expect, beforeEach, type Mock } from 'vitest'; +import { checkHasEditor, getDiffCommand, openDiff } from './editor.js'; +import { execSync, spawn } from 'child_process'; + +vi.mock('child_process', () => ({ + execSync: vi.fn(), + spawn: vi.fn(), +})); + +describe('checkHasEditor', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('should return true for vscode if "code" command exists', () => { + (execSync as Mock).mockReturnValue(Buffer.from('/usr/bin/code')); + expect(checkHasEditor('vscode')).toBe(true); + expect(execSync).toHaveBeenCalledWith('which code', { stdio: 'ignore' }); + }); + + it('should return false for vscode if "code" command does not exist', () => { + (execSync as Mock).mockImplementation(() => { + throw new Error(); + }); + expect(checkHasEditor('vscode')).toBe(false); + }); + + it('should return true for vim if "vim" command exists', () => { + (execSync as Mock).mockReturnValue(Buffer.from('/usr/bin/vim')); + expect(checkHasEditor('vim')).toBe(true); + expect(execSync).toHaveBeenCalledWith('which vim', { stdio: 'ignore' }); + }); + + it('should return false for vim if "vim" command does not exist', () => { + (execSync as Mock).mockImplementation(() => { + throw new Error(); + }); + expect(checkHasEditor('vim')).toBe(false); + }); +}); + +describe('getDiffCommand', () => { + it('should return the correct command for vscode', () => { + const command = getDiffCommand('old.txt', 'new.txt', 'vscode'); + expect(command).toEqual({ + command: 'code', + args: ['--wait', '--diff', 'old.txt', 'new.txt'], + }); + }); + + it('should return the correct command for vim', () => { + const command = getDiffCommand('old.txt', 'new.txt', 'vim'); + expect(command?.command).toBe('vim'); + expect(command?.args).toContain('old.txt'); + expect(command?.args).toContain('new.txt'); + }); + + it('should return null for an unsupported editor', () => { + // @ts-expect-error Testing unsupported editor + const command = getDiffCommand('old.txt', 'new.txt', 'nano'); + expect(command).toBeNull(); + }); +}); + +describe('openDiff', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('should call spawn for vscode', async () => { + const mockSpawn = { + on: vi.fn((event, cb) => { + if (event === 'close') { + cb(0); + } + }), + }; + (spawn as Mock).mockReturnValue(mockSpawn); + await openDiff('old.txt', 'new.txt', 'vscode'); + expect(spawn).toHaveBeenCalledWith( + 'code', + ['--wait', '--diff', 'old.txt', 'new.txt'], + { stdio: 'inherit' }, + ); + expect(mockSpawn.on).toHaveBeenCalledWith('close', expect.any(Function)); + expect(mockSpawn.on).toHaveBeenCalledWith('error', expect.any(Function)); + }); + + it('should call execSync for vim', async () => { + await openDiff('old.txt', 'new.txt', 'vim'); + expect(execSync).toHaveBeenCalled(); + const command = (execSync as Mock).mock.calls[0][0]; + expect(command).toContain('vim'); + expect(command).toContain('old.txt'); + expect(command).toContain('new.txt'); + }); + + it('should handle spawn error for vscode', async () => { + const mockSpawn = { + on: vi.fn((event, cb) => { + if (event === 'error') { + cb(new Error('spawn error')); + } + }), + }; + (spawn as Mock).mockReturnValue(mockSpawn); + await expect(openDiff('old.txt', 'new.txt', 'vscode')).rejects.toThrow( + 'spawn error', + ); + }); +}); diff --git a/packages/core/src/utils/editor.ts b/packages/core/src/utils/editor.ts index 6f65d8da..447aa0d2 100644 --- a/packages/core/src/utils/editor.ts +++ b/packages/core/src/utils/editor.ts @@ -13,16 +13,16 @@ interface DiffCommand { args: string[]; } -export function checkHasEditor(editor: EditorType): boolean { - const commandExists = (cmd: string): boolean => { - try { - execSync(`which ${cmd}`, { stdio: 'ignore' }); - return true; - } catch { - return false; - } - }; +function commandExists(cmd: string): boolean { + try { + execSync(`which ${cmd}`, { stdio: 'ignore' }); + return true; + } catch { + return false; + } +} +export function checkHasEditor(editor: EditorType): boolean { if (editor === 'vscode') { return commandExists('code'); } else if (editor === 'vim') {