@@ -40,6 +40,8 @@ import {EMPTY, Observable, from} from 'rxjs';
4040
4141import { HttpInterceptorFn , resetFetchBackendWarningFlag } from '../src/interceptor' ;
4242import {
43+ HttpFeature ,
44+ HttpFeatureKind ,
4345 provideHttpClient ,
4446 withFetch ,
4547 withInterceptors ,
@@ -339,94 +341,107 @@ describe('provideHttpClient', () => {
339341 } ) ;
340342
341343 describe ( 'withRequestsMadeViaParent()' , ( ) => {
342- it ( 'should have independent HTTP setups if not explicitly specified' , async ( ) => {
343- TestBed . configureTestingModule ( {
344- providers : [ provideHttpClient ( ) , provideHttpClientTesting ( ) ] ,
345- } ) ;
346-
347- const child = createEnvironmentInjector (
348- [
349- provideHttpClient ( ) ,
350- {
351- provide : XhrFactory ,
352- useValue : {
353- build : ( ) => {
354- throw new Error ( 'Request reached the "backend".' ) ;
344+ for ( const backend of [ 'fetch' , 'xhr' ] ) {
345+ describe ( `given '${ backend } ' backend` , ( ) => {
346+ const commonHttpFeatures : HttpFeature < HttpFeatureKind > [ ] = [ ] ;
347+ if ( backend === 'fetch' ) {
348+ commonHttpFeatures . push ( withFetch ( ) ) ;
349+ }
350+
351+ it ( 'should have independent HTTP setups if not explicitly specified' , async ( ) => {
352+ TestBed . configureTestingModule ( {
353+ providers : [ provideHttpClient ( ...commonHttpFeatures ) , provideHttpClientTesting ( ) ] ,
354+ } ) ;
355+
356+ const child = createEnvironmentInjector (
357+ [
358+ provideHttpClient ( ) ,
359+ {
360+ provide : XhrFactory ,
361+ useValue : {
362+ build : ( ) => {
363+ throw new Error ( 'Request reached the "backend".' ) ;
364+ } ,
365+ } ,
355366 } ,
356- } ,
357- } ,
358- ] ,
359- TestBed . inject ( EnvironmentInjector ) ,
360- ) ;
361-
362- // Because `child` is an entirely independent HTTP context, it is not connected to the
363- // HTTP testing backend from the parent injector, and requests attempted via the child's
364- // `HttpClient` will fail.
365- await expectAsync ( child . get ( HttpClient ) . get ( '/test' ) . toPromise ( ) ) . toBeRejected ( ) ;
366- } ) ;
367-
368- it ( 'should connect child to parent configuration if specified' , ( ) => {
369- TestBed . configureTestingModule ( {
370- providers : [ provideHttpClient ( ) , provideHttpClientTesting ( ) ] ,
371- } ) ;
372-
373- const child = createEnvironmentInjector (
374- [ provideHttpClient ( withRequestsMadeViaParent ( ) ) ] ,
375- TestBed . inject ( EnvironmentInjector ) ,
376- ) ;
377-
378- // `child` is now to the parent HTTP context and therefore the testing backend, and so a
379- // request made via its `HttpClient` can be made.
380- child . get ( HttpClient ) . get ( '/test' , { responseType : 'text' } ) . subscribe ( ) ;
381- const req = TestBed . inject ( HttpTestingController ) . expectOne ( '/test' ) ;
382- req . flush ( '' ) ;
383- } ) ;
384-
385- it ( 'should include interceptors from both parent and child contexts' , ( ) => {
386- TestBed . configureTestingModule ( {
387- providers : [
388- provideHttpClient ( withInterceptors ( [ makeLiteralTagInterceptorFn ( 'parent' ) ] ) ) ,
389- provideHttpClientTesting ( ) ,
390- ] ,
391- } ) ;
367+ ] ,
368+ TestBed . inject ( EnvironmentInjector ) ,
369+ ) ;
370+
371+ // Because `child` is an entirely independent HTTP context, it is not connected to the
372+ // HTTP testing backend from the parent injector, and requests attempted via the child's
373+ // `HttpClient` will fail.
374+ await expectAsync ( child . get ( HttpClient ) . get ( '/test' ) . toPromise ( ) ) . toBeRejected ( ) ;
375+ } ) ;
392376
393- const child = createEnvironmentInjector (
394- [
395- provideHttpClient (
396- withRequestsMadeViaParent ( ) ,
397- withInterceptors ( [ makeLiteralTagInterceptorFn ( 'child' ) ] ) ,
398- ) ,
399- ] ,
400- TestBed . inject ( EnvironmentInjector ) ,
401- ) ;
377+ it ( 'should connect child to parent configuration if specified' , ( ) => {
378+ TestBed . configureTestingModule ( {
379+ providers : [ provideHttpClient ( ...commonHttpFeatures ) , provideHttpClientTesting ( ) ] ,
380+ } ) ;
381+
382+ const child = createEnvironmentInjector (
383+ [ provideHttpClient ( withRequestsMadeViaParent ( ) ) ] ,
384+ TestBed . inject ( EnvironmentInjector ) ,
385+ ) ;
386+
387+ // `child` is now to the parent HTTP context and therefore the testing backend, and so a
388+ // request made via its `HttpClient` can be made.
389+ child . get ( HttpClient ) . get ( '/test' , { responseType : 'text' } ) . subscribe ( ) ;
390+ const req = TestBed . inject ( HttpTestingController ) . expectOne ( '/test' ) ;
391+ req . flush ( '' ) ;
392+ } ) ;
402393
403- child . get ( HttpClient ) . get ( '/test' , { responseType : 'text' } ) . subscribe ( ) ;
404- const req = TestBed . inject ( HttpTestingController ) . expectOne ( '/test' ) ;
405- expect ( req . request . headers . get ( 'X-Tag' ) ) . toEqual ( 'child,parent' ) ;
406- req . flush ( '' ) ;
407- } ) ;
394+ it ( 'should include interceptors from both parent and child contexts' , ( ) => {
395+ TestBed . configureTestingModule ( {
396+ providers : [
397+ provideHttpClient (
398+ ...commonHttpFeatures ,
399+ withInterceptors ( [ makeLiteralTagInterceptorFn ( 'parent' ) ] ) ,
400+ ) ,
401+ provideHttpClientTesting ( ) ,
402+ ] ,
403+ } ) ;
404+
405+ const child = createEnvironmentInjector (
406+ [
407+ provideHttpClient (
408+ withRequestsMadeViaParent ( ) ,
409+ withInterceptors ( [ makeLiteralTagInterceptorFn ( 'child' ) ] ) ,
410+ ) ,
411+ ] ,
412+ TestBed . inject ( EnvironmentInjector ) ,
413+ ) ;
414+
415+ child . get ( HttpClient ) . get ( '/test' , { responseType : 'text' } ) . subscribe ( ) ;
416+ const req = TestBed . inject ( HttpTestingController ) . expectOne ( '/test' ) ;
417+ expect ( req . request . headers . get ( 'X-Tag' ) ) . toEqual ( 'child,parent' ) ;
418+ req . flush ( '' ) ;
419+ } ) ;
408420
409- it ( 'should be able to connect to a legacy-provided HttpClient context' , ( ) => {
410- TestBed . configureTestingModule ( {
411- imports : [ HttpClientTestingModule ] ,
412- providers : [ provideLegacyInterceptor ( 'parent' ) ] ,
421+ it ( 'should be able to connect to a legacy-provided HttpClient context' , ( ) => {
422+ TestBed . configureTestingModule ( {
423+ imports : [ HttpClientTestingModule ] ,
424+ providers : [ provideLegacyInterceptor ( 'parent' ) ] ,
425+ } ) ;
426+
427+ const child = createEnvironmentInjector (
428+ [
429+ provideHttpClient (
430+ ...commonHttpFeatures ,
431+ withRequestsMadeViaParent ( ) ,
432+ withInterceptors ( [ makeLiteralTagInterceptorFn ( 'child' ) ] ) ,
433+ ) ,
434+ ] ,
435+ TestBed . inject ( EnvironmentInjector ) ,
436+ ) ;
437+
438+ child . get ( HttpClient ) . get ( '/test' , { responseType : 'text' } ) . subscribe ( ) ;
439+ const req = TestBed . inject ( HttpTestingController ) . expectOne ( '/test' ) ;
440+ expect ( req . request . headers . get ( 'X-Tag' ) ) . toEqual ( 'child,parent' ) ;
441+ req . flush ( '' ) ;
442+ } ) ;
413443 } ) ;
414-
415- const child = createEnvironmentInjector (
416- [
417- provideHttpClient (
418- withRequestsMadeViaParent ( ) ,
419- withInterceptors ( [ makeLiteralTagInterceptorFn ( 'child' ) ] ) ,
420- ) ,
421- ] ,
422- TestBed . inject ( EnvironmentInjector ) ,
423- ) ;
424-
425- child . get ( HttpClient ) . get ( '/test' , { responseType : 'text' } ) . subscribe ( ) ;
426- const req = TestBed . inject ( HttpTestingController ) . expectOne ( '/test' ) ;
427- expect ( req . request . headers . get ( 'X-Tag' ) ) . toEqual ( 'child,parent' ) ;
428- req . flush ( '' ) ;
429- } ) ;
444+ }
430445 } ) ;
431446
432447 describe ( 'compatibility with Http NgModules' , ( ) => {
@@ -472,20 +487,33 @@ describe('provideHttpClient', () => {
472487 expect ( consoleWarnSpy . calls . count ( ) ) . toBe ( 0 ) ;
473488 } ) ;
474489
475- it ( 'withFetch should always override the backend' , ( ) => {
490+ it ( `'withFetch' should not override provided backend` , ( ) => {
491+ class CustomBackendExtends extends HttpXhrBackend { }
492+
476493 TestBed . resetTestingModule ( ) ;
477494 TestBed . configureTestingModule ( {
478495 providers : [
479496 provideHttpClient ( withFetch ( ) ) ,
480- // This emulates a situation when `provideHttpClient()` is used
481- // later in a different part of an app. We want to make sure that
482- // the `FetchBackend` is enabled in that case as well.
483- { provide : HttpBackend , useClass : HttpXhrBackend } ,
497+ { provide : HttpBackend , useClass : CustomBackendExtends } ,
484498 ] ,
485499 } ) ;
486500
487- const handler = TestBed . inject ( HttpHandler ) ;
488- expect ( ( handler as any ) . backend ) . toBeInstanceOf ( FetchBackend ) ;
501+ const backend = TestBed . inject ( HttpBackend ) ;
502+ expect ( backend ) . toBeInstanceOf ( CustomBackendExtends ) ;
503+ } ) ;
504+
505+ it ( `fetch API should be used in child when 'withFetch' was used in parent injector` , ( ) => {
506+ TestBed . configureTestingModule ( {
507+ providers : [ provideHttpClient ( withFetch ( ) ) , provideHttpClientTesting ( ) ] ,
508+ } ) ;
509+
510+ const child = createEnvironmentInjector (
511+ [ provideHttpClient ( ) ] ,
512+ TestBed . inject ( EnvironmentInjector ) ,
513+ ) ;
514+
515+ const backend = child . get ( HttpBackend ) ;
516+ expect ( backend ) . toBeInstanceOf ( FetchBackend ) ;
489517 } ) ;
490518
491519 it ( 'should not warn if fetch is not configured when running in a browser' , ( ) => {
0 commit comments