Skip to content

Commit bb49c24

Browse files
Merge branch 'master' of https://github.com/openedx/frontend-app-admin-console into updating-permissions-namespaces
2 parents d561791 + 0572a73 commit bb49c24

10 files changed

Lines changed: 8514 additions & 13393 deletions

File tree

package-lock.json

Lines changed: 8395 additions & 13274 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/authz-module/components/AuthZTitle.test.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ describe('AuthZTitle', () => {
4444
});
4545

4646
it('renders page subtitle as ReactNode', () => {
47-
const subtitleNode = <div data-testid="custom-subtitle">Custom Subtitle</div>;
47+
const subtitleNode = <div>Custom Subtitle</div>;
4848
render(<AuthZTitle {...defaultProps} pageSubtitle={subtitleNode} />);
49-
expect(screen.getByTestId('custom-subtitle')).toBeInTheDocument();
49+
expect(screen.getByText('Custom Subtitle')).toBeInTheDocument();
5050
});
5151

5252
it('renders action buttons and triggers onClick', () => {
@@ -69,22 +69,22 @@ describe('AuthZTitle', () => {
6969
});
7070

7171
it('renders action buttons with icons', () => {
72-
const mockIcon = () => <span data-testid="mock-icon">Icon</span>;
72+
const mockIcon = () => <span role="img" aria-label="save icon">Icon</span>;
7373
const onClick = jest.fn();
7474
const actions = [
7575
{ label: 'Save', icon: mockIcon, onClick },
7676
];
7777

7878
render(<AuthZTitle {...defaultProps} actions={actions} />);
7979

80-
const button = screen.getByRole('button', { name: 'Icon Save' });
80+
const button = screen.getByRole('button', { name: 'save icon Save' });
8181
expect(button).toBeInTheDocument();
82-
expect(screen.getByTestId('mock-icon')).toBeInTheDocument();
82+
expect(screen.getByRole('img', { name: 'save icon' })).toBeInTheDocument();
8383
});
8484

8585
it('renders ReactNode actions alongside button actions', () => {
8686
const onClick = jest.fn();
87-
const customAction = <div data-testid="custom-action">Custom Action</div>;
87+
const customAction = <div role="region" aria-label="custom action area">Custom Action</div>;
8888
const actions = [
8989
{ label: 'Save', onClick },
9090
customAction,
@@ -93,6 +93,6 @@ describe('AuthZTitle', () => {
9393
render(<AuthZTitle {...defaultProps} actions={actions} />);
9494

9595
expect(screen.getByRole('button', { name: 'Save' })).toBeInTheDocument();
96-
expect(screen.getByTestId('custom-action')).toBeInTheDocument();
96+
expect(screen.getByRole('region', { name: 'custom action area' })).toBeInTheDocument();
9797
});
9898
});

src/authz-module/components/RoleCard/index.test.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ import userEvent from '@testing-library/user-event';
44
import RoleCard from '.';
55

66
jest.mock('@openedx/paragon/icons', () => ({
7-
Delete: () => <svg data-testid="delete-icon" />,
8-
Person: () => <svg data-testid="person-icon" />,
7+
Delete: () => <svg role="img" aria-label="delete icon" />,
8+
Person: () => <svg role="img" aria-label="person icon" />,
99
}));
1010

1111
jest.mock('./constants', () => ({
1212
actionsDictionary: {
13-
view: () => <svg data-testid="view-icon" />,
14-
manage: () => <svg data-testid="manage-icon" />,
13+
view: () => <svg role="img" aria-label="view action icon" />,
14+
manage: () => <svg role="img" aria-label="manage action icon" />,
1515
},
1616
}));
1717

@@ -47,7 +47,7 @@ describe('RoleCard', () => {
4747

4848
// User counter with icon
4949
expect(screen.getByText('2')).toBeInTheDocument();
50-
expect(screen.getByTestId('person-icon')).toBeInTheDocument();
50+
expect(screen.getByRole('img', { name: 'person icon' })).toBeInTheDocument();
5151

5252
// Subtitle (object name)
5353
expect(screen.getByText('Test Library')).toBeInTheDocument();
@@ -71,8 +71,8 @@ describe('RoleCard', () => {
7171
expect(screen.getByText('Manage')).toBeInTheDocument();
7272

7373
// Action icons
74-
expect(screen.getByTestId('view-icon')).toBeInTheDocument();
75-
expect(screen.getByTestId('manage-icon')).toBeInTheDocument();
74+
expect(screen.getByRole('img', { name: 'view action icon' })).toBeInTheDocument();
75+
expect(screen.getByRole('img', { name: 'manage action icon' })).toBeInTheDocument();
7676
});
7777

7878
it('does not show delete button when handleDelete is not passed', () => {
@@ -82,7 +82,7 @@ describe('RoleCard', () => {
8282

8383
it('handles no userCounter gracefully', () => {
8484
renderWrapper(<RoleCard {...defaultProps} userCounter={null} />);
85-
expect(screen.queryByTestId('person-icon')).not.toBeInTheDocument();
85+
expect(screen.queryByRole('img', { name: 'person icon' })).not.toBeInTheDocument();
8686
expect(screen.queryByText('2')).not.toBeInTheDocument();
8787
});
8888

src/authz-module/index.test.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@ import AuthZModule from './index';
88

99
jest.mock('./libraries-manager', () => ({
1010
// eslint-disable-next-line no-promise-executor-return
11-
LibrariesLayout: lazy(() => new Promise<{ default: ComponentType<any> }>(resolve => setTimeout(() => resolve({ default: () => <div data-testid="layout"><Outlet /></div> }), 100))),
12-
LibrariesTeamManager: () => <div data-testid="libraries-manager">Libraries Team Page</div>,
13-
LibrariesUserManager: () => <div data-testid="libraries-user-manager">Libraries User Page</div>,
11+
LibrariesLayout: lazy(() => new Promise<{ default: ComponentType<any> }>(resolve => setTimeout(
12+
() => resolve({ default: () => <div><Outlet /></div> }),
13+
100,
14+
))),
15+
LibrariesTeamManager: () => <div>Libraries Team Page</div>,
16+
LibrariesUserManager: () => <div>Libraries User Page</div>,
1417
}));
1518

1619
const createTestQueryClient = () => new QueryClient({
@@ -42,10 +45,10 @@ describe('AuthZModule', () => {
4245
</IntlProvider>,
4346
);
4447

45-
expect(screen.getByTestId('loading-page')).toBeInTheDocument();
48+
expect(document.querySelector('.spinner-border')).toBeInTheDocument();
4649

4750
await waitFor(() => {
48-
expect(screen.getByTestId('libraries-manager')).toBeInTheDocument();
51+
expect(screen.getByText('Libraries Team Page')).toBeInTheDocument();
4952
});
5053
});
5154

@@ -63,7 +66,7 @@ describe('AuthZModule', () => {
6366
</IntlProvider>,
6467
);
6568
await waitFor(() => {
66-
expect(screen.getByTestId('libraries-user-manager')).toBeInTheDocument();
69+
expect(screen.getByText('Libraries User Page')).toBeInTheDocument();
6770
});
6871
});
6972
});

src/authz-module/libraries-manager/LibrariesTeamManager.test.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ jest.mock('@src/authz-module/data/hooks', () => ({
2525

2626
jest.mock('./components/TeamTable', () => ({
2727
__esModule: true,
28-
default: () => <div data-testid="team-table">MockTeamTable</div>,
28+
default: () => <div role="table" aria-label="Team Members Table">Team member list</div>,
2929
}));
3030

3131
jest.mock('./components/AddNewTeamMemberModal', () => ({
3232
__esModule: true,
33-
AddNewTeamMemberTrigger: () => <div data-testid="add-team-member-trigger">MockAddNewTeamMemberTrigger</div>,
33+
AddNewTeamMemberTrigger: () => <button type="button">Add Team Member</button>,
3434
}));
3535

3636
jest.mock('../components/RoleCard', () => ({
@@ -40,10 +40,10 @@ jest.mock('../components/RoleCard', () => ({
4040
description: string,
4141
permissionsByResource: any[]
4242
}) => (
43-
<div data-testid="role-card">
44-
<div>{title}</div>
45-
<div>{description}</div>
46-
<div>{permissionsByResource.length} permissions</div>
43+
<div role="article" aria-label={`Role: ${title}`}>
44+
<h3>{title}</h3>
45+
<p>{description}</p>
46+
<span>{permissionsByResource.length} permissions</span>
4747
</div>
4848
),
4949
}));
@@ -108,10 +108,10 @@ describe('LibrariesTeamManager', () => {
108108
expect(screen.getByText('lib-001')).toBeInTheDocument(); // subtitle
109109

110110
// TeamTable is rendered
111-
expect(screen.getByTestId('team-table')).toBeInTheDocument();
111+
expect(screen.getByRole('table', { name: 'Team Members Table' })).toBeInTheDocument();
112112

113113
// AddNewTeamMemberTrigger is rendered
114-
expect(screen.getByTestId('add-team-member-trigger')).toBeInTheDocument();
114+
expect(screen.getByRole('button', { name: 'Add Team Member' })).toBeInTheDocument();
115115
});
116116

117117
it('renders role cards when "Roles" tab is selected', async () => {
@@ -123,10 +123,10 @@ describe('LibrariesTeamManager', () => {
123123
const rolesTab = await screen.findByRole('tab', { name: /roles/i });
124124
await user.click(rolesTab);
125125

126-
const roleCards = await screen.findAllByTestId('role-card');
126+
const roleCards = await screen.findAllByRole('article', { name: /Role:/ });
127127
const rolesScope = within(roleCards[0]);
128128
expect(roleCards.length).toBe(1);
129-
expect(rolesScope.getByText('Instructor')).toBeInTheDocument();
129+
expect(rolesScope.getByRole('heading', { name: 'Instructor' })).toBeInTheDocument();
130130
expect(screen.getByText(/Can manage content/i)).toBeInTheDocument();
131131
expect(screen.getByText(/1 permissions/i)).toBeInTheDocument();
132132
});

src/authz-module/libraries-manager/components/AddNewTeamMemberModal/AddNewTeamMemberTrigger.test.tsx

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,27 @@ jest.mock('./AddNewTeamMemberModal', () => {
2121
isOpen, close, onSave, isLoading, formValues, handleChangeForm,
2222
}) => (
2323
isOpen ? (
24-
<div data-testid="add-team-member-modal">
25-
<button type="button" onClick={close} data-testid="close-modal">Close</button>
26-
<button type="button" onClick={onSave} data-testid="save-modal">Save</button>
24+
<div role="dialog" aria-label="Add New Team Member">
25+
<button type="button" onClick={close} aria-label="Close modal">Close</button>
26+
<button type="button" onClick={onSave} aria-label="Save team member">Save</button>
2727
<textarea
2828
name="users"
2929
value={formValues?.users || ''}
3030
onChange={handleChangeForm}
31-
data-testid="users-input"
31+
aria-label="Enter user emails or usernames"
32+
placeholder="Enter emails or usernames"
3233
/>
3334
<select
3435
name="role"
3536
value={formValues?.role || ''}
3637
onChange={handleChangeForm}
37-
data-testid="role-select"
38+
aria-label="Select role"
3839
>
3940
<option value="">Select role</option>
4041
<option value="admin">Admin</option>
4142
<option value="editor">Editor</option>
4243
</select>
43-
{isLoading && <div data-testid="loading-indicator">Loading...</div>}
44+
{isLoading && <div role="status" aria-label="Adding team member loader">Loading...</div>}
4445
</div>
4546
) : null
4647
);
@@ -75,7 +76,7 @@ describe('AddNewTeamMemberTrigger', () => {
7576
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
7677
await user.click(triggerButton);
7778

78-
expect(screen.getByTestId('add-team-member-modal')).toBeInTheDocument();
79+
expect(screen.getByRole('dialog', { name: 'Add New Team Member' })).toBeInTheDocument();
7980
});
8081

8182
it('closes modal when close button is clicked', async () => {
@@ -85,12 +86,12 @@ describe('AddNewTeamMemberTrigger', () => {
8586
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
8687
await user.click(triggerButton);
8788

88-
expect(screen.getByTestId('add-team-member-modal')).toBeInTheDocument();
89+
expect(screen.getByRole('dialog', { name: 'Add New Team Member' })).toBeInTheDocument();
8990

90-
const closeButton = screen.getByTestId('close-modal');
91+
const closeButton = screen.getByRole('button', { name: 'Close modal' });
9192
await user.click(closeButton);
9293

93-
expect(screen.queryByTestId('add-team-member-modal')).not.toBeInTheDocument();
94+
expect(screen.queryByRole('dialog', { name: 'Add New Team Member' })).not.toBeInTheDocument();
9495
});
9596

9697
it('calls addTeamMember with correct data when save is clicked', async () => {
@@ -100,9 +101,9 @@ describe('AddNewTeamMemberTrigger', () => {
100101
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
101102
await user.click(triggerButton);
102103

103-
const usersInput = screen.getByTestId('users-input');
104-
const roleSelect = screen.getByTestId('role-select');
105-
const saveButton = screen.getByTestId('save-modal');
104+
const usersInput = screen.getByRole('textbox', { name: 'Enter user emails or usernames' });
105+
const roleSelect = screen.getByRole('combobox', { name: 'Select role' });
106+
const saveButton = screen.getByRole('button', { name: 'Save team member' });
106107

107108
await user.type(usersInput, '[email protected], [email protected]');
108109
await user.selectOptions(roleSelect, 'editor');
@@ -129,7 +130,7 @@ describe('AddNewTeamMemberTrigger', () => {
129130
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
130131
await user.click(triggerButton);
131132

132-
const saveButton = screen.getByTestId('save-modal');
133+
const saveButton = screen.getByRole('button', { name: 'Save team member' });
133134
await user.click(saveButton);
134135

135136
// Simulate successful response with no errors
@@ -143,7 +144,7 @@ describe('AddNewTeamMemberTrigger', () => {
143144
});
144145

145146
await waitFor(() => {
146-
expect(screen.queryByTestId('add-team-member-modal')).not.toBeInTheDocument();
147+
expect(screen.queryByRole('dialog', { name: 'Add New Team Member' })).not.toBeInTheDocument();
147148
});
148149

149150
expect(screen.getByText('2 team members added successfully.')).toBeInTheDocument();
@@ -156,7 +157,7 @@ describe('AddNewTeamMemberTrigger', () => {
156157
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
157158
await user.click(triggerButton);
158159

159-
const saveButton = screen.getByTestId('save-modal');
160+
const saveButton = screen.getByRole('button', { name: 'Save team member' });
160161
await user.click(saveButton);
161162

162163
// Simulate partial success response
@@ -176,7 +177,7 @@ describe('AddNewTeamMemberTrigger', () => {
176177
});
177178

178179
// Modal should remain open when there are errors
179-
expect(screen.getByTestId('add-team-member-modal')).toBeInTheDocument();
180+
expect(screen.getByRole('dialog', { name: 'Add New Team Member' })).toBeInTheDocument();
180181
});
181182

182183
it('displays only error toast when all additions fail', async () => {
@@ -186,7 +187,7 @@ describe('AddNewTeamMemberTrigger', () => {
186187
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
187188
await user.click(triggerButton);
188189

189-
const saveButton = screen.getByTestId('save-modal');
190+
const saveButton = screen.getByRole('button', { name: 'Save team member' });
190191
await user.click(saveButton);
191192

192193
// Simulate all failed response
@@ -204,7 +205,7 @@ describe('AddNewTeamMemberTrigger', () => {
204205
});
205206

206207
// Modal should remain open when there are errors
207-
expect(screen.getByTestId('add-team-member-modal')).toBeInTheDocument();
208+
expect(screen.getByRole('dialog', { name: 'Add New Team Member' })).toBeInTheDocument();
208209
});
209210

210211
it('resets form values after successful addition with no errors', async () => {
@@ -214,9 +215,9 @@ describe('AddNewTeamMemberTrigger', () => {
214215
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
215216
await user.click(triggerButton);
216217

217-
const usersInput = screen.getByTestId('users-input');
218-
const roleSelect = screen.getByTestId('role-select');
219-
const saveButton = screen.getByTestId('save-modal');
218+
const usersInput = screen.getByRole('textbox', { name: 'Enter user emails or usernames' });
219+
const roleSelect = screen.getByRole('combobox', { name: 'Select role' });
220+
const saveButton = screen.getByRole('button', { name: 'Save team member' });
220221

221222
await user.type(usersInput, '[email protected]');
222223
await user.selectOptions(roleSelect, 'editor');
@@ -232,8 +233,8 @@ describe('AddNewTeamMemberTrigger', () => {
232233
// Open modal again to check if form is reset
233234
await user.click(triggerButton);
234235

235-
const newUsersInput = screen.getByTestId('users-input');
236-
const newRoleSelect = screen.getByTestId('role-select');
236+
const newUsersInput = screen.getByRole('textbox', { name: 'Enter user emails or usernames' });
237+
const newRoleSelect = screen.getByRole('combobox', { name: 'Select role' });
237238

238239
expect(newUsersInput).toHaveValue('');
239240
expect(newRoleSelect).toHaveValue('');
@@ -246,7 +247,7 @@ describe('AddNewTeamMemberTrigger', () => {
246247
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
247248
await user.click(triggerButton);
248249

249-
const saveButton = screen.getByTestId('save-modal');
250+
const saveButton = screen.getByRole('button', { name: 'Save team member' });
250251
await user.click(saveButton);
251252

252253
// Simulate successful response
@@ -289,7 +290,7 @@ describe('AddNewTeamMemberTrigger', () => {
289290
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
290291
await user.click(triggerButton);
291292

292-
const saveButton = screen.getByTestId('save-modal');
293+
const saveButton = screen.getByRole('button', { name: 'Save team member' });
293294
await user.click(saveButton);
294295

295296
await waitFor(() => {
@@ -351,16 +352,16 @@ describe('AddNewTeamMemberTrigger', () => {
351352
const triggerButton = screen.getByRole('button', { name: /add new team member/i });
352353
await user.click(triggerButton);
353354

354-
const userInput = screen.getByTestId('users-input');
355-
const roleSelect = screen.getByTestId('role-select');
355+
const userInput = screen.getByRole('textbox', { name: 'Enter user emails or usernames' });
356+
const roleSelect = screen.getByRole('combobox', { name: 'Select role' });
356357
await user.type(userInput, '[email protected]');
357358
await user.selectOptions(roleSelect, 'editor');
358359

359-
const saveButton = screen.getByTestId('save-modal');
360+
const saveButton = screen.getByRole('button', { name: 'Save team member' });
360361
await user.click(saveButton);
361362

362363
// should now reflect isPending = true
363-
const loadingIndicator = await screen.findByTestId('loading-indicator');
364+
const loadingIndicator = await screen.findByRole('status', { name: 'Adding team member loader' });
364365
expect(loadingIndicator).toBeInTheDocument();
365366
expect(loadingIndicator).toHaveTextContent('Loading...');
366367

0 commit comments

Comments
 (0)