@@ -178,6 +178,101 @@ test('propagates flash message context into callback', async () => {
178178 } ) ;
179179} ) ;
180180
181+ test ( 'propagates state changes to update callback' , async ( ) => {
182+ const updateContentSpy = jest . fn ( ) ;
183+ const testAction : ActionConfig = {
184+ ...defaultAction ,
185+ updateContent : ( container , context ) => updateContentSpy ( context . contentRef . current ?. textContent ) ,
186+ } ;
187+
188+ awsuiPlugins . flashbar . registerAction ( testAction ) ;
189+ const { rerender } = render ( < Flashbar items = { [ { ...defaultItem , content : 'Initial content' } ] } /> ) ;
190+ await delay ( ) ;
191+ expect ( updateContentSpy ) . toHaveBeenCalledTimes ( 0 ) ;
192+ rerender ( < Flashbar items = { [ { ...defaultItem , content : 'Updated content' } ] } /> ) ;
193+ expect ( updateContentSpy ) . toHaveBeenCalledTimes ( 1 ) ;
194+ expect ( updateContentSpy ) . toHaveBeenCalledWith ( 'Updated content' ) ;
195+ } ) ;
196+
197+ test ( 'container reference is permanent between mount/update/unmount' , async ( ) => {
198+ let container : HTMLElement | null = null ;
199+ const testAction : ActionConfig = {
200+ id : 'test-action' ,
201+ mountContent : jest . fn ( newContainer => ( container = newContainer ) ) ,
202+ updateContent : jest . fn ( newContainer => expect ( container ) . toBe ( newContainer ) ) ,
203+ unmountContent : jest . fn ( newContainer => expect ( container ) . toBe ( newContainer ) ) ,
204+ } ;
205+ awsuiPlugins . flashbar . registerAction ( testAction ) ;
206+ const { rerender } = render ( < Flashbar items = { [ { ...defaultItem } ] } /> ) ;
207+ await delay ( ) ;
208+ expect ( testAction . mountContent ) . toHaveBeenCalledTimes ( 1 ) ;
209+ expect ( testAction . updateContent ) . toHaveBeenCalledTimes ( 0 ) ;
210+ expect ( testAction . unmountContent ) . toHaveBeenCalledTimes ( 0 ) ;
211+ rerender ( < Flashbar items = { [ { ...defaultItem } ] } /> ) ;
212+ expect ( testAction . mountContent ) . toHaveBeenCalledTimes ( 1 ) ;
213+ expect ( testAction . updateContent ) . toHaveBeenCalledTimes ( 1 ) ;
214+ expect ( testAction . unmountContent ) . toHaveBeenCalledTimes ( 0 ) ;
215+ rerender ( < > </ > ) ;
216+ expect ( testAction . mountContent ) . toHaveBeenCalledTimes ( 1 ) ;
217+ expect ( testAction . updateContent ) . toHaveBeenCalledTimes ( 1 ) ;
218+ expect ( testAction . unmountContent ) . toHaveBeenCalledTimes ( 1 ) ;
219+ } ) ;
220+
221+ test ( 'allows conditionally render content when an item changes' , async ( ) => {
222+ const unmount = ( container : HTMLElement ) => ( container . innerHTML = '' ) ;
223+ const renderIfApplicable = ( container : HTMLElement , content : string ) => {
224+ if ( content . includes ( 'permission' ) ) {
225+ container . innerHTML = '<button data-testid="troubleshooter"></button>' ;
226+ } else {
227+ unmount ( container ) ;
228+ }
229+ } ;
230+ const testAction : ActionConfig = {
231+ ...defaultAction ,
232+ mountContent : ( container , { contentRef } ) => renderIfApplicable ( container , contentRef . current ! . textContent ! ) ,
233+ updateContent : ( container , { contentRef } ) => renderIfApplicable ( container , contentRef . current ! . textContent ! ) ,
234+ unmountContent : unmount ,
235+ } ;
236+ awsuiPlugins . flashbar . registerAction ( testAction ) ;
237+ const { rerender, queryAllByTestId } = render ( < Flashbar items = { [ { id : '1' , content : 'random content' } ] } /> ) ;
238+ await delay ( ) ;
239+ expect ( queryAllByTestId ( 'troubleshooter' ) ) . toHaveLength ( 0 ) ;
240+
241+ // add new notification matching the pattern
242+ rerender (
243+ < Flashbar
244+ items = { [
245+ { id : '1' , content : 'random content' } ,
246+ { id : '2' , content : 'permission issue' } ,
247+ ] }
248+ />
249+ ) ;
250+ await delay ( ) ;
251+ expect ( queryAllByTestId ( 'troubleshooter' ) ) . toHaveLength ( 1 ) ;
252+
253+ // update the existing notification to match the pattern
254+ rerender (
255+ < Flashbar
256+ items = { [
257+ { id : '1' , content : 'permission issue dynamic' } ,
258+ { id : '2' , content : 'permission issue' } ,
259+ ] }
260+ />
261+ ) ;
262+ expect ( queryAllByTestId ( 'troubleshooter' ) ) . toHaveLength ( 2 ) ;
263+
264+ // update the existing notification to not match the pattern anymore
265+ rerender (
266+ < Flashbar
267+ items = { [
268+ { id : '1' , content : 'resolved issue' } ,
269+ { id : '2' , content : 'permission issue' } ,
270+ ] }
271+ />
272+ ) ;
273+ expect ( queryAllByTestId ( 'troubleshooter' ) ) . toHaveLength ( 1 ) ;
274+ } ) ;
275+
181276test ( 'cleans up on unmount' , async ( ) => {
182277 const testAction : ActionConfig = {
183278 ...defaultAction ,
0 commit comments