ESLint fixes

This commit is contained in:
Atef Bellaaj 2025-06-24 14:37:19 +02:00 committed by Danny Avila
parent 33c4ef03c3
commit c6e1c65fe7
No known key found for this signature in database
GPG key ID: BF31EEB2C5CA0956
9 changed files with 114 additions and 56 deletions

View file

@ -456,7 +456,7 @@ describe('Accessibility Improvements', () => {
expect(alert).toHaveAttribute('aria-atomic', 'true');
// Check heading structure
const heading = screen.getByRole('heading', { level: 2 });
const heading = screen.getByRole('heading', { level: 3 });
expect(heading).toHaveAttribute('id', 'error-title');
});

View file

@ -1,5 +1,5 @@
import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { MemoryRouter, useNavigate } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
@ -19,6 +19,7 @@ jest.mock('react-router-dom', () => ({
jest.mock('~/hooks', () => ({
useToast: jest.fn(),
useMediaQuery: jest.fn(() => false), // Mock as desktop by default
}));
jest.mock('~/hooks/useLocalize', () => ({
@ -33,11 +34,7 @@ jest.mock('~/utils/agents', () => ({
}));
// Mock clipboard API
Object.assign(navigator, {
clipboard: {
writeText: jest.fn(),
},
});
const mockWriteText = jest.fn();
const mockNavigate = jest.fn();
const mockShowToast = jest.fn();
@ -55,17 +52,23 @@ const mockAgent: t.Agent = {
provider: 'openai',
instructions: 'You are a helpful test agent',
tools: [],
code_interpreter: false,
file_search: false,
author: 'test-user-id',
author_name: 'Test User',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
created_at: new Date().getTime(),
version: 1,
support_contact: {
name: 'Support Team',
email: 'support@test.com',
},
model_parameters: {
model: undefined,
temperature: null,
maxContextTokens: null,
max_context_tokens: null,
max_output_tokens: null,
top_p: null,
frequency_penalty: null,
presence_penalty: null,
},
};
// Helper function to render with providers
@ -95,8 +98,19 @@ describe('AgentDetail', () => {
(useToast as jest.Mock).mockReturnValue({ showToast: mockShowToast });
(useLocalize as jest.Mock).mockReturnValue(mockLocalize);
// Reset clipboard mock
(navigator.clipboard.writeText as jest.Mock).mockResolvedValue(undefined);
// Setup clipboard mock if it doesn't exist
if (!navigator.clipboard) {
Object.defineProperty(navigator, 'clipboard', {
value: {
writeText: mockWriteText,
},
configurable: true,
});
} else {
// If clipboard exists, spy on it
jest.spyOn(navigator.clipboard, 'writeText').mockImplementation(mockWriteText);
}
mockWriteText.mockResolvedValue(undefined);
});
const defaultProps = {
@ -224,12 +238,18 @@ describe('AgentDetail', () => {
const copyLinkButton = screen.getByRole('button', { name: 'com_agents_copy_link' });
await user.click(copyLinkButton);
expect(navigator.clipboard.writeText).toHaveBeenCalledWith(
// Wait for async clipboard operation to complete
await waitFor(() => {
expect(mockWriteText).toHaveBeenCalledWith(
`${window.location.origin}/c/new?agent_id=test-agent-id`,
);
});
await waitFor(() => {
expect(mockShowToast).toHaveBeenCalledWith({
message: 'Link copied',
});
});
// Dropdown should close
await waitFor(() => {
@ -241,7 +261,7 @@ describe('AgentDetail', () => {
it('should show error toast when clipboard write fails', async () => {
const user = userEvent.setup();
(navigator.clipboard.writeText as jest.Mock).mockRejectedValue(new Error('Clipboard error'));
mockWriteText.mockRejectedValue(new Error('Clipboard error'));
renderWithProviders(<AgentDetail {...defaultProps} />);
@ -252,6 +272,11 @@ describe('AgentDetail', () => {
const copyLinkButton = screen.getByRole('button', { name: 'com_agents_copy_link' });
await user.click(copyLinkButton);
// Wait for clipboard operation to fail and error toast to show
await waitFor(() => {
expect(mockWriteText).toHaveBeenCalled();
});
await waitFor(() => {
expect(mockShowToast).toHaveBeenCalledWith({
message: 'com_agents_link_copy_failed',
@ -261,7 +286,7 @@ describe('AgentDetail', () => {
it('should call onClose when dialog is closed', () => {
const mockOnClose = jest.fn();
render(<AgentDetail {...defaultProps} onClose={mockOnClose} isOpen={false} />);
renderWithProviders(<AgentDetail {...defaultProps} onClose={mockOnClose} isOpen={false} />);
// Since we're testing the onOpenChange callback, we need to trigger it
// This would normally be done by the Dialog component when ESC is pressed or overlay is clicked

View file

@ -1,5 +1,5 @@
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom';
import CategoryTabs from '../CategoryTabs';

View file

@ -301,5 +301,3 @@ describe('ErrorDisplay', () => {
});
});
});
export default {};

View file

@ -1,5 +1,5 @@
import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom';
import SearchBar from '../SearchBar';
@ -9,7 +9,7 @@ jest.mock('~/hooks/useLocalize', () => () => (key: string) => key);
// Mock useDebounce hook
jest.mock('~/hooks', () => ({
useDebounce: (value: string, delay: number) => value, // Return value immediately for testing
useDebounce: (value: string) => value, // Return value immediately for testing
}));
describe('SearchBar', () => {

View file

@ -193,8 +193,6 @@ export const useUploadAgentAvatarMutation = (
t.AgentAvatarVariables, // request
unknown // context
> => {
const queryClient = useQueryClient();
return useMutation([MutationKeys.agentAvatarUpload], {
mutationFn: ({ postCreation, ...variables }: t.AgentAvatarVariables) =>
dataService.uploadAgentAvatar(variables),

View file

@ -1,6 +1,8 @@
import { renderHook } from '@testing-library/react';
import React from 'react';
import { renderHook, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import useAgentCategories from '../useAgentCategories';
import { AGENT_CATEGORIES, EMPTY_AGENT_CATEGORY } from '~/constants/agentCategories';
import { EMPTY_AGENT_CATEGORY } from '~/constants/agentCategories';
// Mock the useLocalize hook
jest.mock('~/hooks/useLocalize', () => ({
@ -11,25 +13,68 @@ jest.mock('~/hooks/useLocalize', () => ({
},
}));
describe('useAgentCategories', () => {
it('should return processed categories with correct structure', () => {
const { result } = renderHook(() => useAgentCategories());
// Mock the data provider
jest.mock('~/data-provider/Agents', () => ({
useGetAgentCategoriesQuery: jest.fn(() => ({
data: [
{ value: 'general', label: 'com_ui_agent_category_general' },
{ value: 'hr', label: 'com_ui_agent_category_hr' },
{ value: 'rd', label: 'com_ui_agent_category_rd' },
{ value: 'finance', label: 'com_ui_agent_category_finance' },
{ value: 'it', label: 'com_ui_agent_category_it' },
{ value: 'sales', label: 'com_ui_agent_category_sales' },
{ value: 'aftersales', label: 'com_ui_agent_category_aftersales' },
{ value: 'promoted', label: 'Promoted' }, // Should be filtered out
{ value: 'all', label: 'All' }, // Should be filtered out
],
isLoading: false,
error: null,
})),
}));
// Check that we have the expected number of categories
expect(result.current.categories.length).toBe(AGENT_CATEGORIES.length);
const createWrapper = () => {
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
});
return ({ children }: { children: React.ReactNode }) => (
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
);
};
describe('useAgentCategories', () => {
it('should return processed categories with correct structure', async () => {
const { result } = renderHook(() => useAgentCategories(), {
wrapper: createWrapper(),
});
await waitFor(() => {
// Check that we have the expected number of categories (excluding 'promoted' and 'all')
expect(result.current.categories.length).toBe(7);
});
// Check that the first category has the expected structure
const firstCategory = result.current.categories[0];
const firstOriginalCategory = AGENT_CATEGORIES[0];
expect(firstCategory.value).toBe(firstOriginalCategory.value);
// Check that labels are properly translated
expect(firstCategory.label).toBe('General (Translated)');
expect(firstCategory.value).toBe('general');
expect(firstCategory.label).toBe('com_ui_agent_category_general');
expect(firstCategory.className).toBe('w-full');
// Verify special categories are filtered out
const categoryValues = result.current.categories.map((cat) => cat.value);
expect(categoryValues).not.toContain('promoted');
expect(categoryValues).not.toContain('all');
// Check the empty category
expect(result.current.emptyCategory.value).toBe(EMPTY_AGENT_CATEGORY.value);
expect(result.current.emptyCategory.label).toBeTruthy();
expect(result.current.emptyCategory.label).toBe('General (Translated)');
expect(result.current.emptyCategory.className).toBe('w-full');
// Check loading state
expect(result.current.isLoading).toBe(false);
expect(result.current.error).toBeNull();
});
});

View file

@ -1,11 +1,5 @@
import { useMemo } from 'react';
import {
MessageSquareQuote,
ArrowRightToLine,
Settings2, Database,
Bookmark,
LayoutGrid,
} from 'lucide-react';
import { MessageSquareQuote, ArrowRightToLine, Settings2, Database, Bookmark } from 'lucide-react';
import {
isAssistantsEndpoint,
isAgentsEndpoint,
@ -27,7 +21,6 @@ import FilesPanel from '~/components/SidePanel/Files/Panel';
import MCPPanel from '~/components/SidePanel/MCP/MCPPanel';
import { useGetStartupConfig } from '~/data-provider';
import { useHasAccess } from '~/hooks';
import { useNavigate } from 'react-router-dom';
export default function useSideNavLinks({
hidePanel,
@ -44,7 +37,6 @@ export default function useSideNavLinks({
interfaceConfig: Partial<TInterfaceConfig>;
endpointsConfig: TEndpointsConfig;
}) {
const navigate = useNavigate();
const hasAccessToPrompts = useHasAccess({
permissionType: PermissionTypes.PROMPTS,
permission: Permissions.USE,

View file

@ -33,7 +33,7 @@ describe('Agent Utilities', () => {
id: '1',
name: 'Test Agent',
avatar: '/path/to/avatar.png',
} as t.Agent;
} as unknown as t.Agent;
expect(getAgentAvatarUrl(agent)).toBe('/path/to/avatar.png');
});
@ -62,7 +62,7 @@ describe('Agent Utilities', () => {
id: '1',
name: 'Test Agent',
avatar: '/test-avatar.png',
} as t.Agent;
} as unknown as t.Agent;
render(<div>{renderAgentAvatar(agent)}</div>);
@ -90,7 +90,7 @@ describe('Agent Utilities', () => {
id: '1',
name: 'Test Agent',
avatar: '/test-avatar.png',
} as t.Agent;
} as unknown as t.Agent;
const { rerender } = render(<div>{renderAgentAvatar(agent, { size: 'sm' })}</div>);
expect(screen.getByAltText('Test Agent avatar')).toHaveClass('h-12', 'w-12');
@ -107,7 +107,7 @@ describe('Agent Utilities', () => {
id: '1',
name: 'Test Agent',
avatar: '/test-avatar.png',
} as t.Agent;
} as unknown as t.Agent;
render(<div>{renderAgentAvatar(agent, { className: 'custom-class' })}</div>);
@ -120,7 +120,7 @@ describe('Agent Utilities', () => {
id: '1',
name: 'Test Agent',
avatar: '/test-avatar.png',
} as t.Agent;
} as unknown as t.Agent;
const { rerender } = render(<div>{renderAgentAvatar(agent, { showBorder: true })}</div>);
expect(screen.getByAltText('Test Agent avatar')).toHaveClass('border-2');