@@ -253,7 +253,7 @@ describe('page rules — render-time evaluation (#141052)', () => {
253253 test ( 'cached page-ruled notifications survive a reload on an excluded page but stay hidden' , ( ) => {
254254 setUrl ( EXCLUDED_URL ) ;
255255 const nm = withContainer ( GleapNotificationManager . getInstance ( ) ) ;
256- const cached = pageRuledNotification ( ) ;
256+ const cached = { ... pageRuledNotification ( ) , cachedForGleapId : 'user-1' } ;
257257 loadFromGleapCache . mockReturnValue ( [ cached ] ) ;
258258
259259 nm . reloadNotificationsFromCache ( ) ;
@@ -319,7 +319,9 @@ describe('notification stack', () => {
319319 test ( 'reloadNotificationsFromCache keeps the NEWEST 4 (the same end shift() trims from)' , ( ) => {
320320 const nm = withContainer ( GleapNotificationManager . getInstance ( ) ) ;
321321 jest . spyOn ( nm , 'renderNotifications' ) . mockImplementation ( ( ) => { } ) ;
322- loadFromGleapCache . mockReturnValue ( [ 1 , 2 , 3 , 4 , 5 , 6 ] . map ( ( i ) => plainNotification ( `n${ i } ` ) ) ) ;
322+ loadFromGleapCache . mockReturnValue (
323+ [ 1 , 2 , 3 , 4 , 5 , 6 ] . map ( ( i ) => ( { ...plainNotification ( `n${ i } ` ) , cachedForGleapId : 'user-1' } ) )
324+ ) ;
323325
324326 nm . reloadNotificationsFromCache ( ) ;
325327
@@ -365,9 +367,71 @@ describe('clearAllNotifications — cross-tab broadcast gate', () => {
365367 expect ( sendMessageMock ) . not . toHaveBeenCalled ( ) ;
366368 } ) ;
367369
368- test ( 'no notification container => early return, no broadcast' , ( ) => {
370+ test ( 'no notification container => no broadcast (the tab channel only starts with the UI) ' , ( ) => {
369371 const nm = GleapNotificationManager . getInstance ( ) ;
370372 nm . clearAllNotifications ( ) ;
371373 expect ( sendMessageMock ) . not . toHaveBeenCalled ( ) ;
372374 } ) ;
373375} ) ;
376+
377+ describe ( 'notification cache vs identity (#225880)' , ( ) => {
378+ const plainNotification = ( text , gleapId ) => ( {
379+ outbound : `outbound-${ text } ` ,
380+ createdAt : new Date ( ) . toISOString ( ) ,
381+ data : { text } ,
382+ ...( gleapId ? { cachedForGleapId : gleapId } : { } ) ,
383+ } ) ;
384+
385+ beforeEach ( ( ) => {
386+ loadFromGleapCache . mockReset ( ) ;
387+ saveToGleapCache . mockReset ( ) ;
388+ } ) ;
389+
390+ test ( 'clearAllNotifications(false) clears the persisted cache before the UI is mounted' , ( ) => {
391+ // A clearIdentity() queued in the snippet runs before injectNotificationUI().
392+ const nm = GleapNotificationManager . getInstance ( ) ;
393+ nm . notifications = [ plainNotification ( 'previous user' ) ] ;
394+
395+ nm . clearAllNotifications ( false ) ;
396+
397+ expect ( nm . notifications ) . toEqual ( [ ] ) ;
398+ expect ( saveToGleapCache ) . toHaveBeenCalledWith ( nm . unreadNotificationsKey , [ ] ) ;
399+ } ) ;
400+
401+ test ( 'a UI-only clear before mount leaves the cache alone' , ( ) => {
402+ const nm = GleapNotificationManager . getInstance ( ) ;
403+ const notification = plainNotification ( 'keep' ) ;
404+ nm . notifications = [ notification ] ;
405+
406+ nm . clearAllNotifications ( true ) ;
407+
408+ expect ( nm . notifications ) . toEqual ( [ notification ] ) ;
409+ expect ( saveToGleapCache ) . not . toHaveBeenCalled ( ) ;
410+ } ) ;
411+
412+ test ( 'showNotification stamps the receiving gleapId on the cached notification' , ( ) => {
413+ const nm = withContainer ( GleapNotificationManager . getInstance ( ) ) ;
414+ jest . spyOn ( nm , 'renderNotifications' ) . mockImplementation ( ( ) => { } ) ;
415+
416+ nm . showNotification ( plainNotification ( 'hello' ) ) ;
417+
418+ expect ( saveToGleapCache ) . toHaveBeenCalledWith ( nm . unreadNotificationsKey , [
419+ expect . objectContaining ( { cachedForGleapId : 'user-1' } ) ,
420+ ] ) ;
421+ } ) ;
422+
423+ test ( 'reloadNotificationsFromCache drops notifications cached for another (or no) gleapId' , ( ) => {
424+ const nm = withContainer ( GleapNotificationManager . getInstance ( ) ) ;
425+ jest . spyOn ( nm , 'renderNotifications' ) . mockImplementation ( ( ) => { } ) ;
426+ const own = plainNotification ( 'own' , 'user-1' ) ;
427+ loadFromGleapCache . mockReturnValue ( [
428+ plainNotification ( 'previous user' , 'user-0' ) ,
429+ plainNotification ( 'unstamped' ) ,
430+ own ,
431+ ] ) ;
432+
433+ nm . reloadNotificationsFromCache ( ) ;
434+
435+ expect ( nm . notifications ) . toEqual ( [ own ] ) ;
436+ } ) ;
437+ } ) ;
0 commit comments