Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/authz-module/components/AuthZTitle.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand All @@ -69,22 +69,22 @@ 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 },
];

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,
Expand All @@ -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();
});
});
16 changes: 8 additions & 8 deletions src/authz-module/components/RoleCard/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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" />,
},
}));

Expand Down Expand Up @@ -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();
Expand All @@ -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', () => {
Expand All @@ -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();
});

Expand Down
15 changes: 9 additions & 6 deletions src/authz-module/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down Expand Up @@ -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();
});
});

Expand All @@ -63,7 +66,7 @@ describe('AuthZModule', () => {
</IntlProvider>,
);
await waitFor(() => {
expect(screen.getByTestId('libraries-user-manager')).toBeInTheDocument();
expect(screen.getByText('Libraries User Page')).toBeInTheDocument();
});
});
});
20 changes: 10 additions & 10 deletions src/authz-module/libraries-manager/LibrariesTeamManager.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => ({
Expand All @@ -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>
),
}));
Expand Down Expand Up @@ -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 () => {
Expand All @@ -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();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
Expand Down Expand Up @@ -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 () => {
Expand All @@ -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 () => {
Expand All @@ -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');
Expand All @@ -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
Expand All @@ -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();
Expand All @@ -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
Expand All @@ -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 () => {
Expand All @@ -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
Expand All @@ -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 () => {
Expand All @@ -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');
Expand All @@ -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('');
Expand All @@ -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
Expand Down Expand Up @@ -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(() => {
Expand Down Expand Up @@ -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...');

Expand Down
Loading