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(getItemSpy).toHaveBeenCalledWith('aio-notification/survey-january-2018');
|
||||||
expect(component.showNotification).toBe('hide');
|
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({
|
@Component({
|
||||||
|
|
|
@ -20,7 +20,7 @@ const LOCAL_STORAGE_NAMESPACE = 'aio-notification/';
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class NotificationComponent implements OnInit {
|
export class NotificationComponent implements OnInit {
|
||||||
private get localStorage() { return this.window.localStorage; }
|
private storage: Storage;
|
||||||
|
|
||||||
@Input() dismissOnContentClick: boolean;
|
@Input() dismissOnContentClick: boolean;
|
||||||
@Input() notificationId: string;
|
@Input() notificationId: string;
|
||||||
|
@ -31,12 +31,27 @@ export class NotificationComponent implements OnInit {
|
||||||
showNotification: 'show'|'hide';
|
showNotification: 'show'|'hide';
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(WindowToken) private window: Window,
|
@Inject(WindowToken) window: Window,
|
||||||
@Inject(CurrentDateToken) private currentDate: Date
|
@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() {
|
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);
|
const expired = this.currentDate > new Date(this.expirationDate);
|
||||||
this.showNotification = previouslyHidden || expired ? 'hide' : 'show';
|
this.showNotification = previouslyHidden || expired ? 'hide' : 'show';
|
||||||
}
|
}
|
||||||
|
@ -48,7 +63,7 @@ export class NotificationComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
dismiss() {
|
dismiss() {
|
||||||
this.localStorage.setItem(LOCAL_STORAGE_NAMESPACE + this.notificationId, 'hide');
|
this.storage.setItem(LOCAL_STORAGE_NAMESPACE + this.notificationId, 'hide');
|
||||||
this.showNotification = 'hide';
|
this.showNotification = 'hide';
|
||||||
this.dismissed.next();
|
this.dismissed.next();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue