mirror of https://github.com/abpframework/abp.git
committed by
GitHub
15 changed files with 504 additions and 84 deletions
@ -0,0 +1,49 @@ |
|||||
|
import { LocalizationPipe } from '@abp/ng.core'; |
||||
|
import { Directive } from '@angular/core'; |
||||
|
import { Router } from '@angular/router'; |
||||
|
import { createComponentFactory, Spectator, SpyObject } from '@ngneat/spectator/jest'; |
||||
|
import { Store } from '@ngxs/store'; |
||||
|
import { BreadcrumbComponent } from '../components/breadcrumb/breadcrumb.component'; |
||||
|
|
||||
|
@Directive({ |
||||
|
// tslint:disable-next-line: directive-selector
|
||||
|
selector: '[routerLink], [routerLinkActive]', |
||||
|
}) |
||||
|
class DummyRouterLinkDirective {} |
||||
|
|
||||
|
describe('BreadcrumbComponent', () => { |
||||
|
let spectator: Spectator<BreadcrumbComponent>; |
||||
|
let store: SpyObject<Store>; |
||||
|
const createComponent = createComponentFactory({ |
||||
|
component: BreadcrumbComponent, |
||||
|
mocks: [Store, Router], |
||||
|
imports: [], |
||||
|
declarations: [LocalizationPipe, DummyRouterLinkDirective], |
||||
|
detectChanges: false, |
||||
|
}); |
||||
|
|
||||
|
beforeEach(() => { |
||||
|
spectator = createComponent(); |
||||
|
store = spectator.get(Store); |
||||
|
}); |
||||
|
|
||||
|
it('should display the breadcrumb', () => { |
||||
|
const router = spectator.get(Router); |
||||
|
(router as any).url = '/identity/users'; |
||||
|
store.selectSnapshot.mockReturnValueOnce({ LeptonLayoutState: {} }); |
||||
|
store.selectSnapshot.mockReturnValueOnce({ |
||||
|
name: 'Identity', |
||||
|
children: [{ name: 'Users', path: 'users' }], |
||||
|
}); |
||||
|
// for abpLocalization
|
||||
|
store.selectSnapshot.mockReturnValueOnce('Identity'); |
||||
|
store.selectSnapshot.mockReturnValueOnce('Users'); |
||||
|
spectator.detectChanges(); |
||||
|
|
||||
|
expect(spectator.component.segments).toEqual(['Identity', 'Users']); |
||||
|
const elements = spectator.queryAll('li'); |
||||
|
expect(elements).toHaveLength(3); |
||||
|
expect(elements[1]).toHaveText('Identity'); |
||||
|
expect(elements[2]).toHaveText('Users'); |
||||
|
}); |
||||
|
}); |
||||
@ -0,0 +1,126 @@ |
|||||
|
import { createHostFactory, SpectatorHost } from '@ngneat/spectator/jest'; |
||||
|
import { ChartComponent } from '../components'; |
||||
|
import { chartJsLoaded$ } from '../utils/widget-utils'; |
||||
|
import { ReplaySubject } from 'rxjs'; |
||||
|
import * as widgetUtils from '../utils/widget-utils'; |
||||
|
// import 'chart.js';
|
||||
|
declare const Chart; |
||||
|
|
||||
|
Object.defineProperty(window, 'getComputedStyle', { |
||||
|
value: () => ({ |
||||
|
getPropertyValue: prop => { |
||||
|
return ''; |
||||
|
}, |
||||
|
}), |
||||
|
}); |
||||
|
|
||||
|
describe('ChartComponent', () => { |
||||
|
let spectator: SpectatorHost<ChartComponent>; |
||||
|
const createHost = createHostFactory({ component: ChartComponent }); |
||||
|
|
||||
|
beforeEach(() => { |
||||
|
(widgetUtils as any).chartJsLoaded$ = new ReplaySubject(1); |
||||
|
spectator = createHost('<abp-chart [data]="data" type="polarArea"></abp-chart>', { |
||||
|
hostProps: { |
||||
|
data: { |
||||
|
datasets: [ |
||||
|
{ |
||||
|
data: [11], |
||||
|
backgroundColor: ['#FF6384'], |
||||
|
label: 'My dataset', |
||||
|
}, |
||||
|
], |
||||
|
labels: ['Red'], |
||||
|
}, |
||||
|
}, |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
test('should throw error when chart.js is not loaded', () => { |
||||
|
try { |
||||
|
spectator.component.testChartJs(); |
||||
|
} catch (error) { |
||||
|
expect(error.message).toContain('Chart is not found'); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
test('should have a success class by default', async done => { |
||||
|
await import('chart.js'); |
||||
|
|
||||
|
chartJsLoaded$.next(); |
||||
|
setTimeout(() => { |
||||
|
expect(spectator.component.chart).toBeTruthy(); |
||||
|
done(); |
||||
|
}, 0); |
||||
|
}); |
||||
|
|
||||
|
describe('#reinit', () => { |
||||
|
it('should call the destroy method', done => { |
||||
|
chartJsLoaded$.next(); |
||||
|
const spy = jest.spyOn(spectator.component.chart, 'destroy'); |
||||
|
spectator.setHostInput({ |
||||
|
data: { |
||||
|
datasets: [ |
||||
|
{ |
||||
|
data: [12], |
||||
|
label: 'My dataset', |
||||
|
}, |
||||
|
], |
||||
|
labels: ['Red'], |
||||
|
}, |
||||
|
}); |
||||
|
spectator.detectChanges(); |
||||
|
setTimeout(() => { |
||||
|
expect(spy).toHaveBeenCalled(); |
||||
|
done(); |
||||
|
}, 0); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
describe('#refresh', () => { |
||||
|
it('should call the update method', done => { |
||||
|
chartJsLoaded$.next(); |
||||
|
const spy = jest.spyOn(spectator.component.chart, 'update'); |
||||
|
spectator.component.refresh(); |
||||
|
setTimeout(() => { |
||||
|
expect(spy).toHaveBeenCalled(); |
||||
|
done(); |
||||
|
}, 0); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
describe('#generateLegend', () => { |
||||
|
it('should call the generateLegend method', done => { |
||||
|
chartJsLoaded$.next(); |
||||
|
const spy = jest.spyOn(spectator.component.chart, 'generateLegend'); |
||||
|
spectator.component.generateLegend(); |
||||
|
setTimeout(() => { |
||||
|
expect(spy).toHaveBeenCalled(); |
||||
|
done(); |
||||
|
}, 0); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
describe('#onCanvasClick', () => { |
||||
|
it('should emit the onDataSelect', done => { |
||||
|
spectator.component.onDataSelect.subscribe(() => { |
||||
|
done(); |
||||
|
}); |
||||
|
|
||||
|
chartJsLoaded$.next(); |
||||
|
jest.spyOn(spectator.component.chart, 'getElementAtEvent').mockReturnValue([document.createElement('div')]); |
||||
|
spectator.click('canvas'); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
describe('#base64Image', () => { |
||||
|
it('should return the base64 image', done => { |
||||
|
chartJsLoaded$.next(); |
||||
|
|
||||
|
setTimeout(() => { |
||||
|
expect(spectator.component.base64Image).toContain('base64'); |
||||
|
done(); |
||||
|
}, 0); |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
@ -0,0 +1,36 @@ |
|||||
|
import { SpectatorHost, createHostFactory } from '@ngneat/spectator/jest'; |
||||
|
import { ErrorComponent } from '../components/error/error.component'; |
||||
|
import { LocalizationPipe } from '@abp/ng.core'; |
||||
|
import { Store } from '@ngxs/store'; |
||||
|
import { Renderer2, ElementRef } from '@angular/core'; |
||||
|
|
||||
|
describe('ErrorComponent', () => { |
||||
|
let spectator: SpectatorHost<ErrorComponent>; |
||||
|
const createHost = createHostFactory({ |
||||
|
component: ErrorComponent, |
||||
|
declarations: [LocalizationPipe], |
||||
|
mocks: [Store], |
||||
|
providers: [ |
||||
|
{ provide: Renderer2, useValue: { removeChild: () => null } }, |
||||
|
{ provide: ElementRef, useValue: { nativeElement: document.createElement('div') } }, |
||||
|
], |
||||
|
}); |
||||
|
|
||||
|
beforeEach(() => (spectator = createHost('<abp-error></abp-error>'))); |
||||
|
|
||||
|
describe('#destroy', () => { |
||||
|
it('should remove the dom', () => { |
||||
|
const renderer = spectator.get(Renderer2); |
||||
|
const rendererSpy = jest.spyOn(renderer, 'removeChild'); |
||||
|
spectator.component.renderer = renderer; |
||||
|
|
||||
|
const elementRef = spectator.get(ElementRef); |
||||
|
spectator.component.elementRef = elementRef; |
||||
|
spectator.component.host = spectator.hostComponent; |
||||
|
|
||||
|
spectator.click('button#abp-close-button'); |
||||
|
spectator.detectChanges(); |
||||
|
expect(rendererSpy).toHaveBeenCalledWith(spectator.hostComponent, elementRef.nativeElement); |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
@ -0,0 +1,92 @@ |
|||||
|
import { Router, RouteReuseStrategy, NavigationStart, NavigationEnd, NavigationError } from '@angular/router'; |
||||
|
import { createHostFactory, SpectatorHost, SpyObject } from '@ngneat/spectator/jest'; |
||||
|
import { Actions, NgxsModule, Store } from '@ngxs/store'; |
||||
|
import { Subject, Subscription, Observable, Subscriber, timer } from 'rxjs'; |
||||
|
import { LoaderBarComponent } from '../components/loader-bar/loader-bar.component'; |
||||
|
import { StartLoader, StopLoader } from '@abp/ng.core'; |
||||
|
import { HttpRequest } from '@angular/common/http'; |
||||
|
|
||||
|
describe('LoaderBarComponent', () => { |
||||
|
let spectator: SpectatorHost<LoaderBarComponent>; |
||||
|
let router: SpyObject<Router>; |
||||
|
const events$ = new Subject(); |
||||
|
|
||||
|
const createHost = createHostFactory({ |
||||
|
component: LoaderBarComponent, |
||||
|
mocks: [Router], |
||||
|
imports: [NgxsModule.forRoot()], |
||||
|
detectChanges: false, |
||||
|
}); |
||||
|
|
||||
|
beforeEach(() => { |
||||
|
spectator = createHost('<abp-loader-bar></abp-loader-bar>'); |
||||
|
spectator.component.intervalPeriod = 1; |
||||
|
spectator.component.stopDelay = 1; |
||||
|
router = spectator.get(Router); |
||||
|
(router as any).events = events$; |
||||
|
}); |
||||
|
|
||||
|
it('should initial variable values are correct', () => { |
||||
|
spectator.component.interval = new Subscription(); |
||||
|
expect(spectator.component.containerClass).toBe('abp-loader-bar'); |
||||
|
expect(spectator.component.color).toBe('#77b6ff'); |
||||
|
}); |
||||
|
|
||||
|
it('should increase the progressLevel maximum 10 point when value is 0', done => { |
||||
|
spectator.detectChanges(); |
||||
|
spectator.get(Store).dispatch(new StartLoader(new HttpRequest('GET', 'test'))); |
||||
|
setTimeout(() => { |
||||
|
expect(spectator.component.progressLevel > 0 && spectator.component.progressLevel < 10).toBeTruthy(); |
||||
|
done(); |
||||
|
}, 2); |
||||
|
}); |
||||
|
|
||||
|
it('should be interval unsubscribed', done => { |
||||
|
spectator.detectChanges(); |
||||
|
spectator.get(Store).dispatch(new StartLoader(new HttpRequest('GET', 'test'))); |
||||
|
expect(spectator.component.interval.closed).toBe(false); |
||||
|
|
||||
|
timer(400).subscribe(() => { |
||||
|
expect(spectator.component.interval.closed).toBe(true); |
||||
|
done(); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
it('should start and stop the loading with navigation', done => { |
||||
|
spectator.detectChanges(); |
||||
|
(router as any).events.next(new NavigationStart(1, 'test')); |
||||
|
expect(spectator.component.interval.closed).toBe(false); |
||||
|
|
||||
|
(router as any).events.next(new NavigationEnd(1, 'test', 'test')); |
||||
|
(router as any).events.next(new NavigationError(1, 'test', 'test')); |
||||
|
expect(spectator.component.progressLevel).toBe(100); |
||||
|
|
||||
|
timer(2).subscribe(() => { |
||||
|
expect(spectator.component.progressLevel).toBe(0); |
||||
|
done(); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
it('should stop the loading with navigation', done => { |
||||
|
spectator.detectChanges(); |
||||
|
(router as any).events.next(new NavigationStart(1, 'test')); |
||||
|
expect(spectator.component.interval.closed).toBe(false); |
||||
|
|
||||
|
spectator.get(Store).dispatch(new StopLoader(new HttpRequest('GET', 'test'))); |
||||
|
expect(spectator.component.progressLevel).toBe(100); |
||||
|
|
||||
|
timer(2).subscribe(() => { |
||||
|
expect(spectator.component.progressLevel).toBe(0); |
||||
|
done(); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
describe('#startLoading', () => { |
||||
|
it('should return when isLoading is true', done => { |
||||
|
spectator.detectChanges(); |
||||
|
(router as any).events.next(new NavigationStart(1, 'test')); |
||||
|
(router as any).events.next(new NavigationStart(1, 'test')); |
||||
|
done(); |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
@ -0,0 +1,126 @@ |
|||||
|
import { LocalizationPipe } from '@abp/ng.core'; |
||||
|
import { createHostFactory, SpectatorHost } from '@ngneat/spectator/jest'; |
||||
|
import { Store } from '@ngxs/store'; |
||||
|
import { MessageService } from 'primeng/components/common/messageservice'; |
||||
|
import { ToastModule } from 'primeng/toast'; |
||||
|
import { ConfirmationComponent, ModalComponent, ButtonComponent } from '../components'; |
||||
|
|
||||
|
describe('ModalComponent', () => { |
||||
|
let spectator: SpectatorHost<ModalComponent, { visible: boolean; busy: boolean; ngDirty: boolean }>; |
||||
|
let appearFn; |
||||
|
let disappearFn; |
||||
|
const createHost = createHostFactory({ |
||||
|
component: ModalComponent, |
||||
|
imports: [ToastModule], |
||||
|
declarations: [ConfirmationComponent, LocalizationPipe, ButtonComponent], |
||||
|
providers: [MessageService], |
||||
|
mocks: [Store], |
||||
|
}); |
||||
|
|
||||
|
beforeEach(() => { |
||||
|
appearFn = jest.fn(() => null); |
||||
|
disappearFn = jest.fn(() => null); |
||||
|
|
||||
|
spectator = createHost( |
||||
|
`<abp-modal [(visible)]="visible" [busy]="busy" [centered]="true" (appear)="appearFn()" (disappear)="disappearFn()" size="sm" modalClass="test">
|
||||
|
<ng-template #abpHeader> |
||||
|
<div class="header"></div> |
||||
|
</ng-template> |
||||
|
|
||||
|
<ng-template #abpBody> |
||||
|
<div class="body"> |
||||
|
<input [class.ng-dirty]="ngDirty"> |
||||
|
</div> |
||||
|
</ng-template> |
||||
|
|
||||
|
<ng-template #abpFooter> |
||||
|
<div class="footer"> |
||||
|
<button id="abp-close" #abpClose></button> |
||||
|
</div> |
||||
|
</ng-template> |
||||
|
<abp-button>Submit</abp-button> |
||||
|
<abp-confirmation></abp-confirmation> |
||||
|
</abp-modal> |
||||
|
`,
|
||||
|
{ |
||||
|
hostProps: { |
||||
|
visible: true, |
||||
|
busy: false, |
||||
|
ngDirty: true, |
||||
|
appearFn, |
||||
|
disappearFn, |
||||
|
}, |
||||
|
}, |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
it('should be created', () => { |
||||
|
expect(spectator.query('div.modal')).toBeTruthy(); |
||||
|
expect(spectator.query('div.modal-backdrop')).toBeTruthy(); |
||||
|
expect(spectator.query('div#abp-modal-dialog')).toBeTruthy(); |
||||
|
}); |
||||
|
|
||||
|
it('should works right the inputs', () => { |
||||
|
expect(spectator.query('div.test')).toBeTruthy(); |
||||
|
expect(spectator.query('div.modal-sm')).toBeTruthy(); |
||||
|
expect(spectator.query('div.modal-dialog-centered')).toBeTruthy(); |
||||
|
}); |
||||
|
|
||||
|
it('should emit the appear output', () => { |
||||
|
expect(appearFn).toHaveBeenCalled(); |
||||
|
}); |
||||
|
|
||||
|
it('should emit the disappear output', () => { |
||||
|
spectator.hostComponent.visible = false; |
||||
|
spectator.detectChanges(); |
||||
|
expect(disappearFn).toHaveBeenCalled(); |
||||
|
}); |
||||
|
|
||||
|
it('should open the confirmation popup and works correct', () => { |
||||
|
spectator.click('#abp-modal-close-button'); |
||||
|
expect(disappearFn).not.toHaveBeenCalled(); |
||||
|
|
||||
|
expect(spectator.query('p-toast')).toBeTruthy(); |
||||
|
spectator.click('button#cancel'); |
||||
|
expect(spectator.query('div.modal')).toBeTruthy(); |
||||
|
|
||||
|
spectator.click('#abp-modal-close-button'); |
||||
|
spectator.click('button#confirm'); |
||||
|
expect(spectator.query('div.modal')).toBeFalsy(); |
||||
|
expect(disappearFn).toHaveBeenCalled(); |
||||
|
}); |
||||
|
|
||||
|
it('should close with the abpClose', done => { |
||||
|
spectator.hostComponent.ngDirty = false; |
||||
|
spectator.detectChanges(); |
||||
|
setTimeout(() => { |
||||
|
spectator.click('#abp-close'); |
||||
|
expect(disappearFn).toHaveBeenCalled(); |
||||
|
done(); |
||||
|
}, 10); |
||||
|
}); |
||||
|
|
||||
|
it('should close with esc key', done => { |
||||
|
spectator.hostComponent.ngDirty = false; |
||||
|
spectator.detectChanges(); |
||||
|
setTimeout(() => { |
||||
|
spectator.dispatchKeyboardEvent(document.body, 'keyup', 'Escape'); |
||||
|
}, 0); |
||||
|
setTimeout(() => { |
||||
|
expect(spectator.component.visible).toBe(false); |
||||
|
done(); |
||||
|
}, 200); |
||||
|
}); |
||||
|
|
||||
|
it('should not close when busy is true', done => { |
||||
|
setTimeout(() => { |
||||
|
spectator.hostComponent.busy = true; |
||||
|
spectator.hostComponent.ngDirty = false; |
||||
|
spectator.detectChanges(); |
||||
|
spectator.click('#abp-modal-close-button'); |
||||
|
expect(disappearFn).not.toHaveBeenCalled(); |
||||
|
expect(spectator.component.abpSubmit.loading).toBe(true); |
||||
|
done(); |
||||
|
}, 0); |
||||
|
}); |
||||
|
}); |
||||
@ -1 +1,2 @@ |
|||||
import 'jest-preset-angular'; |
import 'jest-preset-angular'; |
||||
|
import 'jest-canvas-mock'; |
||||
|
|||||
Loading…
Reference in new issue