import { APP_BASE_HREF } from '@angular/common' ; import { Component , DebugElement , ViewChild } from '@angular/core' ; import { ComponentFixture , fakeAsync , flush , TestBed , tick } from '@angular/core/testing' ; import { By } from '@angular/platform-browser' ; import { Router } from '@angular/router' ; import { RouterTestingModule } from '@angular/router/testing' ; import { createTestContext } from '@delon/testing' ; import { AlainI18NService , AlainI18NServiceFake , AlainThemeModule , ALAIN_I18N_TOKEN , MenuService , SettingsService , TitleService } from '@delon/theme' ; import { NzAffixComponent } from 'ng-zorro-antd/affix' ; import { NzSafeAny } from 'ng-zorro-antd/core/types' ; import { ReuseTabService } from '../reuse-tab/reuse-tab.service' ; import { PageHeaderComponent } from './page-header.component' ; import { PageHeaderModule } from './page-header.module' ; class MockI18NServiceFake extends AlainI18NServiceFake { fanyi ( key ) { return key ; } } describe ( 'abc: page-header' , ( ) => { let fixture ; let dl ; let menuSrv ; let context ; let router ; function genModule ( other ) { const imports = [ RouterTestingModule . withRoutes ( [ { path : '1-1/:name' , component : TestComponent } ] ) , PageHeaderModule , AlainThemeModule ] ; const providers = [ { provide : APP_BASE_HREF , useValue : '/' } , SettingsService ] ; if ( other . providers && other . providers . length ) { providers . push ( ... other . providers ) ; } TestBed . configureTestingModule ( { imports , declarations : [ TestComponent ] , providers } ) ; if ( other . template ) TestBed . overrideTemplate ( TestComponent , other . template ) ; fixture = TestBed . createComponent ( TestComponent ) ; dl = fixture . debugElement ; context = fixture . componentInstance ; if ( other . created !== false ) fixture . detectChanges ( ) ; menuSrv = TestBed . inject < MenuService > ( MenuService ) ; router = TestBed . inject < Router > ( Router ) ; } function isExists ( cls , stauts = true ) { if ( stauts ) { expect ( dl . query ( By . css ( cls ) ) ) . not . toBeNull ( ) ; } else { expect ( dl . query ( By . css ( cls ) ) ) . toBeNull ( ) ; } } function checkValue ( cls , value ) { const el = dl . query ( By . css ( cls ) ) . nativeElement as HTMLElement ; expect ( el . textContent ! . trim ( ) ) . toBe ( value ) ; } describe ( '' , ( ) => { beforeEach ( ( ) => { TestBed . configureTestingModule ( { imports : [ RouterTestingModule . withRoutes ( [ { path : '1-1/:name' , component : TestComponent } ] ) , PageHeaderModule , AlainThemeModule ] , providers : [ { provide : APP_BASE_HREF , useValue : '/' } , SettingsService ] , declarations : [ TestComponent , TestAutoBreadcrumbComponent , TestI18nComponent ] } ) ; } ) ; describe ( '[property]' , ( ) => { beforeEach ( ( ) => { ( { fixture , dl , context } = createTestContext ( TestComponent ) ) ; menuSrv = TestBed . inject < MenuService > ( MenuService ) ; router = TestBed . inject < Router > ( Router ) ; fixture . detectChanges ( ) ; } ) ; describe ( '#title' , ( ) => { it ( 'with string' , ( ) => { isExists ( '.page-header__title' ) ; } ) ; it ( 'with null' , ( ) => { context . title = null ; fixture . detectChanges ( ) ; isExists ( '.page-header__title' , false ) ; } ) ; } ) ; [ 'breadcrumb' , 'logo' , 'action' , 'content' , 'extra' , 'tab' ] . forEach ( type => { it ( `#${ type }` , ( ) => isExists ( `.${ type }` ) ) ; } ) ; describe ( '#fixed' , ( ) => { beforeEach ( ( ) => { context . fixed = true ; fixture . detectChanges ( ) ; } ) ; it ( 'should working' , ( ) => { isExists ( 'nz-affix' , true ) ; } ) ; it ( 'should be update position when switch collapsed' , ( ) => { const srv = TestBed . inject ( SettingsService ) ; const affixComp = dl . query ( By . directive ( NzAffixComponent ) ) . injector . get < NzAffixComponent > ( NzAffixComponent , undefined ) ; spyOn ( affixComp , 'updatePosition' ) ; srv . setLayout ( 'collapsed' , true ) ; expect ( affixComp . updatePosition ) . toHaveBeenCalled ( ) ; } ) ; } ) ; it ( '#wide' , ( ) => { context . wide = true ; fixture . detectChanges ( ) ; isExists ( '.page-header__wide' ) ; } ) ; it ( '#loading' , ( ) => { context . loading = true ; fixture . detectChanges ( ) ; isExists ( '.ant-skeleton' ) ; } ) ; } ) ; describe ( '[generation breadcrumb]' , ( ) => { beforeEach ( ( ) => { ( { fixture , dl , context } = createTestContext ( TestAutoBreadcrumbComponent ) ) ; menuSrv = TestBed . inject < MenuService > ( MenuService ) ; router = TestBed . inject < Router > ( Router ) ; fixture . detectChanges ( ) ; menuSrv . add ( [ { text : 'root' , children : [ { text : '1-1' , link : '/1-1' , children : [ { text : '1-1-1' , link : '/1-1/1-1-1' } , { text : '1-1-2' , link : '/1-1/1-1-2' } ] } ] } ] ) ; } ) ; it ( 'should be' , ( ) => { spyOnProperty ( router , 'url' ) . and . returnValue ( '/1-1/1-1-2' ) ; context . home = '' ; context . autoBreadcrumb = true ; fixture . detectChanges ( ) ; expect ( dl . queryAll ( By . css ( 'nz-breadcrumb-item' ) ) . length ) . toBe ( 3 ) ; } ) ; it ( 'should be no breadcrumb when invalid url' , ( ) => { spyOnProperty ( router , 'url' ) . and . returnValue ( '/1-1/a-1-1-2' ) ; context . autoBreadcrumb = true ; fixture . detectChanges ( ) ; expect ( dl . queryAll ( By . css ( 'nz-breadcrumb-item' ) ) . length ) . toBe ( 0 ) ; } ) ; it ( 'should be hide breadcrumb' , ( ) => { menuSrv . add ( [ { text : 'root' , hideInBreadcrumb : true , children : [ { text : '1-1' , link : '/1-1' , children : [ { text : '1-1-1' , link : '/1-1/1-1-1' } , { text : '1-1-2' , link : '/1-1/1-1-2' } ] } ] } ] ) ; spyOnProperty ( router , 'url' ) . and . returnValue ( '/1-1/1-1-2' ) ; context . autoBreadcrumb = true ; fixture . detectChanges ( ) ; expect ( dl . queryAll ( By . css ( 'nz-breadcrumb-item' ) ) . length ) . toBe ( 2 ) ; } ) ; describe ( '#home' , ( ) => { it ( 'shoule be hide home' , ( ) => { spyOnProperty ( router , 'url' ) . and . returnValue ( '/1-1/1-1-2' ) ; context . home = '' ; context . autoBreadcrumb = true ; fixture . detectChanges ( ) ; expect ( dl . queryAll ( By . css ( 'nz-breadcrumb-item' ) ) . length ) . toBe ( 3 ) ; } ) ; } ) ; it ( 'shoule be different breadcrumb by paths' , fakeAsync ( ( ) => { context . home = '' ; context . autoBreadcrumb = true ; const urlSpy = spyOnProperty ( router , 'url' ) ; urlSpy . and . returnValue ( '/1-1/1-1-2' ) ; fixture . detectChanges ( ) ; const firstPath = dl . query ( By . css ( 'nz-breadcrumb-item:nth-child(3)' ) ) . nativeElement ; urlSpy . and . returnValue ( '/1-1/1-1-1' ) ; fixture . ngZone ! . run ( ( ) => { router . navigateByUrl ( '/1-1/1-1-1' ) ; fixture . whenStable ( ) . then ( ( ) => { fixture . detectChanges ( ) ; const secondPath = dl . query ( By . css ( 'nz-breadcrumb-item:nth-child(3)' ) ) . nativeElement ; expect ( firstPath . innerText ) . not . toBe ( secondPath . innerText ) ; } ) ; } ) ; flush ( ) ; } ) ) ; } ) ; describe ( '[i18n]' , ( ) => { let i18n ; beforeEach ( ( ) => { TestBed . overrideProvider ( ALAIN_I18N_TOKEN , { useFactory : ( ) => new MockI18NServiceFake ( { merge : ( ) => { } } as NzSafeAny ) } ) ; ( { fixture , dl , context } = createTestContext ( TestI18nComponent ) ) ; i18n = TestBed . inject ( ALAIN_I18N_TOKEN ) ; menuSrv = TestBed . inject < MenuService > ( MenuService ) ; router = TestBed . inject < Router > ( Router ) ; fixture . detectChanges ( ) ; } ) ; it ( 'should be refresh when i18n changed' , ( ) => { spyOn ( context . comp , 'refresh' ) ; expect ( context . comp . refresh ) . not . toHaveBeenCalled ( ) ; i18n . use ( 'en' , { } ) ; expect ( context . comp . refresh ) . toHaveBeenCalled ( ) ; } ) ; it ( 'in text' , ( ) => { menuSrv . add ( [ { text : 'root' , i18n : 'root-i18n' , children : [ { text : '1-1' , link : '/1-1' , children : [ { text : '1-1-1' , link : '/1-1/1-1-1' } , { text : '1-1-2' , link : '/1-1/1-1-2' } ] } ] } ] ) ; spyOnProperty ( router , 'url' ) . and . returnValue ( '/1-1/1-1-2' ) ; spyOn ( i18n , 'fanyi' ) ; expect ( i18n . fanyi ) . not . toHaveBeenCalled ( ) ; context . autoBreadcrumb = true ; fixture . detectChanges ( ) ; expect ( i18n . fanyi ) . toHaveBeenCalled ( ) ; } ) ; it ( 'in title' , ( ) => { const text = 'asdf' ; const i18n = 'i18n' ; context . title = null ; context . autoTitle = true ; context . autoBreadcrumb = true ; spyOn ( menuSrv , 'getPathByUrl' ) . and . returnValue ( [ { text , i18n } ] ) ; fixture . detectChanges ( ) ; checkValue ( '.page-header__title' , i18n ) ; } ) ; it ( 'in home' , ( ) => { menuSrv . add ( [ { text : 'root' , children : [ { text : '1-1' , link : '/1-1' , children : [ { text : '1-1-1' , link : '/1-1/1-1-1' } , { text : '1-1-2' , link : '/1-1/1-1-2' } ] } ] } ] ) ; context . autoBreadcrumb = true ; spyOnProperty ( router , 'url' ) . and . returnValue ( '/1-1/1-1-2' ) ; spyOn ( i18n , 'fanyi' ) ; context . home = 'home' ; context . homeI18n = 'homeI18n' ; context . autoBreadcrumb = true ; fixture . detectChanges ( ) ; expect ( i18n . fanyi ) . toHaveBeenCalled ( ) ; } ) ; } ) ; } ) ; describe ( '#title' , ( ) => { it ( 'should be custom title template' , ( ) => { genModule ( { template : `<page-header #comp [title]="titleTpl">
          <ng-template #titleTpl>
            <div class="custom-title">title</div>
          </ng-template>
        </page-header>` } ) ; expect ( dl . queryAll ( By . css ( '.custom-title' ) ) . length ) . toBe ( 1 ) ; } ) ; it ( 'should be refresh title when route changed of auto generate title' , fakeAsync ( ( ) => { genModule ( { created : false } ) ; context . title = null ; context . autoTitle = true ; menuSrv . add ( [ { text : '1' , link : '/1-1/p1' } , { text : '2' , link : '/1-1/p2' } ] ) ; const urlSpy = spyOnProperty ( router , 'url' ) ; urlSpy . and . returnValue ( '/1-1/p1' ) ; tick ( ) ; fixture . detectChanges ( ) ; checkValue ( '.page-header__title' , '1' ) ; urlSpy . and . returnValue ( '/1-1/p2' ) ; router . navigateByUrl ( '/1-1/p2' ) ; tick ( ) ; fixture . detectChanges ( ) ; checkValue ( '.page-header__title' , '2' ) ; } ) ) ; describe ( '[generateion title]' , ( ) => { beforeEach ( ( ) => { genModule ( { providers : [ { provide : TitleService , useFactory : ( ) => null } , { provide : ReuseTabService , useFactory : ( ) => null } ] } ) ; context . title = null ; context . autoTitle = true ; context . syncTitle = true ; } ) ; it ( 'should be auto generate title via menu data' , ( ) => { const text = 'asdf' ; spyOn ( menuSrv , 'getPathByUrl' ) . and . returnValue ( [ { text } ] ) ; fixture . detectChanges ( ) ; checkValue ( '.page-header__title' , text ) ; } ) ; } ) ; describe ( '[auto sync title]' , ( ) => { class MockTitle { setTitle = jasmine . createSpy ( ) ; } class MockReuse { set title ( _val ) { } get title ( ) : string { return '' ; } } let titleSrv ; let reuseSrv ; beforeEach ( ( ) => { genModule ( { providers : [ { provide : TitleService , useClass : MockTitle } , { provide : ReuseTabService , useClass : MockReuse } ] } ) ; titleSrv = TestBed . inject < TitleService > ( TitleService ) ; reuseSrv = TestBed . inject < ReuseTabService > ( ReuseTabService ) ; context . syncTitle = true ; } ) ; it ( 'should be auto sync title of document and result-tab' , ( ) => { const spyReuseTitle = spyOnProperty ( reuseSrv , 'title' , 'set' ) . and . callThrough ( ) ; fixture . detectChanges ( ) ; context . comp . inited = false ; context . comp . refresh ( ) ; expect ( titleSrv . setTitle ) . toHaveBeenCalled ( ) ; expect ( spyReuseTitle ) . toHaveBeenCalled ( ) ; } ) ; } ) ; } ) ; } ) ; class TestBaseComponent { @ ViewChild ( 'comp' , { static : true } ) comp ! : PageHeaderComponent ; title : string | null = '所属类目' ; autoBreadcrumb ? : boolean ; autoTitle ? : boolean ; syncTitle ? : boolean ; home ? : string ; homeLink ? : string ; homeI18n ? : string ; fixed ? : boolean ; loading = false ; wide = false ; } @ Component ( { template : `
    <page-header
      #comp
      [title]="title"
      [autoTitle]="autoTitle"
      [syncTitle]="syncTitle"
      [autoBreadcrumb]="autoBreadcrumb"
      [home]="home"
      [homeI18n]="homeI18n"
      [homeLink]="homeLink"
      [fixed]="fixed"
      [loading]="loading"
      [wide]="wide"
      [breadcrumb]="breadcrumb"
      [logo]="logo"
      [action]="action"
      [extra]="extra"
      [content]="content"
      [tab]="tab"
    >
      <ng-template #breadcrumb><div class="breadcrumb">面包屑</div></ng-template>
      <ng-template #logo><div class="logo">logo</div></ng-template>
      <ng-template #action><div class="action">action</div></ng-template>
      <ng-template #content><div class="content">content</div></ng-template>
      <ng-template #extra><div class="extra">extra</div></ng-template>
      <ng-template #tab><div class="tab">tab</div></ng-template>
    </page-header>
  ` } ) class TestComponent extends TestBaseComponent { } @ Component ( { template : `
    <page-header
      #comp
      [title]="title"
      [home]="home"
      [homeI18n]="homeI18n"
      [autoBreadcrumb]="autoBreadcrumb"
    ></page-header>
  ` } ) class TestAutoBreadcrumbComponent extends TestBaseComponent { } @ Component ( { template : `
    <page-header
      #comp
      [title]="title"
      [home]="home"
      [homeI18n]="homeI18n"
      [homeLink]="homeLink"
      [autoBreadcrumb]="autoBreadcrumb"
    ></page-header>
  ` } ) class TestI18nComponent extends TestBaseComponent { }