215 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			215 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
/**
 | 
						|
 * @license
 | 
						|
 * Copyright Google Inc. All Rights Reserved.
 | 
						|
 *
 | 
						|
 * 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;
 | 
						|
      beforeEach(() => {
 | 
						|
        testZone = Zone.current.fork({name: 'TestZone'});
 | 
						|
      });
 | 
						|
      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(
 | 
						|
                     function(response: any) {
 | 
						|
                       fail('should not success');
 | 
						|
                     },
 | 
						|
                     (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);
 | 
						|
            },
 | 
						|
            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);
 | 
						|
                },
 | 
						|
            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) => {
 | 
						|
             if (isSafari()) {
 | 
						|
               // 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})
 | 
						|
                   .then(function(response: any) {
 | 
						|
                     fail('should not get response');
 | 
						|
                   })
 | 
						|
                   .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) => {
 | 
						|
             if (isSafari()) {
 | 
						|
               // 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})
 | 
						|
                   .then(function(response: any) {
 | 
						|
                     fail('should not get response');
 | 
						|
                   })
 | 
						|
                   .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);
 | 
						|
             });
 | 
						|
           }));
 | 
						|
      });
 | 
						|
    }));
 |