@@ -7,7 +7,7 @@ import { MantineProvider } from '@mantine/core';
7
7
import { notifications } from '@mantine/notifications' ;
8
8
import userEvent from '@testing-library/user-event' ;
9
9
10
- describe ( 'Exec Group Management Panel read tests' , ( ) => {
10
+ describe ( 'Exec Group Management Panel tests' , ( ) => {
11
11
const renderComponent = async (
12
12
fetchMembers : ( ) => Promise < any [ ] > ,
13
13
updateMembers : ( ) => Promise < any >
@@ -33,18 +33,18 @@ describe('Exec Group Management Panel read tests', () => {
33
33
34
34
await renderComponent ( fetchMembers , updateMembers ) ;
35
35
36
- expect ( screen . getByText ( 'Current Members ' ) ) . toBeInTheDocument ( ) ;
37
- expect ( screen . queryByText ( / .* @ i l l i n o i s \. e d u / ) ) . not . toBeInTheDocument ( ) ;
36
+ expect ( screen . getByText ( 'Exec Council Group Management ' ) ) . toBeInTheDocument ( ) ;
37
+ expect ( screen . queryByText ( / .* @ . * / ) ) . not . toBeInTheDocument ( ) ;
38
38
} ) ;
39
39
40
40
it ( 'renders with a single member' , async ( ) => {
41
41
const fetchMembers = async ( ) => [ { name : 'Doe, John' , email : 'jdoe@illinois.edu' } ] ;
42
- const updateMembers = async ( ) => ( {
43
- success : [ { email : 'jdoe@illinois.edu' } ] ,
44
- } ) ;
42
+ const updateMembers = async ( ) => ( { success : [ { email : 'jdoe@illinois.edu' } ] } ) ;
45
43
46
44
await renderComponent ( fetchMembers , updateMembers ) ;
47
- expect ( screen . getByText ( / D o e , J o h n \( j d o e @ i l l i n o i s \. e d u \) / ) ) . toBeInTheDocument ( ) ;
45
+ expect (
46
+ screen . getByText ( ( content , element ) => element ?. textContent === 'Doe, Johnjdoe@illinois.edu' )
47
+ ) . toBeInTheDocument ( ) ;
48
48
} ) ;
49
49
50
50
it ( 'renders with multiple members' , async ( ) => {
@@ -61,24 +61,21 @@ describe('Exec Group Management Panel read tests', () => {
61
61
] ,
62
62
} ) ;
63
63
64
- await renderComponent ( fetchMembers , updateMembers ) ;
65
- expect ( screen . getByText ( / D o e , J o h n \( j d o e @ i l l i n o i s \. e d u \) / ) ) . toBeInTheDocument ( ) ;
66
- expect ( screen . getByText ( / S m i t h , J a n e \( j s m i t h @ i l l i n o i s \. e d u \) / ) ) . toBeInTheDocument ( ) ;
67
- expect ( screen . getByText ( / B r o w n , B o b \( b b r o w n @ i l l i n o i s \. e d u \) / ) ) . toBeInTheDocument ( ) ;
68
- } ) ;
69
-
70
- it ( 'displays all required UI elements' , async ( ) => {
71
- const fetchMembers = async ( ) => [ ] ;
72
- const updateMembers = async ( ) => ( { success : [ ] } ) ;
73
-
74
64
await renderComponent ( fetchMembers , updateMembers ) ;
75
65
76
- expect ( screen . getByText ( 'Exec Council Group Management' ) ) . toBeInTheDocument ( ) ;
77
- expect ( screen . getByText ( 'Current Members' ) ) . toBeInTheDocument ( ) ;
78
- expect ( screen . getByLabelText ( 'Add Member' ) ) . toBeInTheDocument ( ) ;
79
- expect ( screen . getByPlaceholderText ( 'Enter email' ) ) . toBeInTheDocument ( ) ;
80
- expect ( screen . getByRole ( 'button' , { name : 'Add Member' } ) ) . toBeInTheDocument ( ) ;
81
- expect ( screen . getByRole ( 'button' , { name : 'Save Changes' } ) ) . toBeDisabled ( ) ;
66
+ expect (
67
+ screen . getByText ( ( content , element ) => element ?. textContent === 'Doe, Johnjdoe@illinois.edu' )
68
+ ) . toBeInTheDocument ( ) ;
69
+ expect (
70
+ screen . getByText (
71
+ ( content , element ) => element ?. textContent === 'Smith, Janejsmith@illinois.edu'
72
+ )
73
+ ) . toBeInTheDocument ( ) ;
74
+ expect (
75
+ screen . getByText (
76
+ ( content , element ) => element ?. textContent === 'Brown, Bobbbrown@illinois.edu'
77
+ )
78
+ ) . toBeInTheDocument ( ) ;
82
79
} ) ;
83
80
84
81
it ( 'adds a new member and saves changes' , async ( ) => {
@@ -100,108 +97,36 @@ describe('Exec Group Management Panel read tests', () => {
100
97
const addButton = screen . getByRole ( 'button' , { name : 'Add Member' } ) ;
101
98
await user . click ( addButton ) ;
102
99
103
- // Verify member appears with "Queued for addition" badge
100
+ // Match the queued member
101
+ expect ( screen . getByText ( 'member' ) ) . toBeInTheDocument ( ) ;
104
102
expect ( screen . getByText ( 'member@illinois.edu' ) ) . toBeInTheDocument ( ) ;
105
- expect ( screen . getByText ( 'Queued for addition' ) ) . toBeInTheDocument ( ) ;
106
103
107
- // Click Save Changes which opens modal
104
+ // Save Changes
108
105
const saveButton = screen . getByRole ( 'button' , { name : 'Save Changes' } ) ;
109
106
expect ( saveButton ) . toBeEnabled ( ) ;
110
107
await user . click ( saveButton ) ;
111
108
112
- // Wait for the modal to appear with title
113
109
await screen . findByText ( 'Confirm Changes' ) ;
114
-
115
- // Find and click confirm button in modal
116
110
const confirmButton = screen . getByRole ( 'button' , { name : 'Confirm and Save' } ) ;
117
111
await user . click ( confirmButton ) ;
118
112
119
- // Verify updateMembers was called with correct parameters
120
113
expect ( updateMembers ) . toHaveBeenCalledWith ( [ 'member@illinois.edu' ] , [ ] ) ;
121
-
122
- // Verify list is updated - "Queued for addition" badge should be gone
123
- expect ( screen . getByText ( / m e m b e r \( m e m b e r @ i l l i n o i s \. e d u \) / ) ) . toBeInTheDocument ( ) ;
124
- expect ( screen . queryByText ( 'Queued for addition' ) ) . not . toBeInTheDocument ( ) ;
125
-
126
- // Verify notifications were shown
127
- expect ( notificationsMock ) . toHaveBeenCalledWith (
128
- expect . objectContaining ( {
129
- message : 'All changes processed successfully!' ,
130
- color : 'green' ,
131
- } )
132
- ) ;
133
-
134
- // Verify Save Changes button is disabled again after successful update
135
- expect ( screen . getByRole ( 'button' , { name : 'Save Changes' } ) ) . toBeDisabled ( ) ;
136
-
137
- // Clean up
138
114
notificationsMock . mockRestore ( ) ;
139
115
} ) ;
140
- it ( 'handles failed member updates correctly' , async ( ) => {
141
- const notificationsMock = vi . spyOn ( notifications , 'show' ) ;
142
- const user = userEvent . setup ( ) ;
143
- const fetchMembers = async ( ) => [ ] ;
144
- const updateMembers = vi . fn ( ) . mockResolvedValue ( {
145
- success : [ ] ,
146
- failure : [
147
- {
148
- email : 'member@illinois.edu' ,
149
- message : 'User does not exist in directory' ,
150
- } ,
151
- ] ,
152
- } ) ;
153
-
154
- await renderComponent ( fetchMembers , updateMembers ) ;
155
-
156
- // Add a member that will fail
157
- const emailInput = screen . getByPlaceholderText ( 'Enter email' ) ;
158
- await user . type ( emailInput , 'member@illinois.edu' ) ;
159
- await user . click ( screen . getByRole ( 'button' , { name : 'Add Member' } ) ) ;
160
-
161
- // Verify member shows in queue
162
- expect ( screen . getByText ( 'member@illinois.edu' ) ) . toBeInTheDocument ( ) ;
163
- expect ( screen . getByText ( 'Queued for addition' ) ) . toBeInTheDocument ( ) ;
164
116
165
- // Try to save changes
166
- await user . click ( screen . getByRole ( 'button' , { name : 'Save Changes' } ) ) ;
167
- await screen . findByText ( 'Confirm Changes' ) ;
168
- await user . click ( screen . getByRole ( 'button' , { name : 'Confirm and Save' } ) ) ;
169
-
170
- expect ( notificationsMock ) . toHaveBeenCalledWith (
171
- expect . objectContaining ( {
172
- title : 'Error adding member@illinois.edu' ,
173
- message : 'User does not exist in directory' ,
174
- color : 'red' ,
175
- } )
176
- ) ;
177
-
178
- // Verify member is no longer shown as queued (since queues are cleared)
179
- expect ( screen . queryByText ( 'Queued for addition' ) ) . not . toBeInTheDocument ( ) ;
180
-
181
- // Verify Save Changes button is disabled since queues are cleared
182
- expect ( screen . getByRole ( 'button' , { name : 'Save Changes' } ) ) . toBeDisabled ( ) ;
183
-
184
- notificationsMock . mockRestore ( ) ;
185
- } ) ;
186
-
187
- it ( 'removes an existing member' , async ( ) => {
117
+ it ( 'removes an existing member and saves changes' , async ( ) => {
188
118
const notificationsMock = vi . spyOn ( notifications , 'show' ) ;
189
119
const user = userEvent . setup ( ) ;
190
- const fetchMembers = async ( ) => [
191
- {
192
- name : 'Existing Member' ,
193
- email : 'existing@illinois.edu' ,
194
- } ,
195
- ] ;
120
+ const fetchMembers = async ( ) => [ { name : 'Existing Member' , email : 'existing@illinois.edu' } ] ;
196
121
const updateMembers = vi . fn ( ) . mockResolvedValue ( {
197
122
success : [ { email : 'existing@illinois.edu' } ] ,
198
123
failure : [ ] ,
199
124
} ) ;
200
125
201
126
await renderComponent ( fetchMembers , updateMembers ) ;
202
127
203
- // Click remove button for the existing member using data-testid
204
- const removeButton = screen . getByTestId ( 'remove-exec-member-existing@illinois.edu' ) ;
128
+ // Click remove button for the existing member
129
+ const removeButton = screen . getByRole ( 'button' , { name : / R e m o v e / } ) ;
205
130
await user . click ( removeButton ) ;
206
131
207
132
// Verify member shows removal badge
@@ -217,10 +142,7 @@ describe('Exec Group Management Panel read tests', () => {
217
142
await user . click ( confirmButton ) ;
218
143
219
144
// Verify updateMembers was called with correct parameters
220
- expect ( updateMembers ) . toHaveBeenCalledWith (
221
- [ ] , // toAdd
222
- [ 'existing@illinois.edu' ] // toRemove
223
- ) ;
145
+ expect ( updateMembers ) . toHaveBeenCalledWith ( [ ] , [ 'existing@illinois.edu' ] ) ;
224
146
225
147
// Verify member is removed from the list
226
148
expect (
@@ -237,106 +159,49 @@ describe('Exec Group Management Panel read tests', () => {
237
159
238
160
notificationsMock . mockRestore ( ) ;
239
161
} ) ;
240
- it ( 'handles multiple member changes with mixed success/failure results' , async ( ) => {
162
+
163
+ it ( 'handles failed member updates correctly' , async ( ) => {
241
164
const notificationsMock = vi . spyOn ( notifications , 'show' ) ;
242
165
const user = userEvent . setup ( ) ;
243
-
244
- // Start with two existing members
245
- const fetchMembers = async ( ) => [
246
- { name : 'Stay Member' , email : 'stay@illinois.edu' } ,
247
- { name : 'Remove Success' , email : 'removesuccess@illinois.edu' } ,
248
- { name : 'Remove Fail' , email : 'removefail@illinois.edu' } ,
249
- ] ;
250
-
251
- // Mock mixed success/failure response
166
+ const fetchMembers = async ( ) => [ ] ;
252
167
const updateMembers = vi . fn ( ) . mockResolvedValue ( {
253
- success : [
254
- { email : 'removesuccess@illinois.edu' } , // removal succeeded
255
- { email : 'addsuccess@illinois.edu' } , // addition succeeded
256
- ] ,
168
+ success : [ ] ,
257
169
failure : [
258
170
{
259
- email : 'removefail@illinois.edu' ,
260
- message : 'Cannot remove admin user' ,
261
- } ,
262
- {
263
- email : 'addfail@illinois.edu' ,
264
- message : 'User not found in directory' ,
171
+ email : 'member@illinois.edu' ,
172
+ message : 'User does not exist in directory' ,
265
173
} ,
266
174
] ,
267
175
} ) ;
268
176
269
177
await renderComponent ( fetchMembers , updateMembers ) ;
270
178
271
- // Add two new members - one will succeed, one will fail
179
+ // Add a member that will fail
272
180
const emailInput = screen . getByPlaceholderText ( 'Enter email' ) ;
273
-
274
- await user . type ( emailInput , 'addsuccess@illinois.edu' ) ;
275
- await user . click ( screen . getByRole ( 'button' , { name : 'Add Member' } ) ) ;
276
-
277
- await user . type ( emailInput , 'addfail@illinois.edu' ) ;
181
+ await user . type ( emailInput , 'member@illinois.edu' ) ;
278
182
await user . click ( screen . getByRole ( 'button' , { name : 'Add Member' } ) ) ;
279
183
280
- // Remove two existing members - one will succeed, one will fail
281
- await user . click ( screen . getByTestId ( 'remove-exec-member-removesuccess@illinois.edu' ) ) ;
282
- await user . click ( screen . getByTestId ( 'remove-exec-member-removefail@illinois.edu' ) ) ;
283
-
284
- // Verify queued states before save
285
- expect ( screen . getByText ( 'addsuccess@illinois.edu' ) ) . toBeInTheDocument ( ) ;
286
- expect ( screen . getByText ( 'addfail@illinois.edu' ) ) . toBeInTheDocument ( ) ;
287
- expect ( screen . getAllByText ( 'Queued for addition' ) ) . toHaveLength ( 2 ) ;
288
- expect ( screen . getAllByText ( 'Queued for removal' ) ) . toHaveLength ( 2 ) ;
289
-
290
- // Save changes
291
- const saveButton = screen . getByRole ( 'button' , { name : 'Save Changes' } ) ;
292
- expect ( saveButton ) . toBeEnabled ( ) ;
293
- await user . click ( saveButton ) ;
184
+ // Verify member shows in queue
185
+ expect ( screen . getByText ( 'member@illinois.edu' ) ) . toBeInTheDocument ( ) ;
186
+ expect ( screen . getByText ( 'Queued for addition' ) ) . toBeInTheDocument ( ) ;
294
187
295
- // Confirm in modal
188
+ // Try to save changes
189
+ await user . click ( screen . getByRole ( 'button' , { name : 'Save Changes' } ) ) ;
296
190
await screen . findByText ( 'Confirm Changes' ) ;
297
- const confirmButton = screen . getByRole ( 'button' , { name : 'Confirm and Save' } ) ;
298
- await user . click ( confirmButton ) ;
299
-
300
- // Verify updateMembers was called with all changes
301
- expect ( updateMembers ) . toHaveBeenCalledWith (
302
- [ 'addsuccess@illinois.edu' , 'addfail@illinois.edu' ] ,
303
- [ 'removesuccess@illinois.edu' , 'removefail@illinois.edu' ]
304
- ) ;
305
-
306
- // Verify error notifications for failures
307
- expect ( notificationsMock ) . toHaveBeenCalledWith (
308
- expect . objectContaining ( {
309
- title : 'Error adding addfail@illinois.edu' ,
310
- message : 'User not found in directory' ,
311
- color : 'red' ,
312
- } )
313
- ) ;
191
+ await user . click ( screen . getByRole ( 'button' , { name : 'Confirm and Save' } ) ) ;
314
192
315
193
expect ( notificationsMock ) . toHaveBeenCalledWith (
316
194
expect . objectContaining ( {
317
- title : 'Error removing removefail @illinois.edu' ,
318
- message : 'Cannot remove admin user ' ,
195
+ title : 'Error with member @illinois.edu' ,
196
+ message : 'User does not exist in directory ' ,
319
197
color : 'red' ,
320
198
} )
321
199
) ;
322
200
323
- // Verify end state of member list
324
- // Success cases
325
- expect ( screen . queryByText ( / r e m o v e s u c c e s s @ i l l i n o i s \. e d u / ) ) . not . toBeInTheDocument ( ) ; // Successfully removed
326
- expect ( screen . getByText ( / a d d s u c c e s s @ i l l i n o i s \. e d u / ) ) . toBeInTheDocument ( ) ; // Successfully added
327
-
328
- // Failure cases
329
- expect ( screen . getByText ( / r e m o v e f a i l @ i l l i n o i s \. e d u / ) ) . toBeInTheDocument ( ) ; // Failed to remove
330
- expect ( screen . queryByText ( / a d d f a i l @ i l l i n o i s \. e d u / ) ) . not . toBeInTheDocument ( ) ; // Failed to add
331
-
332
- // Unchanged member
333
- expect ( screen . getByText ( / s t a y @ i l l i n o i s \. e d u / ) ) . toBeInTheDocument ( ) ;
334
-
335
- // Verify queued badges are cleared
201
+ // Verify member is no longer shown as queued
336
202
expect ( screen . queryByText ( 'Queued for addition' ) ) . not . toBeInTheDocument ( ) ;
337
- expect ( screen . queryByText ( 'Queued for removal' ) ) . not . toBeInTheDocument ( ) ;
338
203
339
- // Verify Save Changes button is disabled after operation
204
+ // Verify Save Changes button is disabled
340
205
expect ( screen . getByRole ( 'button' , { name : 'Save Changes' } ) ) . toBeDisabled ( ) ;
341
206
342
207
notificationsMock . mockRestore ( ) ;
0 commit comments