1- import { screen , waitFor , render as rtlRender } from '@testing-library/react' ;
1+ import { screen , waitFor } from '@testing-library/react' ;
22import userEvent from '@testing-library/user-event' ;
3- import { IntlProvider } from '@edx/frontend-platform/i18n' ;
3+ import { renderWrapper } from '@src/setupTest' ;
4+ import { logError } from '@edx/frontend-platform/logging' ;
45import { ToastManagerProvider , useToastManager } from './ToastManagerContext' ;
56
6- const render = ( ui : React . ReactElement ) => rtlRender (
7- < IntlProvider locale = "en" >
8- { ui }
9- </ IntlProvider > ,
10- ) ;
11-
7+ jest . mock ( '@edx/frontend-platform/logging' ) ;
128const TestComponent = ( ) => {
13- const { handleShowToast, handleDiscardToast } = useToastManager ( ) ;
9+ const { showToast } = useToastManager ( ) ;
10+
11+ const handleShowToast = ( ) => showToast ( { message : 'Test toast message' , type : 'error' } ) ;
12+ const handleShowAnotherToast = ( ) => showToast ( { message : 'Another message' , type : 'success' } ) ;
1413
1514 return (
1615 < div >
17- < button type = "button" onClick = { ( ) => handleShowToast ( 'Test toast message' ) } >
18- Show Toast
19- </ button >
20- < button type = "button" onClick = { ( ) => handleShowToast ( 'Another message' ) } >
21- Show Another Toast
22- </ button >
23- < button type = "button" onClick = { handleDiscardToast } >
24- Discard Toast
25- </ button >
16+ < button type = "button" onClick = { handleShowToast } > Show Toast</ button >
17+ < button type = "button" onClick = { handleShowAnotherToast } > Show Another Toast</ button >
2618 </ div >
2719 ) ;
2820} ;
2921
3022describe ( 'ToastManagerContext' , ( ) => {
3123 describe ( 'ToastManagerProvider' , ( ) => {
3224 it ( 'does not show toast initially' , ( ) => {
33- render (
25+ renderWrapper (
3426 < ToastManagerProvider >
3527 < TestComponent />
3628 </ ToastManagerProvider > ,
@@ -39,15 +31,14 @@ describe('ToastManagerContext', () => {
3931 expect ( screen . queryByRole ( 'alert' ) ) . not . toBeInTheDocument ( ) ;
4032 } ) ;
4133
42- it ( 'shows toast when handleShowToast is called' , async ( ) => {
34+ it ( 'shows toast when showToast is called' , async ( ) => {
4335 const user = userEvent . setup ( ) ;
44- render (
36+ renderWrapper (
4537 < ToastManagerProvider >
4638 < TestComponent />
4739 </ ToastManagerProvider > ,
4840 ) ;
4941
50- // handleShowToast is called on button click
5142 const showButton = screen . getByText ( 'Show Toast' ) ;
5243 await user . click ( showButton ) ;
5344
@@ -57,59 +48,29 @@ describe('ToastManagerContext', () => {
5748 } ) ;
5849 } ) ;
5950
60- it ( 'updates toast message when handleShowToast is called with different message ' , async ( ) => {
51+ it ( 'adds multiple toasts when showToast is called multiple times ' , async ( ) => {
6152 const user = userEvent . setup ( ) ;
62- render (
53+ renderWrapper (
6354 < ToastManagerProvider >
6455 < TestComponent />
6556 </ ToastManagerProvider > ,
6657 ) ;
6758
68- // Show first toast
6959 const showButton = screen . getByText ( 'Show Toast' ) ;
70- await user . click ( showButton ) ;
71-
72- await waitFor ( ( ) => {
73- expect ( screen . getByText ( 'Test toast message' ) ) . toBeInTheDocument ( ) ;
74- } ) ;
75-
76- // Show another toast
7760 const showAnotherButton = screen . getByText ( 'Show Another Toast' ) ;
78- await user . click ( showAnotherButton ) ;
79-
80- await waitFor ( ( ) => {
81- expect ( screen . getByText ( 'Another message' ) ) . toBeInTheDocument ( ) ;
82- expect ( screen . queryByText ( 'Test toast message' ) ) . not . toBeInTheDocument ( ) ;
83- } ) ;
84- } ) ;
8561
86- it ( 'hides toast when handleDiscardToast is called' , async ( ) => {
87- const user = userEvent . setup ( ) ;
88- render (
89- < ToastManagerProvider >
90- < TestComponent />
91- </ ToastManagerProvider > ,
92- ) ;
93-
94- const showButton = screen . getByText ( 'Show Toast' ) ;
9562 await user . click ( showButton ) ;
63+ await user . click ( showAnotherButton ) ;
9664
9765 await waitFor ( ( ) => {
9866 expect ( screen . getByText ( 'Test toast message' ) ) . toBeInTheDocument ( ) ;
99- } ) ;
100-
101- // handleDiscardToast is called on button click
102- const discardButton = screen . getByText ( 'Discard Toast' ) ;
103- await user . click ( discardButton ) ;
104-
105- await waitFor ( ( ) => {
106- expect ( screen . queryByRole ( 'alert' ) ) . not . toBeInTheDocument ( ) ;
67+ expect ( screen . getByText ( 'Another message' ) ) . toBeInTheDocument ( ) ;
10768 } ) ;
10869 } ) ;
10970
11071 it ( 'hides toast when close button is clicked' , async ( ) => {
11172 const user = userEvent . setup ( ) ;
112- render (
73+ renderWrapper (
11374 < ToastManagerProvider >
11475 < TestComponent />
11576 </ ToastManagerProvider > ,
@@ -127,50 +88,53 @@ describe('ToastManagerContext', () => {
12788
12889 await waitFor ( ( ) => {
12990 expect ( screen . queryByRole ( 'alert' ) ) . not . toBeInTheDocument ( ) ;
130- } ) ;
131- } ) ;
132-
133- it ( 'calls handleClose callback when toast is closed' , async ( ) => {
134- const user = userEvent . setup ( ) ;
135- const mockHandleClose = jest . fn ( ) ;
136-
137- render (
138- < ToastManagerProvider handleClose = { mockHandleClose } >
139- < TestComponent />
140- </ ToastManagerProvider > ,
141- ) ;
142-
143- const showButton = screen . getByText ( 'Show Toast' ) ;
144- await user . click ( showButton ) ;
145-
146- await waitFor ( ( ) => {
147- expect ( screen . getByText ( 'Test toast message' ) ) . toBeInTheDocument ( ) ;
148- } ) ;
149-
150- const closeButton = screen . getByLabelText ( 'Close' ) ;
151- await user . click ( closeButton ) ;
152-
153- await waitFor ( ( ) => {
154- expect ( mockHandleClose ) . toHaveBeenCalledTimes ( 1 ) ;
155- } ) ;
91+ } , { timeout : 500 } ) ;
15692 } ) ;
15793 } ) ;
15894
15995 describe ( 'useToastManager hook' , ( ) => {
16096 it ( 'throws error when used outside ToastManagerProvider' , ( ) => {
161- // Suppress console.error for this test
162- const consoleSpy = jest . spyOn ( console , 'error' ) . mockImplementation ( ( ) => { } ) ;
97+ const consoleSpy = jest . spyOn ( console , 'error' ) . mockImplementation ( ( ) => { } ) ;
16398
16499 const TestComponentWithoutProvider = ( ) => {
165100 useToastManager ( ) ;
166101 return < div > Test</ div > ;
167102 } ;
168103
169104 expect ( ( ) => {
170- render ( < TestComponentWithoutProvider /> ) ;
171- } ) . toThrow ( 'useToastManager must be used within an ToastManagerProvider' ) ;
105+ renderWrapper ( < TestComponentWithoutProvider /> ) ;
106+ } ) . toThrow ( 'useToastManager must be used within a ToastManagerProvider' ) ;
172107
173108 consoleSpy . mockRestore ( ) ;
174109 } ) ;
175110 } ) ;
111+
112+ it ( 'calls retry function when retry button is clicked' , async ( ) => {
113+ const user = userEvent . setup ( ) ;
114+ const retryFn = jest . fn ( ) ;
115+
116+ const ErrorTestComponent = ( ) => {
117+ const { showErrorToast } = useToastManager ( ) ;
118+ return (
119+ < button
120+ type = "button"
121+ onClick = { ( ) => showErrorToast ( { customAttributes : { httpErrorStatus : 500 } } , retryFn ) }
122+ > Retry Error
123+ </ button >
124+ ) ;
125+ } ;
126+
127+ renderWrapper (
128+ < ToastManagerProvider >
129+ < ErrorTestComponent />
130+ </ ToastManagerProvider > ,
131+ ) ;
132+
133+ await user . click ( screen . getByText ( 'Retry Error' ) ) ;
134+ const retryButton = await screen . findByText ( 'Retry' ) ;
135+ await user . click ( retryButton ) ;
136+
137+ expect ( logError ) . toHaveBeenCalled ( ) ;
138+ expect ( retryFn ) . toHaveBeenCalled ( ) ;
139+ } ) ;
176140} ) ;
0 commit comments