test: replacing queries by test id

This commit is contained in:
jacobo-dominguez-wgu
2025-11-03 14:47:18 -06:00
committed by Adolfo R. Brandes
parent eb224b9f71
commit 0572a73fb4
9 changed files with 119 additions and 119 deletions

View File

@@ -44,9 +44,9 @@ describe('AuthZTitle', () => {
});
it('renders page subtitle as ReactNode', () => {
const subtitleNode = <div data-testid="custom-subtitle">Custom Subtitle</div>;
const subtitleNode = <div>Custom Subtitle</div>;
render(<AuthZTitle {...defaultProps} pageSubtitle={subtitleNode} />);
expect(screen.getByTestId('custom-subtitle')).toBeInTheDocument();
expect(screen.getByText('Custom Subtitle')).toBeInTheDocument();
});
it('renders action buttons and triggers onClick', () => {
@@ -69,7 +69,7 @@ describe('AuthZTitle', () => {
});
it('renders action buttons with icons', () => {
const mockIcon = () => <span data-testid="mock-icon">Icon</span>;
const mockIcon = () => <span role="img" aria-label="save icon">Icon</span>;
const onClick = jest.fn();
const actions = [
{ label: 'Save', icon: mockIcon, onClick },
@@ -77,14 +77,14 @@ describe('AuthZTitle', () => {
render(<AuthZTitle {...defaultProps} actions={actions} />);
const button = screen.getByRole('button', { name: 'Icon Save' });
const button = screen.getByRole('button', { name: 'save icon Save' });
expect(button).toBeInTheDocument();
expect(screen.getByTestId('mock-icon')).toBeInTheDocument();
expect(screen.getByRole('img', { name: 'save icon' })).toBeInTheDocument();
});
it('renders ReactNode actions alongside button actions', () => {
const onClick = jest.fn();
const customAction = <div data-testid="custom-action">Custom Action</div>;
const customAction = <div role="region" aria-label="custom action area">Custom Action</div>;
const actions = [
{ label: 'Save', onClick },
customAction,
@@ -93,6 +93,6 @@ describe('AuthZTitle', () => {
render(<AuthZTitle {...defaultProps} actions={actions} />);
expect(screen.getByRole('button', { name: 'Save' })).toBeInTheDocument();
expect(screen.getByTestId('custom-action')).toBeInTheDocument();
expect(screen.getByRole('region', { name: 'custom action area' })).toBeInTheDocument();
});
});

View File

@@ -4,14 +4,14 @@ import userEvent from '@testing-library/user-event';
import RoleCard from '.';
jest.mock('@openedx/paragon/icons', () => ({
Delete: () => <svg data-testid="delete-icon" />,
Person: () => <svg data-testid="person-icon" />,
Delete: () => <svg role="img" aria-label="delete icon" />,
Person: () => <svg role="img" aria-label="person icon" />,
}));
jest.mock('./constants', () => ({
actionsDictionary: {
view: () => <svg data-testid="view-icon" />,
manage: () => <svg data-testid="manage-icon" />,
view: () => <svg role="img" aria-label="view action icon" />,
manage: () => <svg role="img" aria-label="manage action icon" />,
},
}));
@@ -47,7 +47,7 @@ describe('RoleCard', () => {
// User counter with icon
expect(screen.getByText('2')).toBeInTheDocument();
expect(screen.getByTestId('person-icon')).toBeInTheDocument();
expect(screen.getByRole('img', { name: 'person icon' })).toBeInTheDocument();
// Subtitle (object name)
expect(screen.getByText('Test Library')).toBeInTheDocument();
@@ -71,8 +71,8 @@ describe('RoleCard', () => {
expect(screen.getByText('Manage')).toBeInTheDocument();
// Action icons
expect(screen.getByTestId('view-icon')).toBeInTheDocument();
expect(screen.getByTestId('manage-icon')).toBeInTheDocument();
expect(screen.getByRole('img', { name: 'view action icon' })).toBeInTheDocument();
expect(screen.getByRole('img', { name: 'manage action icon' })).toBeInTheDocument();
});
it('does not show delete button when handleDelete is not passed', () => {
@@ -82,7 +82,7 @@ describe('RoleCard', () => {
it('handles no userCounter gracefully', () => {
renderWrapper(<RoleCard {...defaultProps} userCounter={null} />);
expect(screen.queryByTestId('person-icon')).not.toBeInTheDocument();
expect(screen.queryByRole('img', { name: 'person icon' })).not.toBeInTheDocument();
expect(screen.queryByText('2')).not.toBeInTheDocument();
});

View File

@@ -8,9 +8,12 @@ import AuthZModule from './index';
jest.mock('./libraries-manager', () => ({
// eslint-disable-next-line no-promise-executor-return
LibrariesLayout: lazy(() => new Promise<{ default: ComponentType<any> }>(resolve => setTimeout(() => resolve({ default: () => <div data-testid="layout"><Outlet /></div> }), 100))),
LibrariesTeamManager: () => <div data-testid="libraries-manager">Libraries Team Page</div>,
LibrariesUserManager: () => <div data-testid="libraries-user-manager">Libraries User Page</div>,
LibrariesLayout: lazy(() => new Promise<{ default: ComponentType<any> }>(resolve => setTimeout(
() => resolve({ default: () => <div><Outlet /></div> }),
100,
))),
LibrariesTeamManager: () => <div>Libraries Team Page</div>,
LibrariesUserManager: () => <div>Libraries User Page</div>,
}));
const createTestQueryClient = () => new QueryClient({
@@ -42,10 +45,10 @@ describe('AuthZModule', () => {
</IntlProvider>,
);
expect(screen.getByTestId('loading-page')).toBeInTheDocument();
expect(document.querySelector('.spinner-border')).toBeInTheDocument();
await waitFor(() => {
expect(screen.getByTestId('libraries-manager')).toBeInTheDocument();
expect(screen.getByText('Libraries Team Page')).toBeInTheDocument();
});
});
@@ -63,7 +66,7 @@ describe('AuthZModule', () => {
</IntlProvider>,
);
await waitFor(() => {
expect(screen.getByTestId('libraries-user-manager')).toBeInTheDocument();
expect(screen.getByText('Libraries User Page')).toBeInTheDocument();
});
});
});

View File

@@ -25,12 +25,12 @@ jest.mock('@src/authz-module/data/hooks', () => ({
jest.mock('./components/TeamTable', () => ({
__esModule: true,
default: () => <div data-testid="team-table">MockTeamTable</div>,
default: () => <div role="table" aria-label="Team Members Table">Team member list</div>,
}));
jest.mock('./components/AddNewTeamMemberModal', () => ({
__esModule: true,
AddNewTeamMemberTrigger: () => <div data-testid="add-team-member-trigger">MockAddNewTeamMemberTrigger</div>,
AddNewTeamMemberTrigger: () => <button type="button">Add Team Member</button>,
}));
jest.mock('../components/RoleCard', () => ({
@@ -40,10 +40,10 @@ jest.mock('../components/RoleCard', () => ({
description: string,
permissionsByResource: any[]
}) => (
<div data-testid="role-card">
<div>{title}</div>
<div>{description}</div>
<div>{permissionsByResource.length} permissions</div>
<div role="article" aria-label={`Role: ${title}`}>
<h3>{title}</h3>
<p>{description}</p>
<span>{permissionsByResource.length} permissions</span>
</div>
),
}));
@@ -108,10 +108,10 @@ describe('LibrariesTeamManager', () => {
expect(screen.getByText('lib-001')).toBeInTheDocument(); // subtitle
// TeamTable is rendered
expect(screen.getByTestId('team-table')).toBeInTheDocument();
expect(screen.getByRole('table', { name: 'Team Members Table' })).toBeInTheDocument();
// AddNewTeamMemberTrigger is rendered
expect(screen.getByTestId('add-team-member-trigger')).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Add Team Member' })).toBeInTheDocument();
});
it('renders role cards when "Roles" tab is selected', async () => {
@@ -123,10 +123,10 @@ describe('LibrariesTeamManager', () => {
const rolesTab = await screen.findByRole('tab', { name: /roles/i });
await user.click(rolesTab);
const roleCards = await screen.findAllByTestId('role-card');
const roleCards = await screen.findAllByRole('article', { name: /Role:/ });
const rolesScope = within(roleCards[0]);
expect(roleCards.length).toBe(1);
expect(rolesScope.getByText('Instructor')).toBeInTheDocument();
expect(rolesScope.getByRole('heading', { name: 'Instructor' })).toBeInTheDocument();
expect(screen.getByText(/Can manage content/i)).toBeInTheDocument();
expect(screen.getByText(/1 permissions/i)).toBeInTheDocument();
});

View File

@@ -21,26 +21,27 @@ jest.mock('./AddNewTeamMemberModal', () => {
isOpen, close, onSave, isLoading, formValues, handleChangeForm,
}) => (
isOpen ? (
<div data-testid="add-team-member-modal">
<button type="button" onClick={close} data-testid="close-modal">Close</button>
<button type="button" onClick={onSave} data-testid="save-modal">Save</button>
<div role="dialog" aria-label="Add New Team Member">
<button type="button" onClick={close} aria-label="Close modal">Close</button>
<button type="button" onClick={onSave} aria-label="Save team member">Save</button>
<textarea
name="users"
value={formValues?.users || ''}
onChange={handleChangeForm}
data-testid="users-input"
aria-label="Enter user emails or usernames"
placeholder="Enter emails or usernames"
/>
<select
name="role"
value={formValues?.role || ''}
onChange={handleChangeForm}
data-testid="role-select"
aria-label="Select role"
>
<option value="">Select role</option>
<option value="admin">Admin</option>
<option value="editor">Editor</option>
</select>
{isLoading && <div data-testid="loading-indicator">Loading...</div>}
{isLoading && <div role="status" aria-label="Adding team member loader">Loading...</div>}
</div>
) : null
);
@@ -75,7 +76,7 @@ describe('AddNewTeamMemberTrigger', () => {
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
await user.click(triggerButton);
expect(screen.getByTestId('add-team-member-modal')).toBeInTheDocument();
expect(screen.getByRole('dialog', { name: 'Add New Team Member' })).toBeInTheDocument();
});
it('closes modal when close button is clicked', async () => {
@@ -85,12 +86,12 @@ describe('AddNewTeamMemberTrigger', () => {
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
await user.click(triggerButton);
expect(screen.getByTestId('add-team-member-modal')).toBeInTheDocument();
expect(screen.getByRole('dialog', { name: 'Add New Team Member' })).toBeInTheDocument();
const closeButton = screen.getByTestId('close-modal');
const closeButton = screen.getByRole('button', { name: 'Close modal' });
await user.click(closeButton);
expect(screen.queryByTestId('add-team-member-modal')).not.toBeInTheDocument();
expect(screen.queryByRole('dialog', { name: 'Add New Team Member' })).not.toBeInTheDocument();
});
it('calls addTeamMember with correct data when save is clicked', async () => {
@@ -100,9 +101,9 @@ describe('AddNewTeamMemberTrigger', () => {
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
await user.click(triggerButton);
const usersInput = screen.getByTestId('users-input');
const roleSelect = screen.getByTestId('role-select');
const saveButton = screen.getByTestId('save-modal');
const usersInput = screen.getByRole('textbox', { name: 'Enter user emails or usernames' });
const roleSelect = screen.getByRole('combobox', { name: 'Select role' });
const saveButton = screen.getByRole('button', { name: 'Save team member' });
await user.type(usersInput, 'alice@example.com, bob@example.com');
await user.selectOptions(roleSelect, 'editor');
@@ -129,7 +130,7 @@ describe('AddNewTeamMemberTrigger', () => {
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
await user.click(triggerButton);
const saveButton = screen.getByTestId('save-modal');
const saveButton = screen.getByRole('button', { name: 'Save team member' });
await user.click(saveButton);
// Simulate successful response with no errors
@@ -143,7 +144,7 @@ describe('AddNewTeamMemberTrigger', () => {
});
await waitFor(() => {
expect(screen.queryByTestId('add-team-member-modal')).not.toBeInTheDocument();
expect(screen.queryByRole('dialog', { name: 'Add New Team Member' })).not.toBeInTheDocument();
});
expect(screen.getByText('2 team members added successfully.')).toBeInTheDocument();
@@ -156,7 +157,7 @@ describe('AddNewTeamMemberTrigger', () => {
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
await user.click(triggerButton);
const saveButton = screen.getByTestId('save-modal');
const saveButton = screen.getByRole('button', { name: 'Save team member' });
await user.click(saveButton);
// Simulate partial success response
@@ -176,7 +177,7 @@ describe('AddNewTeamMemberTrigger', () => {
});
// Modal should remain open when there are errors
expect(screen.getByTestId('add-team-member-modal')).toBeInTheDocument();
expect(screen.getByRole('dialog', { name: 'Add New Team Member' })).toBeInTheDocument();
});
it('displays only error toast when all additions fail', async () => {
@@ -186,7 +187,7 @@ describe('AddNewTeamMemberTrigger', () => {
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
await user.click(triggerButton);
const saveButton = screen.getByTestId('save-modal');
const saveButton = screen.getByRole('button', { name: 'Save team member' });
await user.click(saveButton);
// Simulate all failed response
@@ -204,7 +205,7 @@ describe('AddNewTeamMemberTrigger', () => {
});
// Modal should remain open when there are errors
expect(screen.getByTestId('add-team-member-modal')).toBeInTheDocument();
expect(screen.getByRole('dialog', { name: 'Add New Team Member' })).toBeInTheDocument();
});
it('resets form values after successful addition with no errors', async () => {
@@ -214,9 +215,9 @@ describe('AddNewTeamMemberTrigger', () => {
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
await user.click(triggerButton);
const usersInput = screen.getByTestId('users-input');
const roleSelect = screen.getByTestId('role-select');
const saveButton = screen.getByTestId('save-modal');
const usersInput = screen.getByRole('textbox', { name: 'Enter user emails or usernames' });
const roleSelect = screen.getByRole('combobox', { name: 'Select role' });
const saveButton = screen.getByRole('button', { name: 'Save team member' });
await user.type(usersInput, 'alice@example.com');
await user.selectOptions(roleSelect, 'editor');
@@ -232,8 +233,8 @@ describe('AddNewTeamMemberTrigger', () => {
// Open modal again to check if form is reset
await user.click(triggerButton);
const newUsersInput = screen.getByTestId('users-input');
const newRoleSelect = screen.getByTestId('role-select');
const newUsersInput = screen.getByRole('textbox', { name: 'Enter user emails or usernames' });
const newRoleSelect = screen.getByRole('combobox', { name: 'Select role' });
expect(newUsersInput).toHaveValue('');
expect(newRoleSelect).toHaveValue('');
@@ -246,7 +247,7 @@ describe('AddNewTeamMemberTrigger', () => {
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
await user.click(triggerButton);
const saveButton = screen.getByTestId('save-modal');
const saveButton = screen.getByRole('button', { name: 'Save team member' });
await user.click(saveButton);
// Simulate successful response
@@ -289,7 +290,7 @@ describe('AddNewTeamMemberTrigger', () => {
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
await user.click(triggerButton);
const saveButton = screen.getByTestId('save-modal');
const saveButton = screen.getByRole('button', { name: 'Save team member' });
await user.click(saveButton);
await waitFor(() => {
@@ -351,16 +352,16 @@ describe('AddNewTeamMemberTrigger', () => {
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
await user.click(triggerButton);
const userInput = screen.getByTestId('users-input');
const roleSelect = screen.getByTestId('role-select');
const userInput = screen.getByRole('textbox', { name: 'Enter user emails or usernames' });
const roleSelect = screen.getByRole('combobox', { name: 'Select role' });
await user.type(userInput, 'alice@example.com');
await user.selectOptions(roleSelect, 'editor');
const saveButton = screen.getByTestId('save-modal');
const saveButton = screen.getByRole('button', { name: 'Save team member' });
await user.click(saveButton);
// should now reflect isPending = true
const loadingIndicator = await screen.findByTestId('loading-indicator');
const loadingIndicator = await screen.findByRole('status', { name: 'Adding team member loader' });
expect(loadingIndicator).toBeInTheDocument();
expect(loadingIndicator).toHaveTextContent('Loading...');

View File

@@ -26,9 +26,9 @@ jest.mock('./AssignNewRoleModal', () => {
selectedRole,
handleChangeSelectedRole,
}: any) => (isOpen ? (
<div data-testid="assign-new-role-modal">
<div role="dialog" aria-label="Assign New Role">
<h2>Add New Role</h2>
<select data-testid="role-select" value={selectedRole} onChange={handleChangeSelectedRole}>
<select value={selectedRole} onChange={handleChangeSelectedRole} aria-label="Select role">
<option value="">Select a role</option>
{roleOptions.map((role: any) => (
<option key={role.role} value={role.role}>
@@ -36,10 +36,10 @@ jest.mock('./AssignNewRoleModal', () => {
</option>
))}
</select>
<button type="button" onClick={onSave} disabled={isLoading} data-testid="save-button">
<button type="button" onClick={onSave} disabled={isLoading} aria-label="Save role assignment">
{isLoading ? 'Saving...' : 'Save'}
</button>
<button type="button" onClick={close} data-testid="cancel-button">
<button type="button" onClick={close} aria-label="Cancel role assignment">
Cancel
</button>
</div>
@@ -106,7 +106,7 @@ describe('AssignNewRoleTrigger', () => {
it('does not show modal initially', () => {
renderComponent();
expect(screen.queryByTestId('assign-new-role-modal')).not.toBeInTheDocument();
expect(screen.queryByRole('dialog', { name: 'Assign New Role' })).not.toBeInTheDocument();
});
it('does not show toast initially', () => {
@@ -124,7 +124,7 @@ describe('AssignNewRoleTrigger', () => {
const triggerButton = screen.getByRole('button', { name: /add new role/i });
await user.click(triggerButton);
expect(screen.getByTestId('assign-new-role-modal')).toBeInTheDocument();
expect(screen.getByRole('dialog', { name: 'Assign New Role' })).toBeInTheDocument();
expect(screen.getByRole('heading', { name: /add new role/i })).toBeInTheDocument();
});
@@ -134,11 +134,11 @@ describe('AssignNewRoleTrigger', () => {
// Open modal
await user.click(screen.getByRole('button', { name: /add new role/i }));
expect(screen.getByTestId('assign-new-role-modal')).toBeInTheDocument();
expect(screen.getByRole('dialog', { name: 'Assign New Role' })).toBeInTheDocument();
// Close modal
await user.click(screen.getByTestId('cancel-button'));
expect(screen.queryByTestId('assign-new-role-modal')).not.toBeInTheDocument();
await user.click(screen.getByRole('button', { name: 'Cancel role assignment' }));
expect(screen.queryByRole('dialog', { name: 'Assign New Role' })).not.toBeInTheDocument();
});
});
@@ -149,7 +149,7 @@ describe('AssignNewRoleTrigger', () => {
await user.click(screen.getByRole('button', { name: /add new role/i }));
const roleSelect = screen.getByTestId('role-select');
const roleSelect = screen.getByRole('combobox', { name: 'Select role' });
await user.selectOptions(roleSelect, 'admin');
expect(roleSelect).toHaveValue('admin');
@@ -163,11 +163,11 @@ describe('AssignNewRoleTrigger', () => {
await user.click(screen.getByRole('button', { name: /add new role/i }));
// Select a role
const roleSelect = screen.getByTestId('role-select');
const roleSelect = screen.getByRole('combobox', { name: 'Select role' });
await user.selectOptions(roleSelect, choosenRole);
// Click save
await user.click(screen.getByTestId('save-button'));
await user.click(screen.getByRole('button', { name: 'Save role assignment' }));
expect(mockMutate).toHaveBeenCalledWith(
{
@@ -191,15 +191,15 @@ describe('AssignNewRoleTrigger', () => {
await user.click(screen.getByRole('button', { name: /add new role/i }));
// Select a role that user already has
const roleSelect = screen.getByTestId('role-select');
const roleSelect = screen.getByRole('combobox', { name: 'Select role' });
await user.selectOptions(roleSelect, choosenRole);
await user.click(screen.getByTestId('save-button'));
await user.click(screen.getByRole('button', { name: 'Save role assignment' }));
// Should not call assignTeamMembersRole
expect(mockMutate).not.toHaveBeenCalled();
// Modal should be closed
expect(screen.queryByTestId('assign-new-role-modal')).not.toBeInTheDocument();
expect(screen.queryByRole('dialog', { name: 'Assign New Role' })).not.toBeInTheDocument();
});
});
@@ -215,7 +215,7 @@ describe('AssignNewRoleTrigger', () => {
await user.click(screen.getByRole('button', { name: /add new role/i }));
expect(screen.getByTestId('save-button')).toBeDisabled();
expect(screen.getByRole('button', { name: 'Save role assignment' })).toBeDisabled();
expect(screen.getByText('Saving...')).toBeInTheDocument();
});
});
@@ -227,10 +227,10 @@ describe('AssignNewRoleTrigger', () => {
await user.click(screen.getByRole('button', { name: /add new role/i }));
const roleSelect = screen.getByTestId('role-select');
const roleSelect = screen.getByRole('combobox', { name: 'Select role' });
await user.selectOptions(roleSelect, 'admin');
await user.click(screen.getByTestId('save-button'));
await user.click(screen.getByRole('button', { name: 'Save role assignment' }));
// Simulate successful API call
const onSuccessCallback = mockMutate.mock.calls[0][1].onSuccess;
@@ -247,22 +247,22 @@ describe('AssignNewRoleTrigger', () => {
await user.click(screen.getByRole('button', { name: /add new role/i }));
const roleSelect = screen.getByTestId('role-select');
const roleSelect = screen.getByRole('combobox', { name: 'Select role' });
await user.selectOptions(roleSelect, 'admin');
await user.click(screen.getByTestId('save-button'));
await user.click(screen.getByRole('button', { name: 'Save role assignment' }));
// Simulate successful API call
const onSuccessCallback = mockMutate.mock.calls[0][1].onSuccess;
onSuccessCallback({ errors: [] });
await waitFor(() => {
expect(screen.queryByTestId('assign-new-role-modal')).not.toBeInTheDocument();
expect(screen.queryByRole('dialog', { name: 'Assign New Role' })).not.toBeInTheDocument();
});
// Open modal again to check if role is reset
await user.click(screen.getByRole('button', { name: /add new role/i }));
expect(screen.getByTestId('role-select')).toHaveValue('');
expect(screen.getByRole('combobox', { name: 'Select role' })).toHaveValue('');
});
});
@@ -273,15 +273,15 @@ describe('AssignNewRoleTrigger', () => {
renderComponent();
await user.click(screen.getByRole('button', { name: /add new role/i }));
await user.selectOptions(screen.getByTestId('role-select'), 'admin');
await user.click(screen.getByTestId('save-button'));
await user.selectOptions(screen.getByRole('combobox', { name: 'Select role' }), 'admin');
await user.click(screen.getByRole('button', { name: 'Save role assignment' }));
const { onSuccess } = mockMutate.mock.calls[0][1];
onSuccess({ errors: [{ error: 'role_assignment_error' }] });
await waitFor(() => {
expect(screen.getByText(/Something went wrong/i)).toBeInTheDocument();
expect(screen.getByTestId('role-select')).toHaveValue(''); // role reset
expect(screen.getByRole('combobox', { name: 'Select role' })).toHaveValue(''); // role reset
});
});
@@ -306,8 +306,8 @@ describe('AssignNewRoleTrigger', () => {
// Open modal and select a role
await user.click(screen.getByRole('button', { name: /add new role/i }));
await user.selectOptions(screen.getByTestId('role-select'), 'admin');
await user.click(screen.getByTestId('save-button'));
await user.selectOptions(screen.getByRole('combobox', { name: 'Select role' }), 'admin');
await user.click(screen.getByRole('button', { name: 'Save role assignment' }));
// Wait for the error toast to appear with a retry button
await waitFor(() => {

View File

@@ -7,10 +7,8 @@ import userEvent from '@testing-library/user-event';
import TableControlBar from './TableControlBar';
jest.mock('./MultipleChoiceFilter', () => {
// eslint-disable-next-line react/prop-types
const MockMultipleChoiceFilter = (props) => (
// eslint-disable-next-line react/prop-types
<div data-testid="multiple-choice-filter" data-column-id={props.id || props.accessor}>
const MockMultipleChoiceFilter = (props: { id?: string; accessor?: string }) => (
<div role="group" aria-label={`Filter by ${props.id || props.accessor}`}>
Multiple Choice Filter
</div>
);
@@ -20,7 +18,7 @@ jest.mock('./MultipleChoiceFilter', () => {
jest.mock('./SortDropdown', () => {
const MockSortDropdown = () => (
<div data-testid="sort-dropdown">
<div role="group" aria-label="Sort options">
Sort Dropdown
</div>
);
@@ -31,7 +29,7 @@ jest.mock('./SortDropdown', () => {
jest.mock('./SearchFilter', () => {
// eslint-disable-next-line react/prop-types
const MockSearchFilter = (props) => (
<div data-testid="search-filter">
<div role="search" aria-label="Search filter">
<input
// eslint-disable-next-line react/prop-types
placeholder={props.placeholder}
@@ -39,7 +37,7 @@ jest.mock('./SearchFilter', () => {
value={props.filterValue || ''}
// eslint-disable-next-line react/prop-types
onChange={(e) => props.setFilter(e.target.value)}
data-testid="search-input"
aria-label="Search input"
/>
</div>
);
@@ -74,7 +72,7 @@ describe('TableControlBar', () => {
it('should render basic structure with SortDropdown and RowStatus', () => {
renderWithContext();
expect(screen.getByTestId('sort-dropdown')).toBeInTheDocument();
expect(screen.getByRole('group', { name: 'Sort options' })).toBeInTheDocument();
const container = screen.getByText('Sort Dropdown').closest('.pgn__data-table-status-bar');
expect(container).toHaveClass('pgn__data-table-status-bar', 'mb-3', 'flex-wrap');
});
@@ -131,9 +129,9 @@ describe('TableControlBar', () => {
renderWithContext(contextWithCheckboxColumn);
const multipleChoiceFilter = screen.getByTestId('multiple-choice-filter');
const multipleChoiceFilter = screen.getByRole('group', { name: 'Filter by roles' });
expect(multipleChoiceFilter).toBeInTheDocument();
expect(multipleChoiceFilter).toHaveAttribute('data-column-id', 'roles');
expect(screen.getByText('Multiple Choice Filter')).toBeInTheDocument();
});
it('should render SearchFilter for columns with TextFilter', () => {
@@ -154,8 +152,8 @@ describe('TableControlBar', () => {
renderWithContext(contextWithTextColumn);
expect(screen.getByTestId('search-filter')).toBeInTheDocument();
expect(screen.getByTestId('search-input')).toBeInTheDocument();
expect(screen.getByRole('search', { name: 'Search filter' })).toBeInTheDocument();
expect(screen.getByRole('textbox', { name: 'Search input' })).toBeInTheDocument();
});
it('should not render any filter for unsupported Filter types', () => {
@@ -176,8 +174,8 @@ describe('TableControlBar', () => {
renderWithContext(contextWithCustomFilter);
// Only SortDropdown should be present, no filter components
expect(screen.getByTestId('sort-dropdown')).toBeInTheDocument();
expect(screen.queryByTestId('search-filter')).not.toBeInTheDocument();
expect(screen.queryByTestId('multiple-choice-filter')).not.toBeInTheDocument();
expect(screen.getByRole('group', { name: 'Sort options' })).toBeInTheDocument();
expect(screen.queryByRole('search', { name: 'Search filter' })).not.toBeInTheDocument();
expect(screen.queryByRole('group', { name: /Filter by/ })).not.toBeInTheDocument();
});
});

View File

@@ -49,14 +49,12 @@ const TestComponent = () => {
const context = useLibraryAuthZ();
return (
<div>
<div data-testid="username">{context.username}</div>
<div data-testid="libraryId">{context.libraryId}</div>
<div data-testid="canManageTeam">{context.canManageTeam ? 'true' : 'false'}</div>
<div data-testid="roles">{Array.isArray(context.roles) ? context.roles.length : 'undefined'}</div>
<div data-testid="permissions">
{Array.isArray(context.permissions) ? context.permissions.length : 'undefined'}
</div>
<div data-testid="resources">{Array.isArray(context.resources) ? context.resources.length : 'undefined'}</div>
<div>Username: {context.username}</div>
<div>Library ID: {context.libraryId}</div>
<div>Can manage team: {context.canManageTeam ? 'Yes' : 'No'}</div>
<div>Roles count: {Array.isArray(context.roles) ? context.roles.length : 'undefined'}</div>
<div>Permissions count: {Array.isArray(context.permissions) ? context.permissions.length : 'undefined'}</div>
<div>Resources count: {Array.isArray(context.resources) ? context.resources.length : 'undefined'}</div>
</div>
);
};
@@ -109,12 +107,12 @@ describe('LibraryAuthZProvider', () => {
</LibraryAuthZProvider>,
);
expect(screen.getByTestId('username')).toHaveTextContent('testuser');
expect(screen.getByTestId('libraryId')).toHaveTextContent('lib123');
expect(screen.getByTestId('canManageTeam')).toHaveTextContent('true');
expect(Number(screen.getByTestId('roles').textContent)).not.toBeNaN();
expect(Number(screen.getByTestId('permissions').textContent)).not.toBeNaN();
expect(Number(screen.getByTestId('resources').textContent)).not.toBeNaN();
expect(screen.getByText(/Username: testuser/)).toBeInTheDocument();
expect(screen.getByText(/Library ID: lib123/)).toBeInTheDocument();
expect(screen.getByText(/Can manage team: Yes/)).toBeInTheDocument();
expect(screen.getByText(/Roles count: \d+/)).toBeInTheDocument();
expect(screen.getByText(/Permissions count: \d+/)).toBeInTheDocument();
expect(screen.getByText(/Resources count: \d+/)).toBeInTheDocument();
});
it('throws error when user lacks both view and manage permissions', () => {
@@ -148,7 +146,7 @@ describe('LibraryAuthZProvider', () => {
</LibraryAuthZProvider>,
);
expect(screen.getByTestId('canManageTeam')).toHaveTextContent('false');
expect(screen.getByText(/Can manage team: No/)).toBeInTheDocument();
});
it('throws error when libraryId is missing', () => {

View File

@@ -1,7 +1,7 @@
import { Spinner, Container } from '@openedx/paragon';
const LoadingPage = () => (
<Container className="d-flex vh-100" data-testid="loading-page">
<Container className="d-flex vh-100">
<Spinner
variant="primary"
animation="border"