| 
									
										
										
										
											2019-06-01 00:56:07 +09:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							| 
									
										
										
										
											2020-05-19 12:08:49 -07:00
										 |  |  |  * Copyright Google LLC All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2019-06-01 00:56:07 +09:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | import {ifEnvSupports, ifEnvSupportsWithDone, isFirefox, isSafari} from '../test-util'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | declare const global: any; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | describe( | 
					
						
							|  |  |  |     'fetch', ifEnvSupports('fetch', function() { | 
					
						
							|  |  |  |       let testZone: Zone; | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |       beforeEach(() => { | 
					
						
							|  |  |  |         testZone = Zone.current.fork({name: 'TestZone'}); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2019-06-01 00:56:07 +09:00
										 |  |  |       it('should work for text response', function(done) { | 
					
						
							|  |  |  |         testZone.run(function() { | 
					
						
							|  |  |  |           global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json') | 
					
						
							|  |  |  |               .then(function(response: any) { | 
					
						
							|  |  |  |                 const fetchZone = Zone.current; | 
					
						
							|  |  |  |                 expect(fetchZone.name).toBe(testZone.name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 response.text().then(function(text: string) { | 
					
						
							|  |  |  |                   expect(Zone.current.name).toBe(fetchZone.name); | 
					
						
							|  |  |  |                   expect(text.trim()).toEqual('{"hello": "world"}'); | 
					
						
							|  |  |  |                   done(); | 
					
						
							|  |  |  |                 }); | 
					
						
							|  |  |  |               }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should work for json response', function(done) { | 
					
						
							|  |  |  |         testZone.run(function() { | 
					
						
							|  |  |  |           global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json') | 
					
						
							|  |  |  |               .then(function(response: any) { | 
					
						
							|  |  |  |                 const fetchZone = Zone.current; | 
					
						
							|  |  |  |                 expect(fetchZone.name).toBe(testZone.name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 response.json().then(function(obj: any) { | 
					
						
							|  |  |  |                   expect(Zone.current.name).toBe(fetchZone.name); | 
					
						
							|  |  |  |                   expect(obj.hello).toEqual('world'); | 
					
						
							|  |  |  |                   done(); | 
					
						
							|  |  |  |                 }); | 
					
						
							|  |  |  |               }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should work for blob response', function(done) { | 
					
						
							|  |  |  |         testZone.run(function() { | 
					
						
							|  |  |  |           global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json') | 
					
						
							|  |  |  |               .then(function(response: any) { | 
					
						
							|  |  |  |                 const fetchZone = Zone.current; | 
					
						
							|  |  |  |                 expect(fetchZone.name).toBe(testZone.name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // Android 4.3- doesn't support response.blob()
 | 
					
						
							|  |  |  |                 if (response.blob) { | 
					
						
							|  |  |  |                   response.blob().then(function(blob: any) { | 
					
						
							|  |  |  |                     expect(Zone.current.name).toBe(fetchZone.name); | 
					
						
							|  |  |  |                     expect(blob instanceof Blob).toEqual(true); | 
					
						
							|  |  |  |                     done(); | 
					
						
							|  |  |  |                   }); | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                   done(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |               }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should work for arrayBuffer response', function(done) { | 
					
						
							|  |  |  |         testZone.run(function() { | 
					
						
							|  |  |  |           global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json') | 
					
						
							|  |  |  |               .then(function(response: any) { | 
					
						
							|  |  |  |                 const fetchZone = Zone.current; | 
					
						
							|  |  |  |                 expect(fetchZone.name).toBe(testZone.name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // Android 4.3- doesn't support response.arrayBuffer()
 | 
					
						
							|  |  |  |                 if (response.arrayBuffer) { | 
					
						
							|  |  |  |                   response.arrayBuffer().then(function(blob: any) { | 
					
						
							|  |  |  |                     expect(Zone.current).toBe(fetchZone); | 
					
						
							|  |  |  |                     expect(blob instanceof ArrayBuffer).toEqual(true); | 
					
						
							|  |  |  |                     done(); | 
					
						
							|  |  |  |                   }); | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                   done(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |               }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should throw error when send crendential', | 
					
						
							|  |  |  |          ifEnvSupportsWithDone(isFirefox, function(done: DoneFn) { | 
					
						
							|  |  |  |            testZone.run(function() { | 
					
						
							|  |  |  |              global['fetch']('http://user:password@example.com') | 
					
						
							|  |  |  |                  .then( | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |                      function(response: any) { | 
					
						
							|  |  |  |                        fail('should not success'); | 
					
						
							|  |  |  |                      }, | 
					
						
							| 
									
										
										
										
											2019-06-01 00:56:07 +09:00
										 |  |  |                      (error: any) => { | 
					
						
							|  |  |  |                        expect(Zone.current.name).toEqual(testZone.name); | 
					
						
							|  |  |  |                        expect(error.constructor.name).toEqual('TypeError'); | 
					
						
							|  |  |  |                        done(); | 
					
						
							|  |  |  |                      }); | 
					
						
							|  |  |  |            }); | 
					
						
							|  |  |  |          })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       describe('macroTask', () => { | 
					
						
							|  |  |  |         const logs: string[] = []; | 
					
						
							|  |  |  |         let fetchZone: Zone; | 
					
						
							|  |  |  |         let fetchTask: any = null; | 
					
						
							|  |  |  |         beforeEach(() => { | 
					
						
							|  |  |  |           logs.splice(0); | 
					
						
							|  |  |  |           fetchZone = Zone.current.fork({ | 
					
						
							|  |  |  |             name: 'fetch', | 
					
						
							|  |  |  |             onScheduleTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, task: Task) => { | 
					
						
							|  |  |  |               if (task.type !== 'eventTask') { | 
					
						
							|  |  |  |                 logs.push(`scheduleTask:${task.source}:${task.type}`); | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               if (task.source === 'fetch') { | 
					
						
							|  |  |  |                 fetchTask = task; | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               return delegate.scheduleTask(target, task); | 
					
						
							|  |  |  |             }, | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |             onInvokeTask: | 
					
						
							|  |  |  |                 (delegate: ZoneDelegate, curr: Zone, target: Zone, task: Task, applyThis: any, | 
					
						
							|  |  |  |                  applyArgs: any) => { | 
					
						
							|  |  |  |                   if (task.type !== 'eventTask') { | 
					
						
							|  |  |  |                     logs.push(`invokeTask:${task.source}:${task.type}`); | 
					
						
							|  |  |  |                   } | 
					
						
							|  |  |  |                   return delegate.invokeTask(target, task, applyThis, applyArgs); | 
					
						
							|  |  |  |                 }, | 
					
						
							| 
									
										
										
										
											2019-06-01 00:56:07 +09:00
										 |  |  |             onCancelTask: (delegate: ZoneDelegate, curr: Zone, target: Zone, task: Task) => { | 
					
						
							|  |  |  |               if (task.type !== 'eventTask') { | 
					
						
							|  |  |  |                 logs.push(`cancelTask:${task.source}:${task.type}`); | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               return delegate.cancelTask(target, task); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         it('fetch should be considered as macroTask', (done: DoneFn) => { | 
					
						
							|  |  |  |           fetchZone.run(() => { | 
					
						
							|  |  |  |             global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json') | 
					
						
							|  |  |  |                 .then(function(response: any) { | 
					
						
							|  |  |  |                   expect(Zone.current.name).toBe(fetchZone.name); | 
					
						
							|  |  |  |                   expect(logs).toEqual([ | 
					
						
							|  |  |  |                     'scheduleTask:fetch:macroTask', 'scheduleTask:Promise.then:microTask', | 
					
						
							|  |  |  |                     'invokeTask:Promise.then:microTask', 'invokeTask:fetch:macroTask', | 
					
						
							|  |  |  |                     'scheduleTask:Promise.then:microTask', 'invokeTask:Promise.then:microTask' | 
					
						
							|  |  |  |                   ]); | 
					
						
							|  |  |  |                   done(); | 
					
						
							|  |  |  |                 }); | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('cancel fetch should invoke onCancelTask', | 
					
						
							|  |  |  |            ifEnvSupportsWithDone('AbortController', (done: DoneFn) => { | 
					
						
							| 
									
										
										
										
											2019-11-09 20:36:22 +02:00
										 |  |  |              if (isSafari()) { | 
					
						
							| 
									
										
										
										
											2019-06-01 00:56:07 +09:00
										 |  |  |                // safari not work with AbortController
 | 
					
						
							|  |  |  |                done(); | 
					
						
							|  |  |  |                return; | 
					
						
							|  |  |  |              } | 
					
						
							|  |  |  |              fetchZone.run(() => { | 
					
						
							|  |  |  |                const AbortController = global['AbortController']; | 
					
						
							|  |  |  |                const abort = new AbortController(); | 
					
						
							|  |  |  |                const signal = abort.signal; | 
					
						
							|  |  |  |                global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json', {signal}) | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |                    .then(function(response: any) { | 
					
						
							|  |  |  |                      fail('should not get response'); | 
					
						
							|  |  |  |                    }) | 
					
						
							| 
									
										
										
										
											2019-06-01 00:56:07 +09:00
										 |  |  |                    .catch(function(error: any) { | 
					
						
							|  |  |  |                      expect(error.name).toEqual('AbortError'); | 
					
						
							|  |  |  |                      expect(logs).toEqual([ | 
					
						
							|  |  |  |                        'scheduleTask:fetch:macroTask', 'cancelTask:fetch:macroTask', | 
					
						
							|  |  |  |                        'scheduleTask:Promise.then:microTask', 'invokeTask:Promise.then:microTask', | 
					
						
							|  |  |  |                        'scheduleTask:Promise.then:microTask', 'invokeTask:Promise.then:microTask', | 
					
						
							|  |  |  |                        'scheduleTask:Promise.then:microTask', 'invokeTask:Promise.then:microTask' | 
					
						
							|  |  |  |                      ]); | 
					
						
							|  |  |  |                      done(); | 
					
						
							|  |  |  |                    }); | 
					
						
							|  |  |  |                abort.abort(); | 
					
						
							|  |  |  |              }); | 
					
						
							|  |  |  |            })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         it('cancel fetchTask should trigger abort', | 
					
						
							|  |  |  |            ifEnvSupportsWithDone('AbortController', (done: DoneFn) => { | 
					
						
							| 
									
										
										
										
											2019-11-09 20:36:22 +02:00
										 |  |  |              if (isSafari()) { | 
					
						
							| 
									
										
										
										
											2019-06-01 00:56:07 +09:00
										 |  |  |                // safari not work with AbortController
 | 
					
						
							|  |  |  |                done(); | 
					
						
							|  |  |  |                return; | 
					
						
							|  |  |  |              } | 
					
						
							|  |  |  |              fetchZone.run(() => { | 
					
						
							|  |  |  |                const AbortController = global['AbortController']; | 
					
						
							|  |  |  |                const abort = new AbortController(); | 
					
						
							|  |  |  |                const signal = abort.signal; | 
					
						
							|  |  |  |                global['fetch']('/base/angular/packages/zone.js/test/assets/sample.json', {signal}) | 
					
						
							| 
									
										
										
										
											2020-04-13 16:40:21 -07:00
										 |  |  |                    .then(function(response: any) { | 
					
						
							|  |  |  |                      fail('should not get response'); | 
					
						
							|  |  |  |                    }) | 
					
						
							| 
									
										
										
										
											2019-06-01 00:56:07 +09:00
										 |  |  |                    .catch(function(error: any) { | 
					
						
							|  |  |  |                      expect(error.name).toEqual('AbortError'); | 
					
						
							|  |  |  |                      expect(logs).toEqual([ | 
					
						
							|  |  |  |                        'scheduleTask:fetch:macroTask', 'cancelTask:fetch:macroTask', | 
					
						
							|  |  |  |                        'scheduleTask:Promise.then:microTask', 'invokeTask:Promise.then:microTask', | 
					
						
							|  |  |  |                        'scheduleTask:Promise.then:microTask', 'invokeTask:Promise.then:microTask', | 
					
						
							|  |  |  |                        'scheduleTask:Promise.then:microTask', 'invokeTask:Promise.then:microTask' | 
					
						
							|  |  |  |                      ]); | 
					
						
							|  |  |  |                      done(); | 
					
						
							|  |  |  |                    }); | 
					
						
							|  |  |  |                fetchTask.zone.cancelTask(fetchTask); | 
					
						
							|  |  |  |              }); | 
					
						
							|  |  |  |            })); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     })); |