fix(cli): resolve linting errors in tests by using named imports from core

This commit is contained in:
mkorwel 2026-03-24 17:09:50 -07:00 committed by Matt Korwel
parent 2d443dbd83
commit a978de4363
No known key found for this signature in database
GPG key ID: BFC86C7BAF4E589F
5 changed files with 77 additions and 79 deletions

View file

@ -72,7 +72,8 @@ This skill guides the agent in conducting thorough code reviews.
- **Local Changes**: If changes are local... ...
```
- **`name`**: A unique identifier for the skill. This should match the directory name.
- **`name`**: A unique identifier for the skill. This should match the directory
name.
- **`description`**: A description of what the skill does and when Gemini should
use it.
- **Body**: The Markdown body of the file contains the instructions that guide
@ -81,8 +82,8 @@ This skill guides the agent in conducting thorough code reviews.
## Packaging and Distribution
To share a skill or distribute it as a standalone archive, you can package the
skill directory into a `.skill` file. This is essentially a ZIP archive that
the `gemini skills install` command can process.
skill directory into a `.skill` file. This is essentially a ZIP archive that the
`gemini skills install` command can process.
### Using the `skill-creator` toolchain
@ -121,7 +122,8 @@ gemini skills install ./my-skill.skill
gemini skills install ./my-skill.skill --scope workspace
```
After installation, remember to reload your session to pick up the new expertise:
After installation, remember to reload your session to pick up the new
expertise:
1. In an interactive session, run `/skills reload`.
2. Verify the installation with `/skills list`.

View file

@ -15,7 +15,7 @@ import {
} from 'vitest';
import { handleInstall, installCommand } from './install.js';
import yargs from 'yargs';
import * as core from '@google/gemini-cli-core';
import { debugLogger } from '@google/gemini-cli-core';
import type { Stats } from 'node:fs';
import * as path from 'node:path';
import { promptForSetting } from '../../config/extensions/extensionSettings.js';
@ -116,12 +116,8 @@ describe('handleInstall', () => {
let processSpy: MockInstance;
beforeEach(() => {
debugLogSpy = vi
.spyOn(core.debugLogger, 'log')
.mockImplementation(() => {});
debugErrorSpy = vi
.spyOn(core.debugLogger, 'error')
.mockImplementation(() => {});
debugLogSpy = vi.spyOn(debugLogger, 'log').mockImplementation(() => {});
debugErrorSpy = vi.spyOn(debugLogger, 'error').mockImplementation(() => {});
processSpy = vi
.spyOn(process, 'exit')
.mockImplementation(() => undefined as never);

View file

@ -23,6 +23,11 @@ import {
Storage,
generalistProfile,
type ContextManagementConfig,
PolicyDecision,
createPolicyEngineConfig,
loadServerHierarchicalMemory,
type Config,
TelemetryTarget,
} from '@google/gemini-cli-core';
import { loadCliConfig, parseArguments, type CliArgs } from './config.js';
import {
@ -30,7 +35,6 @@ import {
type MergedSettings,
createTestMergedSettings,
} from './settings.js';
import * as ServerConfig from '@google/gemini-cli-core';
import { isWorkspaceTrusted } from './trustedFolders.js';
import { ExtensionManager } from './extension-manager.js';
@ -150,9 +154,9 @@ vi.mock('@google/gemini-cli-core', async () => {
rules: [],
checkers: [],
defaultDecision: interactive
? ServerConfig.PolicyDecision.ASK_USER
: ServerConfig.PolicyDecision.DENY,
approvalMode: approvalMode ?? ServerConfig.ApprovalMode.DEFAULT,
? PolicyDecision.ASK_USER
: PolicyDecision.DENY,
approvalMode: approvalMode ?? ApprovalMode.DEFAULT,
nonInteractive: !interactive,
}),
),
@ -979,7 +983,7 @@ describe('Hierarchical Memory Loading (config.ts) - Placeholder Suite', () => {
]);
const argv = await parseArguments(createTestMergedSettings());
await loadCliConfig(settings, 'session-id', argv);
expect(ServerConfig.loadServerHierarchicalMemory).toHaveBeenCalledWith(
expect(loadServerHierarchicalMemory).toHaveBeenCalledWith(
expect.any(String),
[],
expect.any(Object),
@ -1009,7 +1013,7 @@ describe('Hierarchical Memory Loading (config.ts) - Placeholder Suite', () => {
const argv = await parseArguments(settings);
await loadCliConfig(settings, 'session-id', argv);
expect(ServerConfig.loadServerHierarchicalMemory).toHaveBeenCalledWith(
expect(loadServerHierarchicalMemory).toHaveBeenCalledWith(
expect.any(String),
[includeDir],
expect.any(Object),
@ -1038,7 +1042,7 @@ describe('Hierarchical Memory Loading (config.ts) - Placeholder Suite', () => {
const argv = await parseArguments(settings);
await loadCliConfig(settings, 'session-id', argv);
expect(ServerConfig.loadServerHierarchicalMemory).toHaveBeenCalledWith(
expect(loadServerHierarchicalMemory).toHaveBeenCalledWith(
expect.any(String),
[],
expect.any(Object),
@ -2739,7 +2743,7 @@ describe('loadCliConfig approval mode', () => {
'test-session',
argv,
);
expect(config.getApprovalMode()).toBe(ServerConfig.ApprovalMode.DEFAULT);
expect(config.getApprovalMode()).toBe(ApprovalMode.DEFAULT);
});
it('should set YOLO approval mode when --yolo flag is used', async () => {
@ -2750,7 +2754,7 @@ describe('loadCliConfig approval mode', () => {
'test-session',
argv,
);
expect(config.getApprovalMode()).toBe(ServerConfig.ApprovalMode.YOLO);
expect(config.getApprovalMode()).toBe(ApprovalMode.YOLO);
});
it('should set YOLO approval mode when -y flag is used', async () => {
@ -2761,7 +2765,7 @@ describe('loadCliConfig approval mode', () => {
'test-session',
argv,
);
expect(config.getApprovalMode()).toBe(ServerConfig.ApprovalMode.YOLO);
expect(config.getApprovalMode()).toBe(ApprovalMode.YOLO);
});
it('should set DEFAULT approval mode when --approval-mode=default', async () => {
@ -2772,7 +2776,7 @@ describe('loadCliConfig approval mode', () => {
'test-session',
argv,
);
expect(config.getApprovalMode()).toBe(ServerConfig.ApprovalMode.DEFAULT);
expect(config.getApprovalMode()).toBe(ApprovalMode.DEFAULT);
});
it('should set AUTO_EDIT approval mode when --approval-mode=auto_edit', async () => {
@ -2783,7 +2787,7 @@ describe('loadCliConfig approval mode', () => {
'test-session',
argv,
);
expect(config.getApprovalMode()).toBe(ServerConfig.ApprovalMode.AUTO_EDIT);
expect(config.getApprovalMode()).toBe(ApprovalMode.AUTO_EDIT);
});
it('should set YOLO approval mode when --approval-mode=yolo', async () => {
@ -2794,7 +2798,7 @@ describe('loadCliConfig approval mode', () => {
'test-session',
argv,
);
expect(config.getApprovalMode()).toBe(ServerConfig.ApprovalMode.YOLO);
expect(config.getApprovalMode()).toBe(ApprovalMode.YOLO);
});
it('should prioritize --approval-mode over --yolo when both would be valid (but validation prevents this)', async () => {
@ -2809,7 +2813,7 @@ describe('loadCliConfig approval mode', () => {
'test-session',
argv,
);
expect(config.getApprovalMode()).toBe(ServerConfig.ApprovalMode.DEFAULT);
expect(config.getApprovalMode()).toBe(ApprovalMode.DEFAULT);
});
it('should fall back to --yolo behavior when --approval-mode is not set', async () => {
@ -2820,7 +2824,7 @@ describe('loadCliConfig approval mode', () => {
'test-session',
argv,
);
expect(config.getApprovalMode()).toBe(ServerConfig.ApprovalMode.YOLO);
expect(config.getApprovalMode()).toBe(ApprovalMode.YOLO);
});
it('should set Plan approval mode when --approval-mode=plan is used and plan is enabled', async () => {
@ -2832,7 +2836,7 @@ describe('loadCliConfig approval mode', () => {
},
});
const config = await loadCliConfig(settings, 'test-session', argv);
expect(config.getApprovalMode()).toBe(ServerConfig.ApprovalMode.PLAN);
expect(config.getApprovalMode()).toBe(ApprovalMode.PLAN);
});
it('should ignore "yolo" in settings.tools.approvalMode and fall back to DEFAULT', async () => {
@ -2845,7 +2849,7 @@ describe('loadCliConfig approval mode', () => {
});
const argv = await parseArguments(settings);
const config = await loadCliConfig(settings, 'test-session', argv);
expect(config.getApprovalMode()).toBe(ServerConfig.ApprovalMode.DEFAULT);
expect(config.getApprovalMode()).toBe(ApprovalMode.DEFAULT);
});
it('should throw error when --approval-mode=plan is used but plan is disabled', async () => {
@ -2902,7 +2906,7 @@ describe('loadCliConfig approval mode', () => {
'test-session',
argv,
);
expect(config.getApprovalMode()).toBe(ServerConfig.ApprovalMode.DEFAULT);
expect(config.getApprovalMode()).toBe(ApprovalMode.DEFAULT);
});
it('should override --approval-mode=auto_edit to DEFAULT', async () => {
@ -2913,7 +2917,7 @@ describe('loadCliConfig approval mode', () => {
'test-session',
argv,
);
expect(config.getApprovalMode()).toBe(ServerConfig.ApprovalMode.DEFAULT);
expect(config.getApprovalMode()).toBe(ApprovalMode.DEFAULT);
});
it('should override --yolo flag to DEFAULT', async () => {
@ -2924,7 +2928,7 @@ describe('loadCliConfig approval mode', () => {
'test-session',
argv,
);
expect(config.getApprovalMode()).toBe(ServerConfig.ApprovalMode.DEFAULT);
expect(config.getApprovalMode()).toBe(ApprovalMode.DEFAULT);
});
it('should remain DEFAULT when --approval-mode=default', async () => {
@ -2935,7 +2939,7 @@ describe('loadCliConfig approval mode', () => {
'test-session',
argv,
);
expect(config.getApprovalMode()).toBe(ServerConfig.ApprovalMode.DEFAULT);
expect(config.getApprovalMode()).toBe(ApprovalMode.DEFAULT);
});
});
@ -2947,9 +2951,7 @@ describe('loadCliConfig approval mode', () => {
});
const argv = await parseArguments(settings);
const config = await loadCliConfig(settings, 'test-session', argv);
expect(config.getApprovalMode()).toBe(
ServerConfig.ApprovalMode.AUTO_EDIT,
);
expect(config.getApprovalMode()).toBe(ApprovalMode.AUTO_EDIT);
});
it('should prioritize --approval-mode flag over settings', async () => {
@ -2959,9 +2961,7 @@ describe('loadCliConfig approval mode', () => {
});
const argv = await parseArguments(settings);
const config = await loadCliConfig(settings, 'test-session', argv);
expect(config.getApprovalMode()).toBe(
ServerConfig.ApprovalMode.AUTO_EDIT,
);
expect(config.getApprovalMode()).toBe(ApprovalMode.AUTO_EDIT);
});
it('should prioritize --yolo flag over settings', async () => {
@ -2971,7 +2971,7 @@ describe('loadCliConfig approval mode', () => {
});
const argv = await parseArguments(settings);
const config = await loadCliConfig(settings, 'test-session', argv);
expect(config.getApprovalMode()).toBe(ServerConfig.ApprovalMode.YOLO);
expect(config.getApprovalMode()).toBe(ApprovalMode.YOLO);
});
it('should respect plan mode from settings when plan is enabled', async () => {
@ -2984,7 +2984,7 @@ describe('loadCliConfig approval mode', () => {
});
const argv = await parseArguments(settings);
const config = await loadCliConfig(settings, 'test-session', argv);
expect(config.getApprovalMode()).toBe(ServerConfig.ApprovalMode.PLAN);
expect(config.getApprovalMode()).toBe(ApprovalMode.PLAN);
});
it('should fall back to default if plan mode is in settings but disabled', async () => {
@ -3084,7 +3084,7 @@ describe('loadCliConfig fileFiltering', () => {
>;
const testCases: Array<{
property: keyof FileFilteringSettings;
getter: (config: ServerConfig.Config) => boolean;
getter: (config: Config) => boolean;
value: boolean;
}> = [
{
@ -3328,7 +3328,7 @@ describe('Telemetry configuration via environment variables', () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments(createTestMergedSettings());
const settings = createTestMergedSettings({
telemetry: { target: ServerConfig.TelemetryTarget.LOCAL },
telemetry: { target: TelemetryTarget.LOCAL },
});
const config = await loadCliConfig(settings, 'test-session', argv);
expect(config.getTelemetryTarget()).toBe('gcp');
@ -3339,7 +3339,7 @@ describe('Telemetry configuration via environment variables', () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments(createTestMergedSettings());
const settings = createTestMergedSettings({
telemetry: { target: ServerConfig.TelemetryTarget.GCP },
telemetry: { target: TelemetryTarget.GCP },
});
await expect(loadCliConfig(settings, 'test-session', argv)).rejects.toThrow(
/Invalid telemetry configuration: .*Invalid telemetry target/i,
@ -3417,7 +3417,7 @@ describe('Telemetry configuration via environment variables', () => {
process.argv = ['node', 'script.js'];
const argv = await parseArguments(createTestMergedSettings());
const settings = createTestMergedSettings({
telemetry: { target: ServerConfig.TelemetryTarget.LOCAL },
telemetry: { target: TelemetryTarget.LOCAL },
});
const config = await loadCliConfig(settings, 'test-session', argv);
expect(config.getTelemetryTarget()).toBe('local');
@ -3541,7 +3541,7 @@ describe('Policy Engine Integration in loadCliConfig', () => {
await loadCliConfig(settings, 'test-session', argv);
expect(ServerConfig.createPolicyEngineConfig).toHaveBeenCalledWith(
expect(createPolicyEngineConfig).toHaveBeenCalledWith(
expect.objectContaining({
tools: expect.objectContaining({
allowed: expect.arrayContaining(['cli-tool']),
@ -3564,7 +3564,7 @@ describe('Policy Engine Integration in loadCliConfig', () => {
await loadCliConfig(settings, 'test-session', argv);
// In non-interactive mode, only ask_user is excluded by default
expect(ServerConfig.createPolicyEngineConfig).toHaveBeenCalledWith(
expect(createPolicyEngineConfig).toHaveBeenCalledWith(
expect.objectContaining({
tools: expect.objectContaining({
exclude: expect.arrayContaining([ASK_USER_TOOL_NAME]),
@ -3588,7 +3588,7 @@ describe('Policy Engine Integration in loadCliConfig', () => {
await loadCliConfig(settings, 'test-session', argv);
expect(ServerConfig.createPolicyEngineConfig).toHaveBeenCalledWith(
expect(createPolicyEngineConfig).toHaveBeenCalledWith(
expect.objectContaining({
policyPaths: [
path.normalize('/path/to/policy1.toml'),

View file

@ -6,9 +6,13 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import * as path from 'node:path';
import {
isHeadlessMode,
Storage,
createPolicyEngineConfig,
} from '@google/gemini-cli-core';
import { loadCliConfig, type CliArgs } from './config.js';
import { createTestMergedSettings } from './settings.js';
import * as ServerConfig from '@google/gemini-cli-core';
import { isWorkspaceTrusted } from './trustedFolders.js';
import * as Policy from './policy.js';
@ -21,9 +25,9 @@ const mockCheckIntegrity = vi.fn();
const mockAcceptIntegrity = vi.fn();
vi.mock('@google/gemini-cli-core', async () => {
const actual = await vi.importActual<typeof ServerConfig>(
'@google/gemini-cli-core',
);
const actual = await vi.importActual<
typeof import('@google/gemini-cli-core')
>('@google/gemini-cli-core');
return {
...actual,
loadServerHierarchicalMemory: vi.fn().mockResolvedValue({
@ -61,11 +65,11 @@ describe('Workspace-Level Policy CLI Integration', () => {
hash: 'test-hash',
fileCount: 1,
});
vi.mocked(ServerConfig.isHeadlessMode).mockReturnValue(false);
vi.mocked(isHeadlessMode).mockReturnValue(false);
});
it('should have getWorkspacePoliciesDir on Storage class', () => {
const storage = new ServerConfig.Storage(MOCK_CWD);
const storage = new Storage(MOCK_CWD);
expect(storage.getWorkspacePoliciesDir).toBeDefined();
expect(typeof storage.getWorkspacePoliciesDir).toBe('function');
});
@ -81,7 +85,7 @@ describe('Workspace-Level Policy CLI Integration', () => {
await loadCliConfig(settings, 'test-session', argv, { cwd: MOCK_CWD });
expect(ServerConfig.createPolicyEngineConfig).toHaveBeenCalledWith(
expect(createPolicyEngineConfig).toHaveBeenCalledWith(
expect.objectContaining({
workspacePoliciesDir: expect.stringContaining(
path.join('.gemini', 'policies'),
@ -104,7 +108,7 @@ describe('Workspace-Level Policy CLI Integration', () => {
await loadCliConfig(settings, 'test-session', argv, { cwd: MOCK_CWD });
expect(ServerConfig.createPolicyEngineConfig).toHaveBeenCalledWith(
expect(createPolicyEngineConfig).toHaveBeenCalledWith(
expect.objectContaining({
workspacePoliciesDir: undefined,
}),
@ -130,7 +134,7 @@ describe('Workspace-Level Policy CLI Integration', () => {
await loadCliConfig(settings, 'test-session', argv, { cwd: MOCK_CWD });
expect(ServerConfig.createPolicyEngineConfig).toHaveBeenCalledWith(
expect(createPolicyEngineConfig).toHaveBeenCalledWith(
expect.objectContaining({
workspacePoliciesDir: undefined,
}),
@ -150,7 +154,7 @@ describe('Workspace-Level Policy CLI Integration', () => {
hash: 'new-hash',
fileCount: 1,
});
vi.mocked(ServerConfig.isHeadlessMode).mockReturnValue(true); // Non-interactive
vi.mocked(isHeadlessMode).mockReturnValue(true); // Non-interactive
const settings = createTestMergedSettings();
const argv = { prompt: 'do something' } as unknown as CliArgs;
@ -162,7 +166,7 @@ describe('Workspace-Level Policy CLI Integration', () => {
MOCK_CWD,
'new-hash',
);
expect(ServerConfig.createPolicyEngineConfig).toHaveBeenCalledWith(
expect(createPolicyEngineConfig).toHaveBeenCalledWith(
expect.objectContaining({
workspacePoliciesDir: expect.stringContaining(
path.join('.gemini', 'policies'),
@ -184,7 +188,7 @@ describe('Workspace-Level Policy CLI Integration', () => {
hash: 'new-hash',
fileCount: 1,
});
vi.mocked(ServerConfig.isHeadlessMode).mockReturnValue(false); // Interactive
vi.mocked(isHeadlessMode).mockReturnValue(false); // Interactive
const settings = createTestMergedSettings();
const argv = {
@ -202,7 +206,7 @@ describe('Workspace-Level Policy CLI Integration', () => {
MOCK_CWD,
'new-hash',
);
expect(ServerConfig.createPolicyEngineConfig).toHaveBeenCalledWith(
expect(createPolicyEngineConfig).toHaveBeenCalledWith(
expect.objectContaining({
workspacePoliciesDir: expect.stringContaining(
path.join('.gemini', 'policies'),
@ -224,7 +228,7 @@ describe('Workspace-Level Policy CLI Integration', () => {
hash: 'new-hash',
fileCount: 5,
});
vi.mocked(ServerConfig.isHeadlessMode).mockReturnValue(false); // Interactive
vi.mocked(isHeadlessMode).mockReturnValue(false); // Interactive
const settings = createTestMergedSettings();
const argv = { query: 'test' } as unknown as CliArgs;
@ -240,7 +244,7 @@ describe('Workspace-Level Policy CLI Integration', () => {
'new-hash',
);
expect(ServerConfig.createPolicyEngineConfig).toHaveBeenCalledWith(
expect(createPolicyEngineConfig).toHaveBeenCalledWith(
expect.objectContaining({
workspacePoliciesDir: expect.stringContaining(
path.join('.gemini', 'policies'),
@ -267,7 +271,7 @@ describe('Workspace-Level Policy CLI Integration', () => {
hash: 'new-hash',
fileCount: 1,
});
vi.mocked(ServerConfig.isHeadlessMode).mockReturnValue(false); // Interactive
vi.mocked(isHeadlessMode).mockReturnValue(false); // Interactive
const settings = createTestMergedSettings();
const argv = {
@ -285,7 +289,7 @@ describe('Workspace-Level Policy CLI Integration', () => {
policyDir: expect.stringContaining(path.join('.gemini', 'policies')),
newHash: 'new-hash',
});
expect(ServerConfig.createPolicyEngineConfig).toHaveBeenCalledWith(
expect(createPolicyEngineConfig).toHaveBeenCalledWith(
expect.objectContaining({
workspacePoliciesDir: undefined,
}),

View file

@ -6,7 +6,11 @@
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { setupWorktree } from './worktreeSetup.js';
import * as coreFunctions from '@google/gemini-cli-core';
import {
getProjectRootForWorktree,
createWorktreeService,
writeToStderr,
} from '@google/gemini-cli-core';
// Mock dependencies
vi.mock('@google/gemini-cli-core', async (importOriginal) => {
@ -47,12 +51,8 @@ describe('setupWorktree', () => {
});
// Mock successful execution of core utilities
vi.mocked(coreFunctions.getProjectRootForWorktree).mockResolvedValue(
'/mock/project',
);
vi.mocked(coreFunctions.createWorktreeService).mockResolvedValue(
mockService as never,
);
vi.mocked(getProjectRootForWorktree).mockResolvedValue('/mock/project');
vi.mocked(createWorktreeService).mockResolvedValue(mockService as never);
mockService.setup.mockResolvedValue({
name: 'my-feature',
path: '/mock/project/.gemini/worktrees/my-feature',
@ -69,12 +69,8 @@ describe('setupWorktree', () => {
it('should create and switch to a new worktree', async () => {
await setupWorktree('my-feature');
expect(coreFunctions.getProjectRootForWorktree).toHaveBeenCalledWith(
'/mock/project',
);
expect(coreFunctions.createWorktreeService).toHaveBeenCalledWith(
'/mock/project',
);
expect(getProjectRootForWorktree).toHaveBeenCalledWith('/mock/project');
expect(createWorktreeService).toHaveBeenCalledWith('/mock/project');
expect(mockService.setup).toHaveBeenCalledWith('my-feature');
expect(process.chdir).toHaveBeenCalledWith(
'/mock/project/.gemini/worktrees/my-feature',
@ -99,7 +95,7 @@ describe('setupWorktree', () => {
await setupWorktree('my-feature');
expect(coreFunctions.createWorktreeService).not.toHaveBeenCalled();
expect(createWorktreeService).not.toHaveBeenCalled();
expect(process.chdir).not.toHaveBeenCalled();
});
@ -112,7 +108,7 @@ describe('setupWorktree', () => {
await expect(setupWorktree('my-feature')).rejects.toThrow('PROCESS_EXIT');
expect(coreFunctions.writeToStderr).toHaveBeenCalledWith(
expect(writeToStderr).toHaveBeenCalledWith(
expect.stringContaining(
'Failed to create or switch to worktree: Git failure',
),