mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-03-11 17:21:03 +08:00
feat: implement ignore patterns and extension filters in CodexLens
- Added tests to ensure loading of ignore patterns and extension filters from settings. - Implemented functionality to respect ignore patterns and extension filters during file indexing. - Created integration tests for CodexLens ignore-pattern configuration routes. - Added a new AdvancedTab component with tests for managing ignore patterns and extension filters. - Established a comprehensive branding naming system for the Maestro project, including guidelines for package names, CLI commands, and directory structure.
This commit is contained in:
144
ccw/tests/integration/codexlens-ignore-pattern-routes.test.ts
Normal file
144
ccw/tests/integration/codexlens-ignore-pattern-routes.test.ts
Normal file
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* Integration tests for CodexLens ignore-pattern configuration routes.
|
||||
*
|
||||
* Notes:
|
||||
* - Targets runtime implementation shipped in `ccw/dist`.
|
||||
* - Calls route handler directly (no HTTP server required).
|
||||
* - Uses temporary CODEXLENS_DATA_DIR to isolate ~/.codexlens writes.
|
||||
*/
|
||||
|
||||
import { after, before, describe, it, mock } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
|
||||
const CODEXLENS_HOME = mkdtempSync(join(tmpdir(), 'codexlens-ignore-home-'));
|
||||
const PROJECT_ROOT = mkdtempSync(join(tmpdir(), 'codexlens-ignore-project-'));
|
||||
|
||||
const configRoutesUrl = new URL('../../dist/core/routes/codexlens/config-handlers.js', import.meta.url);
|
||||
configRoutesUrl.searchParams.set('t', String(Date.now()));
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
let mod: any;
|
||||
|
||||
const originalEnv = {
|
||||
CODEXLENS_DATA_DIR: process.env.CODEXLENS_DATA_DIR,
|
||||
};
|
||||
|
||||
async function callConfigRoute(
|
||||
initialPath: string,
|
||||
method: string,
|
||||
path: string,
|
||||
body?: unknown,
|
||||
): Promise<{ handled: boolean; status: number; json: any }> {
|
||||
const url = new URL(path, 'http://localhost');
|
||||
let status = 0;
|
||||
let text = '';
|
||||
let postPromise: Promise<void> | null = null;
|
||||
|
||||
const res = {
|
||||
writeHead(code: number) {
|
||||
status = code;
|
||||
},
|
||||
end(chunk?: unknown) {
|
||||
text = chunk === undefined ? '' : String(chunk);
|
||||
},
|
||||
};
|
||||
|
||||
const handlePostRequest = (_req: unknown, _res: unknown, handler: (parsed: any) => Promise<any>) => {
|
||||
postPromise = (async () => {
|
||||
const result = await handler(body ?? {});
|
||||
const errorValue = result && typeof result === 'object' ? result.error : undefined;
|
||||
const statusValue = result && typeof result === 'object' ? result.status : undefined;
|
||||
|
||||
if (typeof errorValue === 'string' && errorValue.length > 0) {
|
||||
res.writeHead(typeof statusValue === 'number' ? statusValue : 500);
|
||||
res.end(JSON.stringify({ error: errorValue }));
|
||||
return;
|
||||
}
|
||||
|
||||
res.writeHead(200);
|
||||
res.end(JSON.stringify(result));
|
||||
})();
|
||||
};
|
||||
|
||||
const handled = await mod.handleCodexLensConfigRoutes({
|
||||
pathname: url.pathname,
|
||||
url,
|
||||
req: { method },
|
||||
res,
|
||||
initialPath,
|
||||
handlePostRequest,
|
||||
broadcastToClients() {},
|
||||
});
|
||||
|
||||
if (postPromise) {
|
||||
await postPromise;
|
||||
}
|
||||
|
||||
return { handled, status, json: text ? JSON.parse(text) : null };
|
||||
}
|
||||
|
||||
describe('codexlens ignore-pattern routes integration', async () => {
|
||||
before(async () => {
|
||||
process.env.CODEXLENS_DATA_DIR = CODEXLENS_HOME;
|
||||
mock.method(console, 'log', () => {});
|
||||
mock.method(console, 'warn', () => {});
|
||||
mock.method(console, 'error', () => {});
|
||||
mod = await import(configRoutesUrl.href);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
mock.restoreAll();
|
||||
process.env.CODEXLENS_DATA_DIR = originalEnv.CODEXLENS_DATA_DIR;
|
||||
rmSync(CODEXLENS_HOME, { recursive: true, force: true });
|
||||
rmSync(PROJECT_ROOT, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it('GET /api/codexlens/ignore-patterns returns defaults before config exists', async () => {
|
||||
const res = await callConfigRoute(PROJECT_ROOT, 'GET', '/api/codexlens/ignore-patterns');
|
||||
|
||||
assert.equal(res.handled, true);
|
||||
assert.equal(res.status, 200);
|
||||
assert.equal(res.json.success, true);
|
||||
assert.equal(Array.isArray(res.json.patterns), true);
|
||||
assert.equal(Array.isArray(res.json.extensionFilters), true);
|
||||
assert.ok(res.json.patterns.includes('dist'));
|
||||
assert.ok(res.json.extensionFilters.includes('*.min.js'));
|
||||
});
|
||||
|
||||
it('POST /api/codexlens/ignore-patterns persists custom patterns and filters', async () => {
|
||||
const saveRes = await callConfigRoute(PROJECT_ROOT, 'POST', '/api/codexlens/ignore-patterns', {
|
||||
patterns: ['dist', 'frontend/dist'],
|
||||
extensionFilters: ['*.min.js', 'frontend/skip.ts'],
|
||||
});
|
||||
|
||||
assert.equal(saveRes.handled, true);
|
||||
assert.equal(saveRes.status, 200);
|
||||
assert.equal(saveRes.json.success, true);
|
||||
assert.deepEqual(saveRes.json.patterns, ['dist', 'frontend/dist']);
|
||||
assert.deepEqual(saveRes.json.extensionFilters, ['*.min.js', 'frontend/skip.ts']);
|
||||
|
||||
const settingsPath = join(CODEXLENS_HOME, 'settings.json');
|
||||
assert.equal(existsSync(settingsPath), true);
|
||||
const savedSettings = JSON.parse(readFileSync(settingsPath, 'utf8'));
|
||||
assert.deepEqual(savedSettings.ignore_patterns, ['dist', 'frontend/dist']);
|
||||
assert.deepEqual(savedSettings.extension_filters, ['*.min.js', 'frontend/skip.ts']);
|
||||
|
||||
const getRes = await callConfigRoute(PROJECT_ROOT, 'GET', '/api/codexlens/ignore-patterns');
|
||||
assert.equal(getRes.status, 200);
|
||||
assert.deepEqual(getRes.json.patterns, ['dist', 'frontend/dist']);
|
||||
assert.deepEqual(getRes.json.extensionFilters, ['*.min.js', 'frontend/skip.ts']);
|
||||
});
|
||||
|
||||
it('POST /api/codexlens/ignore-patterns rejects invalid entries', async () => {
|
||||
const res = await callConfigRoute(PROJECT_ROOT, 'POST', '/api/codexlens/ignore-patterns', {
|
||||
patterns: ['bad pattern!'],
|
||||
});
|
||||
|
||||
assert.equal(res.handled, true);
|
||||
assert.equal(res.status, 400);
|
||||
assert.match(String(res.json.error), /Invalid patterns:/);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user