mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-21 11:30:38 -07:00
Consolidate tests.
This commit is contained in:
@@ -1,92 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
||||
import * as path from 'node:path';
|
||||
import * as fs from 'node:fs/promises';
|
||||
import * as os from 'node:os';
|
||||
import { GrepTool } from '../packages/core/src/tools/grep.js';
|
||||
import { Config } from '../packages/core/src/config/config.js';
|
||||
import { WorkspaceContext } from '../packages/core/src/utils/workspaceContext.js';
|
||||
|
||||
// Mock Config to provide necessary context
|
||||
class MockConfig {
|
||||
constructor(private targetDir: string) {}
|
||||
|
||||
getTargetDir() {
|
||||
return this.targetDir;
|
||||
}
|
||||
|
||||
getWorkspaceContext() {
|
||||
return new WorkspaceContext(this.targetDir, [this.targetDir]);
|
||||
}
|
||||
|
||||
getDebugMode() {
|
||||
return true;
|
||||
}
|
||||
|
||||
getFileFilteringOptions() {
|
||||
return {
|
||||
respectGitIgnore: true,
|
||||
respectGeminiIgnore: true,
|
||||
customIgnoreFilePaths: [],
|
||||
};
|
||||
}
|
||||
|
||||
getFileExclusions() {
|
||||
return {
|
||||
getGlobExcludes: () => [],
|
||||
};
|
||||
}
|
||||
|
||||
validatePathAccess() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
describe('grep-total-max-matches', () => {
|
||||
let tempDir: string;
|
||||
let tool: GrepTool;
|
||||
|
||||
beforeAll(async () => {
|
||||
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'grep-total-max-test-'));
|
||||
|
||||
// Create a test file with multiple matches
|
||||
const content = `
|
||||
match 1
|
||||
match 2
|
||||
match 3
|
||||
match 4
|
||||
match 5
|
||||
`;
|
||||
await fs.writeFile(path.join(tempDir, 'many_matches.txt'), content);
|
||||
|
||||
const config = new MockConfig(tempDir) as unknown as Config;
|
||||
tool = new GrepTool(config, null!);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await fs.rm(tempDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it('should limit total matches when total_max_matches is set', async () => {
|
||||
const invocation = tool.build({
|
||||
pattern: 'match',
|
||||
total_max_matches: 3,
|
||||
});
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(result.llmContent).toContain('Found 3 matches');
|
||||
expect(result.llmContent).toContain('match 1');
|
||||
expect(result.llmContent).toContain('match 2');
|
||||
expect(result.llmContent).toContain('match 3');
|
||||
expect(result.llmContent).not.toContain('match 4');
|
||||
expect(result.llmContent).not.toContain('match 5');
|
||||
expect(result.llmContent).toContain(
|
||||
'(results limited to 3 matches for performance)',
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,108 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
||||
import * as path from 'node:path';
|
||||
import * as fs from 'node:fs/promises';
|
||||
import * as os from 'node:os';
|
||||
import { RipGrepTool } from '../packages/core/src/tools/ripGrep.js';
|
||||
import { Config } from '../packages/core/src/config/config.js';
|
||||
import { WorkspaceContext } from '../packages/core/src/utils/workspaceContext.js';
|
||||
|
||||
// Mock Config to provide necessary context
|
||||
class MockConfig {
|
||||
constructor(private targetDir: string) {}
|
||||
|
||||
getTargetDir() {
|
||||
return this.targetDir;
|
||||
}
|
||||
|
||||
getWorkspaceContext() {
|
||||
return new WorkspaceContext(this.targetDir, [this.targetDir]);
|
||||
}
|
||||
|
||||
getDebugMode() {
|
||||
return true;
|
||||
}
|
||||
|
||||
getFileFilteringRespectGeminiIgnore() {
|
||||
return true;
|
||||
}
|
||||
|
||||
getFileFilteringOptions() {
|
||||
return {
|
||||
respectGitIgnore: true,
|
||||
respectGeminiIgnore: true,
|
||||
customIgnoreFilePaths: [],
|
||||
};
|
||||
}
|
||||
|
||||
validatePathAccess() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
describe('ripgrep-max-matches', () => {
|
||||
let tempDir: string;
|
||||
let tool: RipGrepTool;
|
||||
|
||||
beforeAll(async () => {
|
||||
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'ripgrep-max-test-'));
|
||||
|
||||
// Create a test file with multiple matches
|
||||
const content = `
|
||||
match 1
|
||||
filler
|
||||
match 2
|
||||
filler
|
||||
match 3
|
||||
filler
|
||||
match 4
|
||||
`;
|
||||
await fs.writeFile(path.join(tempDir, 'many_matches.txt'), content);
|
||||
|
||||
const config = new MockConfig(tempDir) as unknown as Config;
|
||||
tool = new RipGrepTool(config);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await fs.rm(tempDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it('should limit matches per file when max_matches_per_file is set', async () => {
|
||||
const invocation = tool.build({
|
||||
pattern: 'match',
|
||||
max_matches_per_file: 2,
|
||||
});
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(result.llmContent).toContain('Found 2 matches');
|
||||
expect(result.llmContent).toContain('many_matches.txt');
|
||||
expect(result.llmContent).toContain('match 1');
|
||||
expect(result.llmContent).toContain('match 2');
|
||||
expect(result.llmContent).not.toContain('match 3');
|
||||
expect(result.llmContent).not.toContain('match 4');
|
||||
});
|
||||
|
||||
it('should return all matches when max_matches_per_file is not set', async () => {
|
||||
const invocation = tool.build({ pattern: 'match' });
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(result.llmContent).toContain('Found 4 matches');
|
||||
expect(result.llmContent).toContain('match 1');
|
||||
expect(result.llmContent).toContain('match 2');
|
||||
expect(result.llmContent).toContain('match 3');
|
||||
expect(result.llmContent).toContain('match 4');
|
||||
});
|
||||
|
||||
it('should return context lines when requested', async () => {
|
||||
const invocation = tool.build({ pattern: 'match 1', context: 1 });
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(result.llmContent).toContain('match 1');
|
||||
expect(result.llmContent).toContain('filler'); // Context line
|
||||
});
|
||||
});
|
||||
@@ -1,107 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
||||
import * as path from 'node:path';
|
||||
import * as fs from 'node:fs/promises';
|
||||
import * as os from 'node:os';
|
||||
import { RipGrepTool } from '../packages/core/src/tools/ripGrep.js';
|
||||
import { Config } from '../packages/core/src/config/config.js';
|
||||
import { WorkspaceContext } from '../packages/core/src/utils/workspaceContext.js';
|
||||
|
||||
// Mock Config to provide necessary context
|
||||
class MockConfig {
|
||||
constructor(private targetDir: string) {}
|
||||
|
||||
getTargetDir() {
|
||||
return this.targetDir;
|
||||
}
|
||||
|
||||
getWorkspaceContext() {
|
||||
return new WorkspaceContext(this.targetDir, [this.targetDir]);
|
||||
}
|
||||
|
||||
getDebugMode() {
|
||||
return true;
|
||||
}
|
||||
|
||||
getFileFilteringRespectGeminiIgnore() {
|
||||
return true;
|
||||
}
|
||||
|
||||
getFileFilteringOptions() {
|
||||
return {
|
||||
respectGitIgnore: true,
|
||||
respectGeminiIgnore: true,
|
||||
customIgnoreFilePaths: [],
|
||||
};
|
||||
}
|
||||
|
||||
validatePathAccess() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
describe('ripgrep-real-direct', () => {
|
||||
let tempDir: string;
|
||||
let tool: RipGrepTool;
|
||||
|
||||
beforeAll(async () => {
|
||||
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'ripgrep-real-test-'));
|
||||
|
||||
// Create test files
|
||||
await fs.writeFile(path.join(tempDir, 'file1.txt'), 'hello world\n');
|
||||
await fs.mkdir(path.join(tempDir, 'subdir'));
|
||||
await fs.writeFile(
|
||||
path.join(tempDir, 'subdir', 'file2.txt'),
|
||||
'hello universe\n',
|
||||
);
|
||||
await fs.writeFile(path.join(tempDir, 'file3.txt'), 'goodbye moon\n');
|
||||
|
||||
const config = new MockConfig(tempDir) as unknown as Config;
|
||||
tool = new RipGrepTool(config);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await fs.rm(tempDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it('should find matches using the real ripgrep binary', async () => {
|
||||
const invocation = tool.build({ pattern: 'hello' });
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(result.llmContent).toContain('Found 2 matches');
|
||||
expect(result.llmContent).toContain('file1.txt');
|
||||
expect(result.llmContent).toContain('L1: hello world');
|
||||
expect(result.llmContent).toContain('subdir'); // Should show path
|
||||
expect(result.llmContent).toContain('file2.txt');
|
||||
expect(result.llmContent).toContain('L1: hello universe');
|
||||
|
||||
expect(result.llmContent).not.toContain('goodbye moon');
|
||||
});
|
||||
|
||||
it('should handle no matches correctly', async () => {
|
||||
const invocation = tool.build({ pattern: 'nonexistent_pattern_123' });
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(result.llmContent).toContain('No matches found');
|
||||
});
|
||||
|
||||
it('should respect include filters', async () => {
|
||||
// Create a .js file
|
||||
await fs.writeFile(
|
||||
path.join(tempDir, 'script.js'),
|
||||
'console.log("hello");\n',
|
||||
);
|
||||
|
||||
const invocation = tool.build({ pattern: 'hello', include: '*.js' });
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(result.llmContent).toContain('Found 1 match');
|
||||
expect(result.llmContent).toContain('script.js');
|
||||
expect(result.llmContent).not.toContain('file1.txt');
|
||||
});
|
||||
});
|
||||
@@ -1,100 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
||||
import * as path from 'node:path';
|
||||
import * as fs from 'node:fs/promises';
|
||||
import * as os from 'node:os';
|
||||
import { RipGrepTool } from '../packages/core/src/tools/ripGrep.js';
|
||||
import { Config } from '../packages/core/src/config/config.js';
|
||||
import { WorkspaceContext } from '../packages/core/src/utils/workspaceContext.js';
|
||||
|
||||
// Mock Config to provide necessary context
|
||||
class MockConfig {
|
||||
constructor(private targetDir: string) {}
|
||||
|
||||
getTargetDir() {
|
||||
return this.targetDir;
|
||||
}
|
||||
|
||||
getWorkspaceContext() {
|
||||
return new WorkspaceContext(this.targetDir, [this.targetDir]);
|
||||
}
|
||||
|
||||
getDebugMode() {
|
||||
return true;
|
||||
}
|
||||
|
||||
getFileFilteringRespectGeminiIgnore() {
|
||||
return true;
|
||||
}
|
||||
|
||||
getFileFilteringOptions() {
|
||||
return {
|
||||
respectGitIgnore: true,
|
||||
respectGeminiIgnore: true,
|
||||
customIgnoreFilePaths: [],
|
||||
};
|
||||
}
|
||||
|
||||
validatePathAccess() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
describe('ripgrep-total-max-matches', () => {
|
||||
let tempDir: string;
|
||||
let tool: RipGrepTool;
|
||||
|
||||
beforeAll(async () => {
|
||||
tempDir = await fs.mkdtemp(
|
||||
path.join(os.tmpdir(), 'ripgrep-total-max-test-'),
|
||||
);
|
||||
|
||||
// Create a test file with multiple matches
|
||||
const content = `
|
||||
match 1
|
||||
match 2
|
||||
match 3
|
||||
match 4
|
||||
match 5
|
||||
`;
|
||||
await fs.writeFile(path.join(tempDir, 'many_matches.txt'), content);
|
||||
|
||||
const config = new MockConfig(tempDir) as unknown as Config;
|
||||
tool = new RipGrepTool(config);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await fs.rm(tempDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it('should limit total matches when total_max_matches is set', async () => {
|
||||
const invocation = tool.build({
|
||||
pattern: 'match',
|
||||
total_max_matches: 3,
|
||||
});
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(result.llmContent).toContain('Found 3 matches');
|
||||
expect(result.llmContent).toContain('match 1');
|
||||
expect(result.llmContent).toContain('match 2');
|
||||
expect(result.llmContent).toContain('match 3');
|
||||
expect(result.llmContent).not.toContain('match 4');
|
||||
expect(result.llmContent).not.toContain('match 5');
|
||||
expect(result.llmContent).toContain(
|
||||
'(results limited to 3 matches for performance)',
|
||||
);
|
||||
});
|
||||
|
||||
it('should use default limit when total_max_matches is not set', async () => {
|
||||
// We can't easily test the default 100 without 100 matches, but we can verify it doesn't fail.
|
||||
const invocation = tool.build({ pattern: 'match' });
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(result.llmContent).toContain('Found 5 matches');
|
||||
});
|
||||
});
|
||||
235
integration-tests/search-tools.test.ts
Normal file
235
integration-tests/search-tools.test.ts
Normal file
@@ -0,0 +1,235 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
||||
import * as path from 'node:path';
|
||||
import * as fs from 'node:fs/promises';
|
||||
import * as os from 'node:os';
|
||||
import { GrepTool } from '../packages/core/src/tools/grep.js';
|
||||
import { RipGrepTool } from '../packages/core/src/tools/ripGrep.js';
|
||||
import { Config } from '../packages/core/src/config/config.js';
|
||||
import { WorkspaceContext } from '../packages/core/src/utils/workspaceContext.js';
|
||||
|
||||
// Mock Config to provide necessary context for both GrepTool and RipGrepTool
|
||||
class MockConfig {
|
||||
constructor(private targetDir: string) {}
|
||||
|
||||
getTargetDir() {
|
||||
return this.targetDir;
|
||||
}
|
||||
|
||||
getWorkspaceContext() {
|
||||
return new WorkspaceContext(this.targetDir, [this.targetDir]);
|
||||
}
|
||||
|
||||
getDebugMode() {
|
||||
return true;
|
||||
}
|
||||
|
||||
getFileFilteringRespectGeminiIgnore() {
|
||||
return true;
|
||||
}
|
||||
|
||||
getFileFilteringOptions() {
|
||||
return {
|
||||
respectGitIgnore: true,
|
||||
respectGeminiIgnore: true,
|
||||
customIgnoreFilePaths: [],
|
||||
};
|
||||
}
|
||||
|
||||
getFileExclusions() {
|
||||
return {
|
||||
getGlobExcludes: () => [],
|
||||
};
|
||||
}
|
||||
|
||||
validatePathAccess() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
describe('Search Tools Integration', () => {
|
||||
describe('RipGrepTool', () => {
|
||||
let tempDir: string;
|
||||
let tool: RipGrepTool;
|
||||
|
||||
beforeAll(async () => {
|
||||
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'ripgrep-test-'));
|
||||
|
||||
// Create test files
|
||||
await fs.writeFile(path.join(tempDir, 'file1.txt'), 'hello world\n');
|
||||
await fs.mkdir(path.join(tempDir, 'subdir'));
|
||||
await fs.writeFile(
|
||||
path.join(tempDir, 'subdir', 'file2.txt'),
|
||||
'hello universe\n',
|
||||
);
|
||||
await fs.writeFile(path.join(tempDir, 'file3.txt'), 'goodbye moon\n');
|
||||
await fs.writeFile(
|
||||
path.join(tempDir, 'script.js'),
|
||||
'console.log("hello");\n',
|
||||
);
|
||||
|
||||
// Create a file with multiple matches for limits testing
|
||||
const manyMatches = `
|
||||
match 1
|
||||
filler
|
||||
match 2
|
||||
filler
|
||||
match 3
|
||||
filler
|
||||
match 4
|
||||
match 5
|
||||
`;
|
||||
await fs.writeFile(path.join(tempDir, 'many_matches.txt'), manyMatches);
|
||||
|
||||
const config = new MockConfig(tempDir) as unknown as Config;
|
||||
tool = new RipGrepTool(config);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await fs.rm(tempDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
describe('Basic Functionality', () => {
|
||||
it('should find matches using the real ripgrep binary', async () => {
|
||||
const invocation = tool.build({ pattern: 'hello' });
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(result.llmContent).toContain('Found 3 matches'); // file1, file2, script.js
|
||||
expect(result.llmContent).toContain('file1.txt');
|
||||
expect(result.llmContent).toContain('L1: hello world');
|
||||
expect(result.llmContent).toContain('subdir');
|
||||
expect(result.llmContent).toContain('file2.txt');
|
||||
expect(result.llmContent).toContain('L1: hello universe');
|
||||
expect(result.llmContent).not.toContain('goodbye moon');
|
||||
});
|
||||
|
||||
it('should handle no matches correctly', async () => {
|
||||
const invocation = tool.build({ pattern: 'nonexistent_pattern_123' });
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(result.llmContent).toContain('No matches found');
|
||||
});
|
||||
|
||||
it('should respect include filters', async () => {
|
||||
const invocation = tool.build({ pattern: 'hello', include: '*.js' });
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(result.llmContent).toContain('Found 1 match');
|
||||
expect(result.llmContent).toContain('script.js');
|
||||
expect(result.llmContent).not.toContain('file1.txt');
|
||||
});
|
||||
|
||||
it('should return context lines when requested', async () => {
|
||||
const invocation = tool.build({ pattern: 'match 1', context: 1 });
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(result.llmContent).toContain('match 1');
|
||||
expect(result.llmContent).toContain('filler'); // Context line
|
||||
});
|
||||
});
|
||||
|
||||
describe('Limits', () => {
|
||||
it('should limit matches per file when max_matches_per_file is set', async () => {
|
||||
const invocation = tool.build({
|
||||
pattern: 'match',
|
||||
max_matches_per_file: 2,
|
||||
});
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(result.llmContent).toContain('Found 2 matches');
|
||||
expect(result.llmContent).toContain('many_matches.txt');
|
||||
expect(result.llmContent).toContain('match 1');
|
||||
expect(result.llmContent).toContain('match 2');
|
||||
expect(result.llmContent).not.toContain('match 3');
|
||||
expect(result.llmContent).not.toContain('match 4');
|
||||
});
|
||||
|
||||
it('should return all matches when max_matches_per_file is not set', async () => {
|
||||
// We test this on a file that has more matches than the previous limit
|
||||
const invocation = tool.build({ pattern: 'match' });
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(result.llmContent).toContain('match 1');
|
||||
expect(result.llmContent).toContain('match 2');
|
||||
expect(result.llmContent).toContain('match 3');
|
||||
expect(result.llmContent).toContain('match 4');
|
||||
expect(result.llmContent).toContain('match 5');
|
||||
});
|
||||
|
||||
it('should limit total matches when total_max_matches is set', async () => {
|
||||
const invocation = tool.build({
|
||||
pattern: 'match',
|
||||
total_max_matches: 3,
|
||||
});
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(result.llmContent).toContain('Found 3 matches');
|
||||
expect(result.llmContent).toContain('match 1');
|
||||
expect(result.llmContent).toContain('match 2');
|
||||
expect(result.llmContent).toContain('match 3');
|
||||
expect(result.llmContent).not.toContain('match 4');
|
||||
expect(result.llmContent).not.toContain('match 5');
|
||||
expect(result.llmContent).toContain(
|
||||
'(results limited to 3 matches for performance)',
|
||||
);
|
||||
});
|
||||
|
||||
it('should use default limit when total_max_matches is not set', async () => {
|
||||
const invocation = tool.build({ pattern: 'match' });
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
// Just verify it found everything available (5 matches)
|
||||
expect(result.llmContent).toContain('Found 5 matches');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('GrepTool', () => {
|
||||
let tempDir: string;
|
||||
let tool: GrepTool;
|
||||
|
||||
beforeAll(async () => {
|
||||
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'grep-test-'));
|
||||
|
||||
// Create a test file with multiple matches
|
||||
const content = `
|
||||
match 1
|
||||
match 2
|
||||
match 3
|
||||
match 4
|
||||
match 5
|
||||
`;
|
||||
await fs.writeFile(path.join(tempDir, 'many_matches.txt'), content);
|
||||
|
||||
const config = new MockConfig(tempDir) as unknown as Config;
|
||||
tool = new GrepTool(config, null!);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await fs.rm(tempDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it('should limit total matches when total_max_matches is set', async () => {
|
||||
const invocation = tool.build({
|
||||
pattern: 'match',
|
||||
total_max_matches: 3,
|
||||
});
|
||||
const result = await invocation.execute(new AbortController().signal);
|
||||
|
||||
expect(result.llmContent).toContain('Found 3 matches');
|
||||
expect(result.llmContent).toContain('match 1');
|
||||
expect(result.llmContent).toContain('match 2');
|
||||
expect(result.llmContent).toContain('match 3');
|
||||
expect(result.llmContent).not.toContain('match 4');
|
||||
expect(result.llmContent).not.toContain('match 5');
|
||||
expect(result.llmContent).toContain(
|
||||
'(results limited to 3 matches for performance)',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user