mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-03-12 17:21:19 +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:
154
ccw/frontend/src/components/codexlens/AdvancedTab.test.tsx
Normal file
154
ccw/frontend/src/components/codexlens/AdvancedTab.test.tsx
Normal file
@@ -0,0 +1,154 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
import { render, screen, waitFor } from '@/test/i18n';
|
||||
import { AdvancedTab } from './AdvancedTab';
|
||||
|
||||
vi.mock('@/hooks', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('@/hooks')>();
|
||||
return {
|
||||
...actual,
|
||||
useCodexLensEnv: vi.fn(),
|
||||
useUpdateCodexLensEnv: vi.fn(),
|
||||
useCodexLensIgnorePatterns: vi.fn(),
|
||||
useUpdateIgnorePatterns: vi.fn(),
|
||||
useNotifications: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
import {
|
||||
useCodexLensEnv,
|
||||
useUpdateCodexLensEnv,
|
||||
useCodexLensIgnorePatterns,
|
||||
useUpdateIgnorePatterns,
|
||||
useNotifications,
|
||||
} from '@/hooks';
|
||||
|
||||
const mockRefetchEnv = vi.fn().mockResolvedValue(undefined);
|
||||
const mockRefetchPatterns = vi.fn().mockResolvedValue(undefined);
|
||||
const mockUpdateEnv = vi.fn().mockResolvedValue({ success: true, message: 'Saved' });
|
||||
const mockUpdatePatterns = vi.fn().mockResolvedValue({
|
||||
success: true,
|
||||
patterns: ['dist', 'frontend/dist'],
|
||||
extensionFilters: ['*.min.js', 'frontend/skip.ts'],
|
||||
defaults: {
|
||||
patterns: ['dist', 'build'],
|
||||
extensionFilters: ['*.min.js'],
|
||||
},
|
||||
});
|
||||
const mockToastSuccess = vi.fn();
|
||||
const mockToastError = vi.fn();
|
||||
|
||||
function setupDefaultMocks() {
|
||||
vi.mocked(useCodexLensEnv).mockReturnValue({
|
||||
data: { success: true, env: {}, settings: {}, raw: '', path: '~/.codexlens/.env' },
|
||||
raw: '',
|
||||
env: {},
|
||||
settings: {},
|
||||
isLoading: false,
|
||||
error: null,
|
||||
refetch: mockRefetchEnv,
|
||||
});
|
||||
|
||||
vi.mocked(useUpdateCodexLensEnv).mockReturnValue({
|
||||
updateEnv: mockUpdateEnv,
|
||||
isUpdating: false,
|
||||
error: null,
|
||||
});
|
||||
|
||||
vi.mocked(useCodexLensIgnorePatterns).mockReturnValue({
|
||||
data: {
|
||||
success: true,
|
||||
patterns: ['dist', 'coverage'],
|
||||
extensionFilters: ['*.min.js', '*.map'],
|
||||
defaults: {
|
||||
patterns: ['dist', 'build', 'coverage'],
|
||||
extensionFilters: ['*.min.js', '*.map'],
|
||||
},
|
||||
},
|
||||
patterns: ['dist', 'coverage'],
|
||||
extensionFilters: ['*.min.js', '*.map'],
|
||||
defaults: {
|
||||
patterns: ['dist', 'build', 'coverage'],
|
||||
extensionFilters: ['*.min.js', '*.map'],
|
||||
},
|
||||
isLoading: false,
|
||||
error: null,
|
||||
refetch: mockRefetchPatterns,
|
||||
});
|
||||
|
||||
vi.mocked(useUpdateIgnorePatterns).mockReturnValue({
|
||||
updatePatterns: mockUpdatePatterns,
|
||||
isUpdating: false,
|
||||
error: null,
|
||||
});
|
||||
|
||||
vi.mocked(useNotifications).mockReturnValue({
|
||||
success: mockToastSuccess,
|
||||
error: mockToastError,
|
||||
} as ReturnType<typeof useNotifications>);
|
||||
}
|
||||
|
||||
describe('AdvancedTab', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
setupDefaultMocks();
|
||||
});
|
||||
|
||||
it('renders existing filter configuration', () => {
|
||||
render(<AdvancedTab enabled={true} />);
|
||||
|
||||
expect(screen.getByLabelText(/Ignored directories \/ paths/i)).toHaveValue('dist\ncoverage');
|
||||
expect(screen.getByLabelText(/Skipped files \/ globs/i)).toHaveValue('*.min.js\n*.map');
|
||||
expect(screen.getByText(/Directory filters: 2/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/File filters: 2/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('saves parsed filter configuration', async () => {
|
||||
render(<AdvancedTab enabled={true} />);
|
||||
|
||||
const ignorePatternsInput = screen.getByLabelText(/Ignored directories \/ paths/i);
|
||||
const extensionFiltersInput = screen.getByLabelText(/Skipped files \/ globs/i);
|
||||
|
||||
fireEvent.change(ignorePatternsInput, { target: { value: 'dist,\nfrontend/dist' } });
|
||||
fireEvent.change(extensionFiltersInput, { target: { value: '*.min.js,\nfrontend/skip.ts' } });
|
||||
fireEvent.click(screen.getByRole('button', { name: /Save filters/i }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockUpdatePatterns).toHaveBeenCalledWith({
|
||||
patterns: ['dist', 'frontend/dist'],
|
||||
extensionFilters: ['*.min.js', 'frontend/skip.ts'],
|
||||
});
|
||||
});
|
||||
expect(mockRefetchPatterns).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('restores default filter values before saving', async () => {
|
||||
render(<AdvancedTab enabled={true} />);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: /Restore defaults/i }));
|
||||
|
||||
expect(screen.getByLabelText(/Ignored directories \/ paths/i)).toHaveValue('dist\nbuild\ncoverage');
|
||||
expect(screen.getByLabelText(/Skipped files \/ globs/i)).toHaveValue('*.min.js\n*.map');
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: /Save filters/i }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockUpdatePatterns).toHaveBeenCalledWith({
|
||||
patterns: ['dist', 'build', 'coverage'],
|
||||
extensionFilters: ['*.min.js', '*.map'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('blocks invalid filter entries before saving', async () => {
|
||||
render(<AdvancedTab enabled={true} />);
|
||||
|
||||
fireEvent.change(screen.getByLabelText(/Ignored directories \/ paths/i), {
|
||||
target: { value: 'bad pattern!' },
|
||||
});
|
||||
fireEvent.click(screen.getByRole('button', { name: /Save filters/i }));
|
||||
|
||||
expect(mockUpdatePatterns).not.toHaveBeenCalled();
|
||||
expect(screen.getByText(/Invalid ignore patterns/i)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user