UNPKG

ohayolibs

Version:

Ohayo is a set of essential modules for ohayojp.

464 lines (431 loc) 15 kB
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 '@ohayo/testing'; import { OhayoI18NService, OhayoI18NServiceFake, OHAYO_I18N_TOKEN, MenuService, SettingsService, TitleService } from '@ohayo/theme'; import { NzAffixComponent } from 'ng-zorro-antd/affix'; import { ReuseTabService } from '../reuse-tab/reuse-tab.service'; import { PageHeaderComponent } from './page-header.component'; import { PageHeaderModule } from './page-header.module'; class MockI18NServiceFake extends OhayoI18NServiceFake { fanyi(key: string): string { return key; } } describe('components: page-header', () => { let fixture: ComponentFixture<TestComponent>; let dl: DebugElement; let menuSrv: MenuService; let context: TestComponent; let router: Router; function genModule(other: { template?: string; providers?: any[]; created?: boolean }): void { const imports = [RouterTestingModule.withRoutes([{ path: '1-1/:name', component: TestComponent }]), PageHeaderModule]; 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: string, stauts: boolean = true): void { if (stauts) { expect(dl.query(By.css(cls))).not.toBeNull(); } else { expect(dl.query(By.css(cls))).toBeNull(); } } function checkValue(cls: string, value: any): void { const el = dl.query(By.css(cls)).nativeElement as HTMLElement; expect(el.textContent!.trim()).toBe(value); } afterEach(() => context.comp.ngOnDestroy()); describe('', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [RouterTestingModule.withRoutes([{ path: '1-1/:name', component: TestComponent }]), PageHeaderModule], 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: HTMLElement = 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: HTMLElement = dl.query(By.css('nz-breadcrumb-item:nth-child(3)')).nativeElement; expect(firstPath.innerText).not.toBe(secondPath.innerText); }); }); flush(); })); }); describe('[i18n]', () => { let i18n: OhayoI18NService; beforeEach(() => { TestBed.overrideProvider(OHAYO_I18N_TOKEN, { useFactory: () => new MockI18NServiceFake(), }); ({ fixture, dl, context } = createTestContext(TestI18nComponent)); i18n = TestBed.inject(OHAYO_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'; // tslint:disable-next-line:no-shadowed-variable 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: string) { } get title(): string { return ''; } } let titleSrv: TitleService; let reuseSrv: ReuseTabService; 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 { }