import { HttpClient , HttpEvent , HttpHandler , HttpHeaders , HttpInterceptor , HttpRequest , HttpResponse , HTTP_INTERCEPTORS } from '@angular/common/http' ; import { HttpClientTestingModule , HttpTestingController } from '@angular/common/http/testing' ; import { Component , NgModule , Type } from '@angular/core' ; import { fakeAsync , TestBed , tick } from '@angular/core/testing' ; import { Router , RouterModule } from '@angular/router' ; import { RouterTestingModule } from '@angular/router/testing' ; import { Observable } from 'rxjs' ; import { mapTo } from 'rxjs/operators' ; import * as Mock from 'mockjs' ; import { AlainMockConfig , ALAIN_CONFIG } from '@delon/util/config' ; import { MockRequest } from './interface' ; import { DelonMockModule } from './mock.module' ; import { MockStatusError } from './status.error' ; const USER_LIST = { users : [ 1 , 2 ] , a : 0 } ; const DATA = { USERS : { 'GET /users' : USER_LIST , '/users/1' : Mock . mock ( { id : 1 , 'rank|3' : '★★★' } ) , '/users/:id' : ( req ) => req . params , '/array' : [ 1 , 2 ] , '/fn/queryString' : ( req ) => req . queryString , '/fn/header' : ( req ) => req . headers , '/HttpResponse' : ( ) => new HttpResponse ( { body : 'Body' , headers : new HttpHeaders ( { token : '1' } ) } ) , 'POST /fn/body' : ( req ) => req . body , 'POST /users/1' : { uid : 1 , action : 'add' } , '/404' : ( ) => { throw new MockStatusError ( 404 ) ; } , '/500' : ( ) => { throw new Error ( '500' ) ; } } } ; let otherRes = new HttpResponse ( ) ; class OtherInterceptor implements HttpInterceptor { intercept ( req , next ) { return next . handle ( req . clone ( ) ) . pipe ( mapTo ( otherRes ) ) ; } } describe ( 'mock: interceptor' , ( ) => { let http ; let httpMock ; function genModule ( data , options , imports = [ ] , spyConsole = true , providers ? ) { TestBed . configureTestingModule ( { declarations : [ RootComponent ] , imports : [ HttpClientTestingModule , RouterTestingModule . withRoutes ( [ { path : 'lazy' , loadChildren : jasmine . createSpy ( 'expected' ) } ] ) , DelonMockModule . forRoot ( { data } ) ] . concat ( imports ) , providers : ( [ { provide : ALAIN_CONFIG , useValue : { mock : options } } ] as any [ ] ) . concat ( providers || [ ] ) } ) ; http = TestBed . inject < HttpClient > ( HttpClient ) ; httpMock = TestBed . inject ( HttpTestingController as Type < HttpTestingController > ) ; if ( spyConsole ) { spyOn ( console , 'log' ) ; spyOn ( console , 'warn' ) ; } } describe ( '[default]' , ( ) => { beforeEach ( ( ) => genModule ( DATA , { executeOtherInterceptors : false , delay : 1 } ) ) ; it ( 'should be init' , ( done ) => { http . get ( '/users' ) . subscribe ( ( res ) => { expect ( res ) . not . toBeNull ( ) ; expect ( res . users ) . not . toBeNull ( ) ; expect ( res . users . length ) . toBe ( DATA . USERS [ 'GET /users' ] . users . length ) ; done ( ) ; } ) ; } ) ; it ( 'should response array' , ( done ) => { http . get ( '/array' ) . subscribe ( ( res ) => { expect ( res ) . not . toBeNull ( ) ; expect ( Array . isArray ( res ) ) . toBe ( true ) ; done ( ) ; } ) ; } ) ; it ( 'should response via callback' , ( done ) => { const key = '/fn/queryString' ; http . get ( key , { params : { pi : '1' } } ) . subscribe ( ( res ) => { expect ( res ) . not . toBeNull ( ) ; expect ( res . pi ) . toBe ( '1' ) ; done ( ) ; } ) ; } ) ; it ( 'should be get the default querystring' , ( done ) => { const key = '/fn/queryString?a=1' ; http . get ( key ) . subscribe ( ( res ) => { expect ( res . a ) . toBe ( '1' ) ; done ( ) ; } ) ; } ) ; it ( 'should return route params' , ( done ) => { const key = '/users/2' ; http . get ( key ) . subscribe ( ( res ) => { expect ( res ) . not . toBeNull ( ) ; expect ( res . id ) . toBe ( '2' ) ; done ( ) ; } ) ; } ) ; it ( 'should return body' , ( done ) => { const key = '/fn/body' ; http . post ( key , { token : 'asdf' } ) . subscribe ( ( res ) => { expect ( res ) . not . toBeNull ( ) ; expect ( res . token ) . toBe ( 'asdf' ) ; done ( ) ; } ) ; } ) ; it ( 'should return header' , ( done ) => { const key = '/fn/header' ; http . get ( key , { headers : { token : 'asdf' } } ) . subscribe ( ( res ) => { expect ( res ) . not . toBeNull ( ) ; expect ( res . token ) . toBe ( 'asdf' ) ; done ( ) ; } ) ; } ) ; it ( 'should return HttpResponse' , ( done ) => { const key = '/HttpResponse' ; http . get ( key , { observe : 'response' } ) . subscribe ( ( res ) => { expect ( res ) . not . toBeNull ( ) ; expect ( res . body ) . toBe ( 'Body' ) ; expect ( res . headers . get ( 'token' ) ) . toBe ( '1' ) ; done ( ) ; } ) ; } ) ; it ( 'should response HttpStatus: 404' , ( done ) => { http . get ( '/404' ) . subscribe ( { next : ( ) => { expect ( false ) . toBe ( true ) ; done ( ) ; } , error : ( ) => { expect ( true ) . toBe ( true ) ; done ( ) ; } } ) ; } ) ; it ( 'muse be use MockStatusError to throw status error' , ( done ) => { http . get ( '/500' ) . subscribe ( { next : ( ) => { expect ( false ) . toBe ( true ) ; done ( ) ; } , error : ( ) => { expect ( true ) . toBe ( true ) ; done ( ) ; } } ) ; } ) ; it ( 'should request POST' , ( done ) => { http . post ( '/users/1' , { data : true } , { observe : 'response' } ) . subscribe ( ( res ) => { expect ( res . body ) . not . toBeNull ( ) ; expect ( res . body . uid ) . toBe ( 1 ) ; expect ( res . body . action ) . toBe ( 'add' ) ; done ( ) ; } ) ; } ) ; it ( 'should normal request if non-mock url' , ( done ) => { http . get ( '/non-mock' , { responseType : 'text' } ) . subscribe ( value => { expect ( value ) . toBe ( 'ok!' ) ; done ( ) ; } ) ; httpMock . expectOne ( '/non-mock' ) . flush ( 'ok!' ) ; } ) ; it ( 'should be array of queryString' , ( done ) => { const key = '/fn/queryString?a=1&b=1&b=2&b=3' ; http . get ( key ) . subscribe ( ( res ) => { expect ( Array . isArray ( res . b ) ) . toBe ( true ) ; expect ( + res . b [ 0 ] ) . toBe ( 1 ) ; expect ( + res . b [ 1 ] ) . toBe ( 2 ) ; done ( ) ; } ) ; } ) ; } ) ; describe ( '[disabled log]' , ( ) => { it ( 'with request' , ( done ) => { genModule ( DATA , { delay : 1 , log : false } ) ; http . get ( '/users' ) . subscribe ( ( ) => { expect ( console . log ) . not . toHaveBeenCalled ( ) ; done ( ) ; } ) ; } ) ; it ( 'with error request' , ( done ) => { genModule ( DATA , { delay : 1 , log : false } ) ; http . get ( '/404' ) . subscribe ( { next : ( ) => { expect ( false ) . toBe ( true ) ; done ( ) ; } , error : ( ) => { expect ( console . log ) . not . toHaveBeenCalled ( ) ; expect ( true ) . toBe ( true ) ; done ( ) ; } } ) ; } ) ; } ) ; describe ( '[lazy module]' , ( ) => { beforeEach ( ( ) => genModule ( DATA , { delay : 1 } ) ) ; it ( 'should work' , fakeAsync ( ( ) => { @ Component ( { selector : 'lazy' , template : '<router-outlet></router-outlet>' } ) class LayoutComponent { } @ Component ( { selector : 'child' , template : 'length-{{res.users.length}}' } ) class ChildComponent { res : any = { } ; constructor ( HTTP ) { HTTP . get ( '/users' ) . subscribe ( res => ( this . res = res ) ) ; } } @ NgModule ( { declarations : [ LayoutComponent , ChildComponent ] , imports : [ DelonMockModule . forChild ( ) , RouterModule . forChild ( [ { path : 'child' , component : ChildComponent } ] ) ] } ) class LazyModule { } const fixture = TestBed . createComponent ( RootComponent ) ; fixture . detectChanges ( ) ; const router = TestBed . inject < Router > ( Router ) ; router . resetConfig ( [ { path : 'lazy' , loadChildren : ( ) => LazyModule } ] ) ; router . navigateByUrl ( `/lazy/child` ) ; tick ( 500 ) ; fixture . detectChanges ( ) ; const text = ( fixture . nativeElement as HTMLElement ) . textContent ; expect ( text ) . toContain ( 'length-2' ) ; } ) ) ; } ) ; describe ( '[executeOtherInterceptors]' , ( ) => { beforeEach ( ( ) => { genModule ( DATA , { delay : 1 , executeOtherInterceptors : true } , [ ] , true , [ { provide : HTTP_INTERCEPTORS , useClass : OtherInterceptor , multi : true } ] ) ; } ) ; it ( 'should working' , done => { otherRes = new HttpResponse ( { body : { a : 1 } } ) ; http . get ( '/users' ) . subscribe ( ( res ) => { expect ( res ) . not . toBeNull ( ) ; expect ( res . a ) . toBe ( 1 ) ; done ( ) ; } ) ; } ) ; } ) ; } ) ; @ Component ( { selector : 'root-cmp' , template : ` <router-outlet></router-outlet> ` } ) class RootComponent { }