Migrate tests to use avoid jsdom (#12118)

This commit is contained in:
Jacob Richman
2025-10-28 10:32:15 -07:00
committed by GitHub
parent 5d61adf804
commit 13aa0148e7
31 changed files with 765 additions and 579 deletions
@@ -4,13 +4,12 @@
* SPDX-License-Identifier: Apache-2.0
*/
/** @vitest-environment jsdom */
import { renderHook, act, waitFor } from '@testing-library/react';
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { act } from 'react';
import { renderHook } from '../../test-utils/render.js';
import { useShellHistory } from './useShellHistory.js';
import * as fs from 'node:fs/promises';
import * as path from 'node:path';
import * as os from 'node:os';
import * as crypto from 'node:crypto';
import { GEMINI_DIR } from '@google/gemini-cli-core';
@@ -19,7 +18,14 @@ vi.mock('node:fs/promises', () => ({
writeFile: vi.fn(),
mkdir: vi.fn(),
}));
vi.mock('node:os');
const mockHomedir = vi.hoisted(() => vi.fn(() => '/tmp/mock-home'));
vi.mock('node:os', async (importOriginal) => {
const actual = await importOriginal<typeof import('node:os')>();
return {
...actual,
homedir: mockHomedir,
};
});
vi.mock('node:crypto');
vi.mock('node:fs', async (importOriginal) => {
const actualFs = await importOriginal<typeof import('node:fs')>();
@@ -33,6 +39,9 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
await importOriginal<typeof import('@google/gemini-cli-core')>();
const path = await import('node:path');
class Storage {
static getGlobalSettingsPath(): string {
return '/test/home/.gemini/settings.json';
}
getProjectTempDir(): string {
return path.join('/test/home/', actual.GEMINI_DIR, 'tmp', 'mocked_hash');
}
@@ -68,7 +77,6 @@ const MOCKED_HISTORY_FILE = path.join(MOCKED_HISTORY_DIR, 'shell_history');
describe('useShellHistory', () => {
const mockedFs = vi.mocked(fs);
const mockedOs = vi.mocked(os);
const mockedCrypto = vi.mocked(crypto);
beforeEach(() => {
@@ -77,7 +85,7 @@ describe('useShellHistory', () => {
mockedFs.readFile.mockResolvedValue('');
mockedFs.writeFile.mockResolvedValue(undefined);
mockedFs.mkdir.mockResolvedValue(undefined);
mockedOs.homedir.mockReturnValue(MOCKED_HOME_DIR);
mockHomedir.mockReturnValue(MOCKED_HOME_DIR);
const hashMock = {
update: vi.fn().mockReturnThis(),
@@ -90,7 +98,7 @@ describe('useShellHistory', () => {
mockedFs.readFile.mockResolvedValue('cmd1\ncmd2');
const { result } = renderHook(() => useShellHistory(MOCKED_PROJECT_ROOT));
await waitFor(() => {
await vi.waitFor(() => {
expect(mockedFs.readFile).toHaveBeenCalledWith(
MOCKED_HISTORY_FILE,
'utf-8',
@@ -113,7 +121,7 @@ describe('useShellHistory', () => {
const { result } = renderHook(() => useShellHistory(MOCKED_PROJECT_ROOT));
await waitFor(() => {
await vi.waitFor(() => {
expect(mockedFs.readFile).toHaveBeenCalled();
});
@@ -128,13 +136,15 @@ describe('useShellHistory', () => {
it('should add a command and write to the history file', async () => {
const { result } = renderHook(() => useShellHistory(MOCKED_PROJECT_ROOT));
await waitFor(() => expect(mockedFs.readFile).toHaveBeenCalled());
await vi.waitFor(() => {
expect(mockedFs.readFile).toHaveBeenCalled();
});
act(() => {
result.current.addCommandToHistory('new_command');
});
await waitFor(() => {
await vi.waitFor(() => {
expect(mockedFs.mkdir).toHaveBeenCalledWith(MOCKED_HISTORY_DIR, {
recursive: true,
});
@@ -156,7 +166,9 @@ describe('useShellHistory', () => {
const { result } = renderHook(() => useShellHistory(MOCKED_PROJECT_ROOT));
// Wait for history to be loaded: ['cmd3', 'cmd2', 'cmd1']
await waitFor(() => expect(mockedFs.readFile).toHaveBeenCalled());
await vi.waitFor(() => {
expect(mockedFs.readFile).toHaveBeenCalled();
});
let command: string | null = null;
@@ -200,7 +212,10 @@ describe('useShellHistory', () => {
it('should not add empty or whitespace-only commands to history', async () => {
const { result } = renderHook(() => useShellHistory(MOCKED_PROJECT_ROOT));
await waitFor(() => expect(mockedFs.readFile).toHaveBeenCalled());
await vi.waitFor(() => {
expect(mockedFs.readFile).toHaveBeenCalled();
});
act(() => {
result.current.addCommandToHistory(' ');
@@ -214,14 +229,18 @@ describe('useShellHistory', () => {
mockedFs.readFile.mockResolvedValue(oldCommands.join('\n'));
const { result } = renderHook(() => useShellHistory(MOCKED_PROJECT_ROOT));
await waitFor(() => expect(mockedFs.readFile).toHaveBeenCalled());
await vi.waitFor(() => {
expect(mockedFs.readFile).toHaveBeenCalled();
});
act(() => {
result.current.addCommandToHistory('new_cmd');
});
// Wait for the async write to happen and then inspect the arguments.
await waitFor(() => expect(mockedFs.writeFile).toHaveBeenCalled());
await vi.waitFor(() => {
expect(mockedFs.writeFile).toHaveBeenCalled();
});
// The hook stores history newest-first.
// Initial state: ['old_cmd_119', ..., 'old_cmd_0']
@@ -240,15 +259,20 @@ describe('useShellHistory', () => {
const { result } = renderHook(() => useShellHistory(MOCKED_PROJECT_ROOT));
// Initial state: ['cmd3', 'cmd2', 'cmd1']
await waitFor(() => expect(mockedFs.readFile).toHaveBeenCalled());
await vi.waitFor(() => {
expect(mockedFs.readFile).toHaveBeenCalled();
});
act(() => {
result.current.addCommandToHistory('cmd1');
});
// After re-adding 'cmd1': ['cmd1', 'cmd3', 'cmd2']
// Written to file (reversed): ['cmd2', 'cmd3', 'cmd1']
await waitFor(() => expect(mockedFs.writeFile).toHaveBeenCalled());
expect(mockedFs.readFile).toHaveBeenCalled();
await vi.waitFor(() => {
expect(mockedFs.writeFile).toHaveBeenCalled();
});
const writtenContent = mockedFs.writeFile.mock.calls[0][1] as string;
const writtenLines = writtenContent.split('\n');