mono/packages/kbot/tests/unit/options-glob.test.ts

178 lines
8.0 KiB
TypeScript

import * as path from 'node:path'
import * as fsSync from 'node:fs' // For reading test file content directly
// import * as fs from 'node:fs/promises' // No longer needed for this test
import { describe, it, expect } from 'vitest' // Removed afterAll, beforeAll
import { E_Mode, run, IKBotTask, complete_options, complete_messages, complete_params, E_WrapMode } from '../../src/index'
// import { LOGGING_DIRECTORY } from '../../src/constants.js' // No longer needed for this test
// import { sync as rimrafSync } from 'rimraf' // No longer needed for this test
describe('globExtension with collected files verification', () => {
const testDataBaseDir = path.resolve(__dirname, '../test-data');
const testDataRoot = path.resolve(testDataBaseDir, 'glob');
// const defaultLogsDir = path.resolve(LOGGING_DIRECTORY); // No longer needed
// const paramsJsonPath = path.resolve(defaultLogsDir, 'params.json'); // No longer needed
// beforeAll/afterAll for log cleanup removed
const expectedFileNames = [
'PHApp.h',
'PHApp.cpp',
'PHApp-Modbus.cpp',
'PHApp-Profiles.cpp',
'PHAppNetwork.cpp',
'PHAppSettings.cpp',
'PHAppWeb.cpp',
'PHApp.md'
];
const expectedAbsoluteFilePaths = expectedFileNames.map(f => path.normalize(path.resolve(testDataRoot, f)));
const mockLogger = {
debug: () => {}, info: () => {}, warn: () => {}, error: () => {}, fatal: () => {},
} as any;
it('should collect .h, related .cpp, and .md files when using brace expansion in globExtension', async () => {
const initialOpts: IKBotTask = {
path: testDataRoot,
include: ['*.h'],
globExtension: '${SRC_DIR}/${SRC_NAME}*.{cpp,md}',
mode: E_Mode.COMPLETION,
prompt: 'test-prompt-direct-file-check',
logger: mockLogger,
// wrap: 'none' // Default is 'none', explicitly test this or remove for default
};
// 1. Complete Options
const completedOptions = await complete_options(initialOpts);
expect(completedOptions).not.toBeNull();
if (!completedOptions) return;
// 2. Complete Messages - and get the raw `files` array
const { files: collectedFileObjects } = await complete_messages(initialOpts, completedOptions);
expect(collectedFileObjects).toBeInstanceOf(Array);
// 3. Assert directly on the paths from collectedFileObjects
// These paths should be relative to `completedOptions.path` (which is testDataRoot)
const actualCollectedPaths: string[] = collectedFileObjects
.map((fileObj: any) => {
if (fileObj && typeof fileObj.path === 'string') {
return path.normalize(path.resolve(testDataRoot, fileObj.path));
}
return null;
})
.filter((p: string | null) => p !== null) as string[];
const collectedPathsSet = new Set(actualCollectedPaths);
// console.log("Expected absolute paths:", expectedAbsoluteFilePaths);
// console.log("Actual collected absolute paths:", actualCollectedPaths);
expectedAbsoluteFilePaths.forEach(expectedFile => {
expect(collectedPathsSet.has(expectedFile), `Expected file ${path.basename(expectedFile)} (${expectedFile}) to be collected.`).toBe(true);
});
expect(collectedPathsSet.size, "Number of unique collected files should match expected").toBe(expectedAbsoluteFilePaths.length);
}, 10000);
});
describe('globExtension and wrap modes with complete_params output', () => {
const testDataBaseDir = path.resolve(__dirname, '../test-data');
const testDataRoot = path.resolve(testDataBaseDir, 'glob');
const expectedFileNamesDefaultTest = [
'PHApp.h',
'PHApp.cpp',
'PHApp-Modbus.cpp',
'PHApp-Profiles.cpp',
'PHAppNetwork.cpp',
'PHAppSettings.cpp',
'PHAppWeb.cpp',
'PHApp.md'
];
const expectedAbsoluteFilePathsDefaultTest = expectedFileNamesDefaultTest.map(f => path.normalize(path.resolve(testDataRoot, f)));
const mockLogger = {
debug: () => {}, info: () => {}, warn: () => {}, error: () => {}, fatal: () => {},
} as any;
it('should collect .h, related .cpp, and .md files when using brace expansion in globExtension (default wrap:none)', async () => {
const initialOpts: IKBotTask = {
path: testDataRoot,
include: ['*.h'],
globExtension: '${SRC_DIR}/${SRC_NAME}*.{cpp,md}',
mode: E_Mode.COMPLETION,
prompt: 'test-prompt-direct-file-check',
logger: mockLogger,
};
// ... (existing test logic for wrap:none - this test remains the same)
// 1. Complete Options
const completedOptions = await complete_options(initialOpts);
expect(completedOptions).not.toBeNull();
if (!completedOptions) return;
// 2. Complete Messages - and get the raw `files` array
const { files: collectedFileObjects } = await complete_messages(initialOpts, completedOptions);
expect(collectedFileObjects).toBeInstanceOf(Array);
const actualCollectedPaths: string[] = collectedFileObjects
.map((fileObj: any) => {
if (fileObj && typeof fileObj.path === 'string') {
return path.normalize(path.resolve(testDataRoot, fileObj.path));
}
return null;
})
.filter((p: string | null) => p !== null) as string[];
const collectedPathsSet = new Set(actualCollectedPaths);
expectedAbsoluteFilePathsDefaultTest.forEach(expectedFile => {
expect(collectedPathsSet.has(expectedFile), `Expected file ${path.basename(expectedFile)} (${expectedFile}) to be collected.`).toBe(true);
});
expect(collectedPathsSet.size, "Number of unique collected files should match expected").toBe(expectedAbsoluteFilePathsDefaultTest.length);
}, 10000);
// New test case for wrap: 'meta'
it('should correctly wrap content with metadata when options.wrap is \'meta\'', async () => {
const targetFileName = 'PHApp.h';
const targetFileAbsolutePath = path.normalize(path.resolve(testDataRoot, targetFileName));
const originalFileContent = fsSync.readFileSync(targetFileAbsolutePath, 'utf-8');
const initialOptsMeta: IKBotTask = {
path: testDataRoot,
include: [targetFileName], // Focus on a single known text file
wrap: E_WrapMode.enum.meta, // Explicitly set wrap mode to meta
mode: E_Mode.COMPLETION,
prompt: 'test-prompt-wrap-meta',
logger: mockLogger,
};
const completedOptionsMeta = await complete_options(initialOptsMeta);
expect(completedOptionsMeta).not.toBeNull();
if (!completedOptionsMeta) return;
const { messages: gatheredMessagesMeta } = await complete_messages(initialOptsMeta, completedOptionsMeta);
const finalParamsMeta = await complete_params(completedOptionsMeta, gatheredMessagesMeta);
const targetFileMessage = finalParamsMeta.messages.find((msg: any) => {
if (msg.role === 'user' && typeof msg.content === 'string') {
// Check if the content contains the file path, good indicator for meta-wrapped file
// More robust: check if msg.content includes `File: ${targetFileName}`
return msg.content.includes(`File: ${targetFileName}`);
}
return false;
});
expect(targetFileMessage, `Message for ${targetFileName} should be found`).toBeDefined();
if (!targetFileMessage) return;
const messageContent = targetFileMessage.content as string;
expect(messageContent).toContain(`File: ${targetFileName}`);
expect(messageContent).toContain(`Absolute Path: ${targetFileAbsolutePath}`);
// expect(messageContent).toContain(`CWD: ${process.cwd()}`); // CWD can vary based on test runner, more fragile
expect(messageContent).toContain('\nOriginal Content:\n' + originalFileContent);
expect(messageContent.startsWith('IMPORTANT: The following information is file metadata.')).toBe(true);
expect(messageContent.includes('METADATA_START')).toBe(true);
expect(messageContent.includes('METADATA_END')).toBe(true);
}, 10000);
});
// To run this test, you would typically use your npm script, e.g., `npm run vi-test` or `npx vitest`