license describe ( 'ProxySpec' , ( ) => { let ProxyZoneSpec ; let delegate ; let proxyZoneSpec ; let proxyZone ; beforeEach ( ( ) => { ProxyZoneSpec = ( Zone as any ) [ 'ProxyZoneSpec' ] ; expect ( typeof ProxyZoneSpec ) . toBe ( 'function' ) ; delegate = { name : 'delegate' } ; proxyZoneSpec = new ProxyZoneSpec ( delegate ) ; proxyZone = Zone . current . fork ( proxyZoneSpec ) ; } ) ; describe ( 'properties' , ( ) => { it ( 'should expose ProxyZone in the properties' , ( ) => { expect ( proxyZone . get ( 'ProxyZoneSpec' ) ) . toBe ( proxyZoneSpec ) ; } ) ; it ( 'should assert that it is in or out of ProxyZone' , ( ) => { let rootZone = Zone . current ; while ( rootZone . parent ) { rootZone = rootZone . parent ; } rootZone . run ( ( ) => { expect ( ( ) => ProxyZoneSpec . assertPresent ( ) ) . toThrow ( ) ; expect ( ProxyZoneSpec . isLoaded ( ) ) . toBe ( false ) ; expect ( ProxyZoneSpec . get ( ) ) . toBe ( undefined ) ; proxyZone . run ( ( ) => { expect ( ProxyZoneSpec . isLoaded ( ) ) . toBe ( true ) ; expect ( ( ) => ProxyZoneSpec . assertPresent ( ) ) . not . toThrow ( ) ; expect ( ProxyZoneSpec . get ( ) ) . toBe ( proxyZoneSpec ) ; } ) ; } ) ; } ) ; it ( 'should reset properties' , ( ) => { expect ( proxyZone . get ( 'myTestKey' ) ) . toBe ( undefined ) ; proxyZoneSpec . setDelegate ( { name : 'd1' , properties : { 'myTestKey' : 'myTestValue' } } ) ; expect ( proxyZone . get ( 'myTestKey' ) ) . toBe ( 'myTestValue' ) ; proxyZoneSpec . resetDelegate ( ) ; expect ( proxyZone . get ( 'myTestKey' ) ) . toBe ( undefined ) ; } ) ; } ) ; describe ( 'delegate' , ( ) => { it ( 'should set/reset delegate' , ( ) => { const defaultDelegate = { name : 'defaultDelegate' } ; const otherDelegate = { name : 'otherDelegate' } ; const proxyZoneSpec = new ProxyZoneSpec ( defaultDelegate ) ; const proxyZone = Zone . current . fork ( proxyZoneSpec ) ; expect ( proxyZoneSpec . getDelegate ( ) ) . toEqual ( defaultDelegate ) ; proxyZoneSpec . setDelegate ( otherDelegate ) ; expect ( proxyZoneSpec . getDelegate ( ) ) . toEqual ( otherDelegate ) ; proxyZoneSpec . resetDelegate ( ) ; expect ( proxyZoneSpec . getDelegate ( ) ) . toEqual ( defaultDelegate ) ; } ) ; } ) ; describe ( 'forwarding' , ( ) => { beforeEach ( ( ) => { proxyZoneSpec = new ProxyZoneSpec ( ) ; proxyZone = Zone . current . fork ( proxyZoneSpec ) ; } ) ; it ( 'should fork' , ( ) => { const forkedZone = proxyZone . fork ( { name : 'fork' } ) ; expect ( forkedZone ) . not . toBe ( proxyZone ) ; expect ( forkedZone . name ) . toBe ( 'fork' ) ; let called = false ; proxyZoneSpec . setDelegate ( { name : '.' , onFork : ( parentZoneDelegate , currentZone , targetZone , zoneSpec ) => { expect ( currentZone ) . toBe ( proxyZone ) ; expect ( targetZone ) . toBe ( proxyZone ) , expect ( zoneSpec . name ) . toBe ( 'fork2' ) ; called = true ; } } ) ; proxyZone . fork ( { name : 'fork2' } ) ; expect ( called ) . toBe ( true ) ; } ) ; it ( 'should intercept' , ( ) => { const fn = ( a ) => a ; expect ( proxyZone . wrap ( fn , 'test' ) ( 'works' ) ) . toEqual ( 'works' ) ; proxyZoneSpec . setDelegate ( { name : '.' , onIntercept : ( parentZoneDelegate , currentZone , targetZone , delegate , source ) : Function => { return ( ) => '(works)' ; } } ) ; expect ( proxyZone . wrap ( fn , 'test' ) ( 'works' ) ) . toEqual ( '(works)' ) ; } ) ; it ( 'should invoke' , ( ) => { const fn = ( ) => 'works' ; expect ( proxyZone . run ( fn ) ) . toEqual ( 'works' ) ; proxyZoneSpec . setDelegate ( { name : '.' , onInvoke : ( parentZoneDelegate , currentZone , targetZone , delegate , applyThis , applyArgs , source ) => { return `(${ parentZoneDelegate . invoke ( targetZone , delegate , applyThis , applyArgs , source ) })` ; } } ) ; expect ( proxyZone . run ( fn ) ) . toEqual ( '(works)' ) ; } ) ; it ( 'should handleError' , ( ) => { const error = new Error ( 'TestError' ) ; const fn = ( ) => { throw error ; } ; expect ( ( ) => proxyZone . run ( fn ) ) . toThrow ( error ) ; proxyZoneSpec . setDelegate ( { name : '.' , onHandleError : ( parentZoneDelegate , currentZone , targetZone , error ) : boolean => { expect ( error ) . toEqual ( error ) ; return false ; } } ) ; expect ( ( ) => proxyZone . runGuarded ( fn ) ) . not . toThrow ( ) ; } ) ; it ( 'should Task' , ( ) => { const fn = ( ) : any => null ; const task = proxyZone . scheduleMacroTask ( 'test' , fn , { } , ( ) => null , ( ) => null ) ; expect ( task . source ) . toEqual ( 'test' ) ; proxyZone . cancelTask ( task ) ; } ) ; } ) ; describe ( 'delegateSpec change' , ( ) => { let log = [ ] ; beforeEach ( ( ) => { log = [ ] ; } ) ; it ( 'should trigger hasTask when invoke' , ( done ) => { const zoneSpec1 = { name : 'zone1' , onHasTask : ( delegate , curr , target , hasTask ) => { log . push ( `zoneSpec1 hasTask: ${ hasTask . microTask },${ hasTask . macroTask }` ) ; return delegate . hasTask ( target , hasTask ) ; } } ; const zoneSpec2 = { name : 'zone2' , onHasTask : ( delegate , curr , target , hasTask ) => { log . push ( `zoneSpec2 hasTask: ${ hasTask . microTask },${ hasTask . macroTask }` ) ; return delegate . hasTask ( target , hasTask ) ; } } ; proxyZoneSpec . setDelegate ( zoneSpec1 ) ; proxyZone . run ( ( ) => { setTimeout ( ( ) => { log . push ( 'timeout in zoneSpec1' ) ; } , 50 ) ; } ) ; proxyZoneSpec . setDelegate ( zoneSpec2 ) ; proxyZone . run ( ( ) => { Promise . resolve ( 1 ) . then ( ( ) => { log . push ( 'then in zoneSpec2' ) ; } ) ; } ) ; proxyZoneSpec . setDelegate ( null ) ; proxyZone . run ( ( ) => { setTimeout ( ( ) => { log . push ( 'timeout in null spec' ) ; } , 50 ) ; } ) ; proxyZoneSpec . setDelegate ( zoneSpec2 ) ; proxyZone . run ( ( ) => { Promise . resolve ( 1 ) . then ( ( ) => { log . push ( 'then in zoneSpec2' ) ; } ) ; } ) ; setTimeout ( ( ) => { expect ( log ) . toEqual ( [ 'zoneSpec1 hasTask: false,true' , 'zoneSpec2 hasTask: false,true' , 'zoneSpec2 hasTask: true,true' , 'zoneSpec2 hasTask: true,true' , 'then in zoneSpec2' , 'then in zoneSpec2' , 'zoneSpec2 hasTask: false,true' , 'timeout in zoneSpec1' , 'timeout in null spec' , 'zoneSpec2 hasTask: false,false' ] ) ; done ( ) ; } , 300 ) ; } ) ; } ) ; } ) ;