@@ -188,6 +188,27 @@ describe("CephContainers (index)", () => {
188188 } )
189189 } )
190190
191+ // The bulk-empty flow now lives in the Zone 3 "Actions" popup: select rows,
192+ // open the (otherwise disabled) Actions menu, then click the singular/plural
193+ // "Empty Bucket(s)" item to open the modal.
194+ const actionsButton = ( ) => screen . getByRole ( "button" , { name : / A c t i o n s / i } )
195+
196+ const selectOne = async ( user : ReturnType < typeof userEvent . setup > ) => {
197+ await user . click ( screen . getByTestId ( "simulate-select-bucket" ) )
198+ await waitFor ( ( ) => expect ( actionsButton ( ) ) . toBeEnabled ( ) )
199+ }
200+
201+ const selectTwo = async ( user : ReturnType < typeof userEvent . setup > ) => {
202+ await user . click ( screen . getByTestId ( "simulate-select-two" ) )
203+ await waitFor ( ( ) => expect ( actionsButton ( ) ) . toBeEnabled ( ) )
204+ }
205+
206+ const openEmptyModal = async ( user : ReturnType < typeof userEvent . setup > , label : "Empty Bucket" | "Empty Buckets" ) => {
207+ await user . click ( actionsButton ( ) )
208+ await user . click ( await screen . findByText ( label ) )
209+ await waitFor ( ( ) => expect ( screen . getByTestId ( "empty-buckets-modal" ) ) . toBeInTheDocument ( ) )
210+ }
211+
191212 describe ( "Loading state" , ( ) => {
192213 test ( "shows loading spinner while fetching" , ( ) => {
193214 trpcState . isLoading = true
@@ -236,14 +257,14 @@ describe("CephContainers (index)", () => {
236257 expect ( screen . getByRole ( "button" , { name : / C r e a t e B u c k e t / i } ) ) . toBeInTheDocument ( )
237258 } )
238259
239- test ( "renders Empty All button" , ( ) => {
260+ test ( "renders the Actions button" , ( ) => {
240261 renderContainers ( )
241- expect ( screen . getByRole ( "button" , { name : / ^ E m p t y A l l $ / i } ) ) . toBeInTheDocument ( )
262+ expect ( screen . getByRole ( "button" , { name : / A c t i o n s / i } ) ) . toBeInTheDocument ( )
242263 } )
243264
244- test ( "Empty All button is disabled when no containers are selected" , ( ) => {
265+ test ( "Actions button is disabled when no containers are selected" , ( ) => {
245266 renderContainers ( )
246- expect ( screen . getByRole ( "button" , { name : / ^ E m p t y A l l $ / i } ) ) . toBeDisabled ( )
267+ expect ( screen . getByRole ( "button" , { name : / A c t i o n s / i } ) ) . toBeDisabled ( )
247268 } )
248269
249270 test ( "passes selectedContainers and setSelectedContainers to ContainerTableView" , ( ) => {
@@ -304,79 +325,71 @@ describe("CephContainers (index)", () => {
304325 } )
305326 } )
306327
307- describe ( "Empty All button " , ( ) => {
308- test ( "shows no count when nothing is selected" , ( ) => {
328+ describe ( "Bulk actions menu " , ( ) => {
329+ test ( "Actions button is disabled when nothing is selected" , ( ) => {
309330 renderContainers ( )
310- expect ( screen . getByRole ( "button" , { name : "Empty All" } ) ) . toBeInTheDocument ( )
331+ expect ( actionsButton ( ) ) . toBeDisabled ( )
311332 } )
312333
313- test ( "is enabled and shows count after selecting containers " , async ( ) => {
334+ test ( "Actions button becomes enabled after selecting a bucket " , async ( ) => {
314335 const user = userEvent . setup ( )
315336 renderContainers ( )
316337 await user . click ( screen . getByTestId ( "simulate-select-bucket" ) )
317- await waitFor ( ( ) => {
318- expect ( screen . getByRole ( "button" , { name : / E m p t y A l l \( 1 \) / i } ) ) . toBeEnabled ( )
319- } )
338+ await waitFor ( ( ) => expect ( actionsButton ( ) ) . toBeEnabled ( ) )
320339 } )
321340
322- test ( "count updates as more containers are selected" , async ( ) => {
341+ test ( "shows the singular Empty Bucket item when one bucket is selected" , async ( ) => {
323342 const user = userEvent . setup ( )
324343 renderContainers ( )
325- await user . click ( screen . getByTestId ( "simulate-select-two" ) )
326- await waitFor ( ( ) => {
327- expect ( screen . getByRole ( "button" , { name : / E m p t y A l l \( 2 \) / i } ) ) . toBeEnabled ( )
328- } )
344+ await selectOne ( user )
345+ await user . click ( actionsButton ( ) )
346+ expect ( await screen . findByText ( "Empty Bucket" ) ) . toBeInTheDocument ( )
329347 } )
330348
331- test ( "returns to disabled with no count after deselecting all " , async ( ) => {
349+ test ( "shows the plural Empty Buckets item when multiple buckets are selected " , async ( ) => {
332350 const user = userEvent . setup ( )
333351 renderContainers ( )
334- await user . click ( screen . getByTestId ( "simulate-select-bucket" ) )
335- await waitFor ( ( ) => expect ( screen . getByRole ( "button" , { name : / E m p t y A l l \( 1 \) / i } ) ) . toBeEnabled ( ) )
352+ await selectTwo ( user )
353+ await user . click ( actionsButton ( ) )
354+ expect ( await screen . findByText ( "Empty Buckets" ) ) . toBeInTheDocument ( )
355+ } )
356+
357+ test ( "Actions button returns to disabled after deselecting all" , async ( ) => {
358+ const user = userEvent . setup ( )
359+ renderContainers ( )
360+ await selectOne ( user )
336361 await user . click ( screen . getByTestId ( "simulate-deselect-all" ) )
337- await waitFor ( ( ) => {
338- expect ( screen . getByRole ( "button" , { name : "Empty All" } ) ) . toBeDisabled ( )
339- } )
362+ await waitFor ( ( ) => expect ( actionsButton ( ) ) . toBeDisabled ( ) )
340363 } )
341364 } )
342365
343- describe ( "Empty All modal" , ( ) => {
344- const selectOne = async ( user : ReturnType < typeof userEvent . setup > ) => {
345- await user . click ( screen . getByTestId ( "simulate-select-bucket" ) )
346- await waitFor ( ( ) => expect ( screen . getByRole ( "button" , { name : / E m p t y A l l \( 1 \) / i } ) ) . toBeEnabled ( ) )
347- }
348-
366+ describe ( "Bulk empty modal" , ( ) => {
349367 test ( "modal is not visible by default" , ( ) => {
350368 renderContainers ( )
351369 expect ( screen . queryByTestId ( "empty-buckets-modal" ) ) . not . toBeInTheDocument ( )
352370 } )
353371
354- test ( "clicking Empty All opens the modal" , async ( ) => {
372+ test ( "choosing Empty Bucket from the Actions menu opens the modal" , async ( ) => {
355373 const user = userEvent . setup ( )
356374 renderContainers ( )
357375 await selectOne ( user )
358- await user . click ( screen . getByRole ( "button" , { name : / E m p t y A l l \( 1 \) / i } ) )
359- await waitFor ( ( ) => {
360- expect ( screen . getByTestId ( "empty-buckets-modal" ) ) . toBeInTheDocument ( )
361- } )
376+ await openEmptyModal ( user , "Empty Bucket" )
377+ expect ( screen . getByTestId ( "empty-buckets-modal" ) ) . toBeInTheDocument ( )
362378 } )
363379
364380 test ( "modal receives the selected bucket count" , async ( ) => {
365381 const user = userEvent . setup ( )
366382 renderContainers ( )
367383 await selectOne ( user )
368- await user . click ( screen . getByRole ( "button" , { name : / E m p t y A l l \( 1 \) / i } ) )
369- await waitFor ( ( ) => {
370- expect ( screen . getByTestId ( "empty-buckets-modal" ) ) . toHaveAttribute ( "data-bucket-count" , "1" )
371- } )
384+ await openEmptyModal ( user , "Empty Bucket" )
385+ expect ( screen . getByTestId ( "empty-buckets-modal" ) ) . toHaveAttribute ( "data-bucket-count" , "1" )
372386 } )
373387
374388 test ( "closing the modal hides it" , async ( ) => {
375389 const user = userEvent . setup ( )
376390 renderContainers ( )
377391 await selectOne ( user )
378- await user . click ( screen . getByRole ( "button" , { name : / E m p t y A l l \( 1 \) / i } ) )
379- await waitFor ( ( ) => expect ( screen . getByTestId ( "empty-buckets-modal" ) ) . toBeInTheDocument ( ) )
392+ await openEmptyModal ( user , "Empty Bucket" )
380393 await user . click ( screen . getByRole ( "button" , { name : "CloseEmptyAll" } ) )
381394 await waitFor ( ( ) => {
382395 expect ( screen . queryByTestId ( "empty-buckets-modal" ) ) . not . toBeInTheDocument ( )
@@ -388,8 +401,7 @@ describe("CephContainers (index)", () => {
388401 const user = userEvent . setup ( )
389402 renderContainers ( )
390403 await selectOne ( user )
391- await user . click ( screen . getByRole ( "button" , { name : / E m p t y A l l \( 1 \) / i } ) )
392- await waitFor ( ( ) => expect ( screen . getByTestId ( "empty-buckets-modal" ) ) . toBeInTheDocument ( ) )
404+ await openEmptyModal ( user , "Empty Bucket" )
393405 await user . click ( screen . getByTestId ( "simulate-empty-success" ) )
394406 await waitFor ( ( ) => {
395407 expect ( getBucketsEmptyCompleteToast ) . toHaveBeenCalledWith (
@@ -398,17 +410,15 @@ describe("CephContainers (index)", () => {
398410 [ ] ,
399411 expect . objectContaining ( { onDismiss : expect . any ( Function ) } )
400412 )
401- expect ( screen . getByRole ( "button" , { name : "Empty All" } ) ) . toBeDisabled ( )
413+ expect ( actionsButton ( ) ) . toBeDisabled ( )
402414 } )
403415 } )
404416
405417 test ( "keeps failed buckets selected after partial error" , async ( ) => {
406418 const user = userEvent . setup ( )
407419 renderContainers ( )
408- await user . click ( screen . getByTestId ( "simulate-select-two" ) )
409- await waitFor ( ( ) => expect ( screen . getByRole ( "button" , { name : / E m p t y A l l \( 2 \) / i } ) ) . toBeEnabled ( ) )
410- await user . click ( screen . getByRole ( "button" , { name : / E m p t y A l l \( 2 \) / i } ) )
411- await waitFor ( ( ) => expect ( screen . getByTestId ( "empty-buckets-modal" ) ) . toBeInTheDocument ( ) )
420+ await selectTwo ( user )
421+ await openEmptyModal ( user , "Empty Buckets" )
412422 await user . click ( screen . getByTestId ( "simulate-empty-error" ) )
413423 await waitFor ( ( ) => {
414424 // Only bucket-1 failed — it stays selected; bucket-2 succeeded — cleared
0 commit comments