feat(aio): make the ServiceWorker update process more intuitive/user-friendly (#16170)
Fixes #16093
This commit is contained in:
		
							parent
							
								
									e07b7ea114
								
							
						
					
					
						commit
						24c34385ee
					
				| @ -11,6 +11,8 @@ import { SwUpdatesService } from './sw-updates.service'; | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| describe('SwUpdateNotificationsService', () => { | describe('SwUpdateNotificationsService', () => { | ||||||
|  |   const UPDATE_AVAILABLE_MESSAGE = 'New update for angular.io is available.'; | ||||||
|  |   const UPDATE_FAILED_MESSAGE = 'Update activation failed :('; | ||||||
|   let injector: ReflectiveInjector; |   let injector: ReflectiveInjector; | ||||||
|   let service: SwUpdateNotificationsService; |   let service: SwUpdateNotificationsService; | ||||||
|   let swUpdates: MockSwUpdatesService; |   let swUpdates: MockSwUpdatesService; | ||||||
| @ -65,8 +67,8 @@ describe('SwUpdateNotificationsService', () => { | |||||||
| 
 | 
 | ||||||
|       swUpdates.$$isUpdateAvailableSubj.next(true); |       swUpdates.$$isUpdateAvailableSubj.next(true); | ||||||
| 
 | 
 | ||||||
|       expect(snackBar.$$lastRef.$$message).toContain('ServiceWorker update available'); |       expect(snackBar.$$lastRef.$$message).toBe(UPDATE_AVAILABLE_MESSAGE); | ||||||
|       expect(snackBar.$$lastRef.$$action).toBe('Activate'); |       expect(snackBar.$$lastRef.$$action).toBe('Update now'); | ||||||
|       expect(snackBar.$$lastRef.$$config.duration).toBeUndefined(); |       expect(snackBar.$$lastRef.$$config.duration).toBeUndefined(); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
| @ -75,7 +77,7 @@ describe('SwUpdateNotificationsService', () => { | |||||||
|       expect(snackBar.$$lastRef).toBeUndefined(); |       expect(snackBar.$$lastRef).toBeUndefined(); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should activate the update when clicking on `Activate`', () => { |     it('should activate the update when clicking on `Update now`', () => { | ||||||
|       spyOn(swUpdates, 'activateUpdate').and.callThrough(); |       spyOn(swUpdates, 'activateUpdate').and.callThrough(); | ||||||
| 
 | 
 | ||||||
|       swUpdates.$$isUpdateAvailableSubj.next(true); |       swUpdates.$$isUpdateAvailableSubj.next(true); | ||||||
| @ -85,30 +87,19 @@ describe('SwUpdateNotificationsService', () => { | |||||||
|       expect(swUpdates.activateUpdate).toHaveBeenCalled(); |       expect(swUpdates.activateUpdate).toHaveBeenCalled(); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should report a successful activation', fakeAsync(() => { |     it('should reload the page after a successful activation', fakeAsync(() => { | ||||||
|  |       const global = injector.get(Global); | ||||||
|  | 
 | ||||||
|  |       expect(global.location.reload).not.toHaveBeenCalled(); | ||||||
|  | 
 | ||||||
|       activateUpdate(true); |       activateUpdate(true); | ||||||
| 
 |       expect(global.location.reload).toHaveBeenCalled(); | ||||||
|       expect(snackBar.$$lastRef.$$message).toContain('Update activated successfully'); |  | ||||||
|       expect(snackBar.$$lastRef.$$action).toBe('Reload'); |  | ||||||
|       expect(snackBar.$$lastRef.$$config.duration).toBeUndefined(); |  | ||||||
|     })); |     })); | ||||||
| 
 | 
 | ||||||
|     it('should reload the page when clicking on `Reload` (after a successful activation)', |  | ||||||
|       fakeAsync(() => { |  | ||||||
|         const global = injector.get(Global); |  | ||||||
| 
 |  | ||||||
|         activateUpdate(true); |  | ||||||
|         expect(global.location.reload).not.toHaveBeenCalled(); |  | ||||||
| 
 |  | ||||||
|         snackBar.$$lastRef.$$onActionSubj.next(); |  | ||||||
|         expect(global.location.reload).toHaveBeenCalled(); |  | ||||||
|       }) |  | ||||||
|     ); |  | ||||||
| 
 |  | ||||||
|     it('should report a failed activation', fakeAsync(() => { |     it('should report a failed activation', fakeAsync(() => { | ||||||
|       activateUpdate(false); |       activateUpdate(false); | ||||||
| 
 | 
 | ||||||
|       expect(snackBar.$$lastRef.$$message).toContain('Update activation failed'); |       expect(snackBar.$$lastRef.$$message).toBe(UPDATE_FAILED_MESSAGE); | ||||||
|       expect(snackBar.$$lastRef.$$action).toBe('Dismiss'); |       expect(snackBar.$$lastRef.$$action).toBe('Dismiss'); | ||||||
|       expect(snackBar.$$lastRef.$$config.duration).toBeGreaterThan(0); |       expect(snackBar.$$lastRef.$$config.duration).toBeGreaterThan(0); | ||||||
|     })); |     })); | ||||||
| @ -128,22 +119,13 @@ describe('SwUpdateNotificationsService', () => { | |||||||
| 
 | 
 | ||||||
|     it('should dismiss open update notification', () => { |     it('should dismiss open update notification', () => { | ||||||
|       swUpdates.$$isUpdateAvailableSubj.next(true); |       swUpdates.$$isUpdateAvailableSubj.next(true); | ||||||
|       expect(snackBar.$$lastRef.$$message).toContain('ServiceWorker update available'); |       expect(snackBar.$$lastRef.$$message).toBe(UPDATE_AVAILABLE_MESSAGE); | ||||||
|       expect(snackBar.$$lastRef.$$dismissed).toBe(false); |       expect(snackBar.$$lastRef.$$dismissed).toBe(false); | ||||||
| 
 | 
 | ||||||
|       service.disable(); |       service.disable(); | ||||||
|       expect(snackBar.$$lastRef.$$dismissed).toBe(true); |       expect(snackBar.$$lastRef.$$dismissed).toBe(true); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should dismiss open activation notification', fakeAsync(() => { |  | ||||||
|       activateUpdate(true); |  | ||||||
|       expect(snackBar.$$lastRef.$$message).toContain('Update activated successfully'); |  | ||||||
|       expect(snackBar.$$lastRef.$$dismissed).toBe(false); |  | ||||||
| 
 |  | ||||||
|       service.disable(); |  | ||||||
|       expect(snackBar.$$lastRef.$$dismissed).toBe(true); |  | ||||||
|     })); |  | ||||||
| 
 |  | ||||||
|     it('should ignore further updates', () => { |     it('should ignore further updates', () => { | ||||||
|       service.disable(); |       service.disable(); | ||||||
|       swUpdates.$$isUpdateAvailableSubj.next(true); |       swUpdates.$$isUpdateAvailableSubj.next(true); | ||||||
| @ -157,7 +139,7 @@ describe('SwUpdateNotificationsService', () => { | |||||||
|       expect(snackBar.$$lastRef).toBeUndefined(); |       expect(snackBar.$$lastRef).toBeUndefined(); | ||||||
| 
 | 
 | ||||||
|       swUpdates.$$isUpdateAvailableSubj.next(true); |       swUpdates.$$isUpdateAvailableSubj.next(true); | ||||||
|       expect(snackBar.$$lastRef.$$message).toContain('ServiceWorker update available'); |       expect(snackBar.$$lastRef.$$message).toBe(UPDATE_AVAILABLE_MESSAGE); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('should not ignore pending updates if re-enabled', () => { |     it('should not ignore pending updates if re-enabled', () => { | ||||||
| @ -166,7 +148,7 @@ describe('SwUpdateNotificationsService', () => { | |||||||
|       expect(snackBar.$$lastRef).toBeUndefined(); |       expect(snackBar.$$lastRef).toBeUndefined(); | ||||||
| 
 | 
 | ||||||
|       service.enable(); |       service.enable(); | ||||||
|       expect(snackBar.$$lastRef.$$message).toContain('ServiceWorker update available'); |       expect(snackBar.$$lastRef.$$message).toBe(UPDATE_AVAILABLE_MESSAGE); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
| @ -174,7 +156,7 @@ describe('SwUpdateNotificationsService', () => { | |||||||
| // Mocks
 | // Mocks
 | ||||||
| class MockGlobal { | class MockGlobal { | ||||||
|   location = { |   location = { | ||||||
|     reload: jasmine.createSpy('MockGlobal.reload') |     reload: jasmine.createSpy('MockGlobal.location.reload') | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -12,9 +12,8 @@ import { SwUpdatesService } from './sw-updates.service'; | |||||||
|  * |  * | ||||||
|  * @description |  * @description | ||||||
|  * Once enabled: |  * Once enabled: | ||||||
|  * 1. Subscribes to ServiceWorker updates and prompts the user to activate. |  * 1. Subscribes to ServiceWorker updates and prompts the user to update. | ||||||
|  * 2. When the user confirms, it activates the update and notifies the user (upon activation success |  * 2. When the user confirms, it activates the update and reloads the page upon activation success. | ||||||
|  *    or failure). |  | ||||||
|  * 3. Continues to listen for available ServiceWorker updates. |  * 3. Continues to listen for available ServiceWorker updates. | ||||||
|  * |  * | ||||||
|  * @method |  * @method | ||||||
| @ -64,7 +63,7 @@ export class SwUpdateNotificationsService { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   private notifyForUpdate() { |   private notifyForUpdate() { | ||||||
|     this.openSnackBar('ServiceWorker update available.', 'Activate') |     this.openSnackBar('New update for angular.io is available.', 'Update now') | ||||||
|         .onAction().subscribe(() => this.activateUpdate()); |         .onAction().subscribe(() => this.activateUpdate()); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -74,9 +73,7 @@ export class SwUpdateNotificationsService { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   private onActivateSuccess() { |   private onActivateSuccess() { | ||||||
|     const message = 'Update activated successfully! Reload the page to see the latest content.'; |     this.reloadPage(); | ||||||
|     this.openSnackBar(message, 'Reload') |  | ||||||
|         .onAction().subscribe(() => this.reloadPage()); |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   private openSnackBar(message: string, action?: string, config?: MdSnackBarConfig): MdSnackBarRef<any> { |   private openSnackBar(message: string, action?: string, config?: MdSnackBarConfig): MdSnackBarRef<any> { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user