fix(docs-infra): do not break when cookies are disabled in the browser (#35557)
Whenever cookies are disabled in the browser, `window.localStorage` is not avaialable to the app (i.e. even trying to access `window.localStorage` throws an error). To avoid breaking the app, we use a no-op `Storage` implementation if `window.localStorage` is not available. (This is similar to #33829, but for `localStorage` instead of `sessionStorage`.) Fixes #35555 PR Close #35557
This commit is contained in:
		
							parent
							
								
									9c01ca42d3
								
							
						
					
					
						commit
						975a11b37f
					
				| @ -111,6 +111,22 @@ describe('NotificationComponent', () => { | ||||
|     expect(getItemSpy).toHaveBeenCalledWith('aio-notification/survey-january-2018'); | ||||
|     expect(component.showNotification).toBe('hide'); | ||||
|   }); | ||||
| 
 | ||||
|   it('should not break when cookies are disabled in the browser', () => { | ||||
|     configTestingModule(); | ||||
| 
 | ||||
|     // Simulate `window.localStorage` being inaccessible, when cookies are disabled.
 | ||||
|     const mockWindow: MockWindow = TestBed.inject(WindowToken); | ||||
|     Object.defineProperty(mockWindow, 'localStorage', { | ||||
|       get() { throw new Error('The operation is insecure'); }, | ||||
|     }); | ||||
| 
 | ||||
|     expect(() => createComponent()).not.toThrow(); | ||||
|     expect(component.showNotification).toBe('show'); | ||||
| 
 | ||||
|     component.dismiss(); | ||||
|     expect(component.showNotification).toBe('hide'); | ||||
|   }); | ||||
| }); | ||||
| 
 | ||||
| @Component({ | ||||
|  | ||||
| @ -20,7 +20,7 @@ const LOCAL_STORAGE_NAMESPACE = 'aio-notification/'; | ||||
|   ] | ||||
| }) | ||||
| export class NotificationComponent implements OnInit { | ||||
|   private get localStorage() { return this.window.localStorage; } | ||||
|   private storage: Storage; | ||||
| 
 | ||||
|   @Input() dismissOnContentClick: boolean; | ||||
|   @Input() notificationId: string; | ||||
| @ -31,12 +31,27 @@ export class NotificationComponent implements OnInit { | ||||
|   showNotification: 'show'|'hide'; | ||||
| 
 | ||||
|   constructor( | ||||
|     @Inject(WindowToken) private window: Window, | ||||
|     @Inject(WindowToken) window: Window, | ||||
|     @Inject(CurrentDateToken) private currentDate: Date | ||||
|   ) {} | ||||
|   ) { | ||||
|     try { | ||||
|       this.storage = window.localStorage; | ||||
|     } catch { | ||||
|       // When cookies are disabled in the browser, even trying to access
 | ||||
|       // `window.localStorage` throws an error. Use a no-op storage.
 | ||||
|       this.storage = { | ||||
|         length: 0, | ||||
|         clear: () => undefined, | ||||
|         getItem: () => null, | ||||
|         key: () => null, | ||||
|         removeItem: () => undefined, | ||||
|         setItem: () => undefined | ||||
|       }; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   ngOnInit() { | ||||
|     const previouslyHidden = this.localStorage.getItem(LOCAL_STORAGE_NAMESPACE + this.notificationId) === 'hide'; | ||||
|     const previouslyHidden = this.storage.getItem(LOCAL_STORAGE_NAMESPACE + this.notificationId) === 'hide'; | ||||
|     const expired = this.currentDate > new Date(this.expirationDate); | ||||
|     this.showNotification = previouslyHidden || expired ? 'hide' : 'show'; | ||||
|   } | ||||
| @ -48,7 +63,7 @@ export class NotificationComponent implements OnInit { | ||||
|   } | ||||
| 
 | ||||
|   dismiss() { | ||||
|     this.localStorage.setItem(LOCAL_STORAGE_NAMESPACE + this.notificationId, 'hide'); | ||||
|     this.storage.setItem(LOCAL_STORAGE_NAMESPACE + this.notificationId, 'hide'); | ||||
|     this.showNotification = 'hide'; | ||||
|     this.dismissed.next(); | ||||
|   } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user