mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-03-01 22:00:18 +01:00
🔐 feat: Granular Role-based Permissions + Entra ID Group Discovery (#7804)
WIP: pre-granular-permissions commit
feat: Add category and support contact fields to Agent schema and UI components
Revert "feat: Add category and support contact fields to Agent schema and UI components"
This reverts commit c43a52b4c9.
Fix: Update import for renderHook in useAgentCategories.spec.tsx
fix: Update icon rendering in AgentCategoryDisplay tests to use empty spans
refactor: Improve category synchronization logic and clean up AgentConfig component
refactor: Remove unused UI flow translations from translation.json
feat: agent marketplace features
🔐 feat: Granular Role-based Permissions + Entra ID Group Discovery (#7804)
This commit is contained in:
parent
1fe977e48f
commit
2f3bbc3b34
143 changed files with 17590 additions and 629 deletions
|
|
@ -0,0 +1,141 @@
|
|||
import React from 'react';
|
||||
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import '@testing-library/jest-dom';
|
||||
import SearchBar from '../SearchBar';
|
||||
|
||||
// Mock useLocalize hook
|
||||
jest.mock('~/hooks/useLocalize', () => () => (key: string) => key);
|
||||
|
||||
// Mock useDebounce hook
|
||||
jest.mock('~/hooks', () => ({
|
||||
useDebounce: (value: string, delay: number) => value, // Return value immediately for testing
|
||||
}));
|
||||
|
||||
describe('SearchBar', () => {
|
||||
const mockOnSearch = jest.fn();
|
||||
const user = userEvent.setup();
|
||||
|
||||
beforeEach(() => {
|
||||
mockOnSearch.mockClear();
|
||||
});
|
||||
|
||||
it('renders with correct placeholder', () => {
|
||||
render(<SearchBar value="" onSearch={mockOnSearch} />);
|
||||
|
||||
const input = screen.getByRole('textbox');
|
||||
expect(input).toBeInTheDocument();
|
||||
expect(input).toHaveAttribute('placeholder', 'com_agents_search_placeholder');
|
||||
});
|
||||
|
||||
it('displays the provided value', () => {
|
||||
render(<SearchBar value="test query" onSearch={mockOnSearch} />);
|
||||
|
||||
const input = screen.getByDisplayValue('test query');
|
||||
expect(input).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('calls onSearch when user types', async () => {
|
||||
render(<SearchBar value="" onSearch={mockOnSearch} />);
|
||||
|
||||
const input = screen.getByRole('textbox');
|
||||
await user.type(input, 'test');
|
||||
|
||||
// Should call onSearch for each character due to debounce mock
|
||||
expect(mockOnSearch).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('shows clear button when there is text', () => {
|
||||
render(<SearchBar value="test" onSearch={mockOnSearch} />);
|
||||
|
||||
const clearButton = screen.getByRole('button', { name: 'com_agents_clear_search' });
|
||||
expect(clearButton).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not show clear button when text is empty', () => {
|
||||
render(<SearchBar value="" onSearch={mockOnSearch} />);
|
||||
|
||||
const clearButton = screen.queryByRole('button', { name: 'com_agents_clear_search' });
|
||||
expect(clearButton).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('clears search when clear button is clicked', async () => {
|
||||
render(<SearchBar value="test" onSearch={mockOnSearch} />);
|
||||
|
||||
const input = screen.getByRole('textbox');
|
||||
const clearButton = screen.getByRole('button', { name: 'com_agents_clear_search' });
|
||||
|
||||
// Verify initial state
|
||||
expect(input).toHaveValue('test');
|
||||
|
||||
await user.click(clearButton);
|
||||
|
||||
// Verify onSearch is called and input is cleared
|
||||
expect(mockOnSearch).toHaveBeenCalledWith('');
|
||||
expect(input).toHaveValue('');
|
||||
});
|
||||
|
||||
it('updates internal state when value prop changes', () => {
|
||||
const { rerender } = render(<SearchBar value="initial" onSearch={mockOnSearch} />);
|
||||
|
||||
expect(screen.getByDisplayValue('initial')).toBeInTheDocument();
|
||||
|
||||
rerender(<SearchBar value="updated" onSearch={mockOnSearch} />);
|
||||
|
||||
expect(screen.getByDisplayValue('updated')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('has proper accessibility attributes', () => {
|
||||
render(<SearchBar value="" onSearch={mockOnSearch} />);
|
||||
|
||||
const input = screen.getByRole('textbox');
|
||||
expect(input).toHaveAttribute('aria-label', 'com_agents_search_aria');
|
||||
});
|
||||
|
||||
it('applies custom className', () => {
|
||||
render(<SearchBar value="" onSearch={mockOnSearch} className="custom-class" />);
|
||||
|
||||
const container = screen.getByRole('textbox').closest('div');
|
||||
expect(container).toHaveClass('custom-class');
|
||||
});
|
||||
|
||||
it('prevents form submission on clear button click', async () => {
|
||||
const handleSubmit = jest.fn();
|
||||
|
||||
render(
|
||||
<form onSubmit={handleSubmit}>
|
||||
<SearchBar value="test" onSearch={mockOnSearch} />
|
||||
</form>,
|
||||
);
|
||||
|
||||
const clearButton = screen.getByRole('button', { name: 'com_agents_clear_search' });
|
||||
await user.click(clearButton);
|
||||
|
||||
expect(handleSubmit).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('handles rapid typing correctly', async () => {
|
||||
render(<SearchBar value="" onSearch={mockOnSearch} />);
|
||||
|
||||
const input = screen.getByRole('textbox');
|
||||
|
||||
// Type multiple characters quickly
|
||||
await user.type(input, 'quick');
|
||||
|
||||
// Should handle all characters
|
||||
expect(input).toHaveValue('quick');
|
||||
});
|
||||
|
||||
it('maintains focus after clear button click', async () => {
|
||||
render(<SearchBar value="test" onSearch={mockOnSearch} />);
|
||||
|
||||
const input = screen.getByRole('textbox');
|
||||
const clearButton = screen.getByRole('button', { name: 'com_agents_clear_search' });
|
||||
|
||||
input.focus();
|
||||
await user.click(clearButton);
|
||||
|
||||
// Input should still be in the document and ready for new input
|
||||
expect(input).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue