Browse Source

Merge pull request #6816 from abpframework/auto-merge/rel-4-1/11

Merge branch dev with rel-4.1
pull/6841/head
Mehmet Erim 6 years ago
committed by GitHub
parent
commit
45d694bcfa
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
  2. 10
      npm/ng-packs/packages/core/src/lib/interceptors/api.interceptor.ts
  3. 4
      npm/ng-packs/packages/core/src/lib/models/common.ts
  4. 44
      npm/ng-packs/packages/core/src/lib/services/http-wait.service.ts
  5. 3
      npm/ng-packs/packages/core/src/lib/services/index.ts
  6. 10
      npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts
  7. 41
      npm/ng-packs/packages/core/src/lib/services/resource-wait.service.ts
  8. 10
      npm/ng-packs/packages/core/src/lib/services/rest.service.ts
  9. 53
      npm/ng-packs/packages/core/src/lib/services/router-wait.service.ts
  10. 19
      npm/ng-packs/packages/core/src/lib/tests/api.interceptor.spec.ts
  11. 7
      npm/ng-packs/packages/core/src/lib/tests/lazy-load.service.spec.ts
  12. 8
      npm/ng-packs/packages/core/testing/src/lib/core-testing.module.ts
  13. 1
      npm/ng-packs/packages/core/testing/src/lib/services/index.ts
  14. 21
      npm/ng-packs/packages/core/testing/src/lib/services/mock-rest.service.ts
  15. 60
      npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts
  16. 7
      npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts
  17. 4
      npm/ng-packs/packages/theme-shared/src/lib/tests/confirmation.service.spec.ts
  18. 2
      npm/ng-packs/packages/theme-shared/src/lib/tests/error.handler.spec.ts
  19. 47
      npm/ng-packs/packages/theme-shared/src/lib/tests/loader-bar.component.spec.ts
  20. 4
      npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts
  21. 28
      npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts
  22. 7
      npm/ng-packs/packages/theme-shared/testing/ng-package.json
  23. 27
      npm/ng-packs/packages/theme-shared/testing/src/lib/theme-shared-testing.module.ts
  24. 1
      npm/ng-packs/packages/theme-shared/testing/src/public-api.ts
  25. 106
      npm/ng-packs/yarn.lock

1
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs

@ -246,6 +246,7 @@ namespace Volo.Abp.Cli.Commands
private void OpenThanksPage(UiFramework uiFramework, DatabaseProvider databaseProvider, bool tiered, bool commercial)
{
uiFramework = uiFramework == UiFramework.NotSpecified || uiFramework == UiFramework.None ? UiFramework.Mvc : uiFramework;
databaseProvider = databaseProvider == DatabaseProvider.NotSpecified ? DatabaseProvider.EntityFrameworkCore : databaseProvider;
var urlPrefix = commercial ? "commercial" : "www";
var tieredYesNo = tiered ? "yes" : "no";

10
npm/ng-packs/packages/core/src/lib/interceptors/api.interceptor.ts

@ -1,10 +1,9 @@
import { HttpHandler, HttpHeaders, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Store } from '@ngxs/store';
import { OAuthService } from 'angular-oauth2-oidc';
import { finalize } from 'rxjs/operators';
import { StartLoader, StopLoader } from '../actions/loader.actions';
import { SessionStateService } from '../services/session-state.service';
import { HttpWaitService } from '../services/http-wait.service';
@Injectable({
providedIn: 'root',
@ -12,20 +11,19 @@ import { SessionStateService } from '../services/session-state.service';
export class ApiInterceptor implements HttpInterceptor {
constructor(
private oAuthService: OAuthService,
private store: Store,
private sessionState: SessionStateService,
private httpWaitService: HttpWaitService,
) {}
intercept(request: HttpRequest<any>, next: HttpHandler) {
this.store.dispatch(new StartLoader(request));
this.httpWaitService.addRequest(request);
return next
.handle(
request.clone({
setHeaders: this.getAdditionalHeaders(request.headers),
}),
)
.pipe(finalize(() => this.store.dispatch(new StopLoader(request))));
.pipe(finalize(() => this.httpWaitService.deleteRequest(request)));
}
getAdditionalHeaders(existingHeaders?: HttpHeaders) {

4
npm/ng-packs/packages/core/src/lib/models/common.ts

@ -1,5 +1,5 @@
import { EventEmitter, Type } from '@angular/core';
import { Router, Routes } from '@angular/router';
import { Routes } from '@angular/router';
import { Subject } from 'rxjs';
import { eLayoutType } from '../enums/common';
import { Environment } from './environment';
@ -13,7 +13,7 @@ export namespace ABP {
}
export interface Test extends Partial<Root> {
baseHref?: Router;
baseHref?: string;
routes?: Routes;
}

44
npm/ng-packs/packages/core/src/lib/services/http-wait.service.ts

@ -0,0 +1,44 @@
import { Injectable } from '@angular/core';
import { HttpRequest } from '@angular/common/http';
import { InternalStore } from '../utils/internal-store-utils';
export interface HttpWaitState {
requests: Set<HttpRequest<any>>;
}
@Injectable({
providedIn: 'root',
})
export class HttpWaitService {
protected store = new InternalStore<HttpWaitState>({ requests: new Set() });
getLoading() {
return !!this.store.state.requests.size;
}
getLoading$() {
return this.store.sliceState(({ requests }) => !!requests.size);
}
updateLoading$() {
return this.store.sliceUpdate(({ requests }) => !!requests.size);
}
clearLoading() {
this.store.patch({ requests: new Set() });
}
addRequest(request: HttpRequest<any>) {
const requests = this.store.state.requests;
requests.add(request);
this.store.patch({ requests });
}
deleteRequest(request: HttpRequest<any>) {
const requests = this.store.state.requests;
requests.delete(request);
this.store.patch({ requests });
}
// TODO: Add filter function
}

3
npm/ng-packs/packages/core/src/lib/services/index.ts

@ -4,6 +4,7 @@ export * from './config-state.service';
export * from './content-projection.service';
export * from './dom-insertion.service';
export * from './environment.service';
export * from './http-wait.service';
export * from './lazy-load.service';
export * from './list.service';
export * from './localization.service';
@ -12,7 +13,9 @@ export * from './permission.service';
export * from './profile-state.service';
export * from './profile.service';
export * from './replaceable-components.service';
export * from './resource-wait.service';
export * from './rest.service';
export * from './router-wait.service';
export * from './routes.service';
export * from './session-state.service';
export * from './subscription.service';

10
npm/ng-packs/packages/core/src/lib/services/lazy-load.service.ts

@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
import { concat, Observable, of, throwError } from 'rxjs';
import { delay, retryWhen, shareReplay, take, tap } from 'rxjs/operators';
import { LoadingStrategy } from '../strategies';
import { ResourceWaitService } from './resource-wait.service';
@Injectable({
providedIn: 'root',
@ -9,9 +10,11 @@ import { LoadingStrategy } from '../strategies';
export class LazyLoadService {
readonly loaded = new Map<string, HTMLScriptElement | HTMLLinkElement>();
constructor(private resourceWaitService: ResourceWaitService) {}
load(strategy: LoadingStrategy, retryTimes?: number, retryDelay?: number): Observable<Event> {
if (this.loaded.has(strategy.path)) return of(new CustomEvent('load'));
this.resourceWaitService.addResource(strategy.path);
return strategy.createStream().pipe(
retryWhen(error$ =>
concat(
@ -19,7 +22,10 @@ export class LazyLoadService {
throwError(new CustomEvent('error')),
),
),
tap(() => this.loaded.set(strategy.path, strategy.element)),
tap(() => {
this.loaded.set(strategy.path, strategy.element);
this.resourceWaitService.deleteResource(strategy.path);
}),
delay(100),
shareReplay({ bufferSize: 1, refCount: true }),
);

41
npm/ng-packs/packages/core/src/lib/services/resource-wait.service.ts

@ -0,0 +1,41 @@
import { Injectable } from '@angular/core';
import { InternalStore } from '../utils/internal-store-utils';
export interface ResourceWaitState {
resources: Set<string>;
}
@Injectable({
providedIn: 'root',
})
export class ResourceWaitService {
private store = new InternalStore<ResourceWaitState>({ resources: new Set() });
getLoading() {
return !!this.store.state.resources.size;
}
getLoading$() {
return this.store.sliceState(({ resources }) => !!resources.size);
}
updateLoading$() {
return this.store.sliceUpdate(({ resources }) => !!resources.size);
}
clearLoading() {
this.store.patch({ resources: new Set() });
}
addResource(resource: string) {
const resources = this.store.state.resources;
resources.add(resource);
this.store.patch({ resources });
}
deleteResource(resource: string) {
const resources = this.store.state.resources;
resources.delete(resource);
this.store.patch({ resources });
}
}

10
npm/ng-packs/packages/core/src/lib/services/rest.service.ts

@ -15,13 +15,13 @@ import { EnvironmentService } from './environment.service';
})
export class RestService {
constructor(
@Inject(CORE_OPTIONS) private options: ABP.Root,
private http: HttpClient,
private store: Store,
private environment: EnvironmentService,
@Inject(CORE_OPTIONS) protected options: ABP.Root,
protected http: HttpClient,
protected environment: EnvironmentService,
protected store: Store,
) {}
private getApiFromStore(apiName: string): string {
protected getApiFromStore(apiName: string): string {
return this.environment.getApiUrl(apiName);
}

53
npm/ng-packs/packages/core/src/lib/services/router-wait.service.ts

@ -0,0 +1,53 @@
import { Injectable } from '@angular/core';
import {
NavigationCancel,
NavigationEnd,
NavigationError,
NavigationStart,
Router,
} from '@angular/router';
import { filter } from 'rxjs/operators';
import { InternalStore } from '../utils/internal-store-utils';
export interface RouterWaitState {
loading: boolean;
}
@Injectable({
providedIn: 'root',
})
export class RouterWaitService {
private store = new InternalStore<RouterWaitState>({ loading: false });
constructor(private router: Router) {
this.router.events
.pipe(
filter(
event =>
event instanceof NavigationStart ||
event instanceof NavigationEnd ||
event instanceof NavigationError ||
event instanceof NavigationCancel,
),
)
.subscribe(event => {
if (event instanceof NavigationStart) this.setLoading(true);
else this.setLoading(false);
});
}
getLoading() {
return this.store.state.loading;
}
getLoading$() {
return this.store.sliceState(({ loading }) => loading);
}
updateLoading$() {
return this.store.sliceUpdate(({ loading }) => loading);
}
setLoading(loading: boolean) {
this.store.patch({ loading });
}
}

19
npm/ng-packs/packages/core/src/lib/tests/api.interceptor.spec.ts

@ -1,31 +1,29 @@
import { HttpRequest } from '@angular/common/http';
import { SpyObject } from '@ngneat/spectator';
import { createServiceFactory, SpectatorService } from '@ngneat/spectator/jest';
import { Store } from '@ngxs/store';
import { OAuthService } from 'angular-oauth2-oidc';
import { Subject, timer } from 'rxjs';
import { StartLoader, StopLoader } from '../actions';
import { ApiInterceptor } from '../interceptors';
import { SessionStateService } from '../services';
import { HttpWaitService, SessionStateService } from '../services';
describe('ApiInterceptor', () => {
let spectator: SpectatorService<ApiInterceptor>;
let interceptor: ApiInterceptor;
let store: SpyObject<Store>;
let oauthService: SpyObject<OAuthService>;
let sessionState: SpyObject<SessionStateService>;
let httpWaitService: SpyObject<HttpWaitService>;
const createService = createServiceFactory({
service: ApiInterceptor,
mocks: [OAuthService, Store, SessionStateService],
mocks: [OAuthService, SessionStateService],
});
beforeEach(() => {
spectator = createService();
interceptor = spectator.service;
store = spectator.inject(Store);
sessionState = spectator.inject(SessionStateService);
oauthService = spectator.inject(OAuthService);
httpWaitService = spectator.inject(HttpWaitService);
});
it('should add headers to http request', done => {
@ -52,8 +50,9 @@ describe('ApiInterceptor', () => {
handleRes$.complete();
});
it('should dispatch the loader', done => {
const spy = jest.spyOn(store, 'dispatch');
it('should call http wait services add request and delete request', done => {
const spyAddRequest = jest.spyOn(httpWaitService, 'addRequest');
const spyDeleteRequest = jest.spyOn(httpWaitService, 'deleteRequest');
const request = new HttpRequest('GET', 'https://abp.io');
const handleRes$ = new Subject();
@ -70,8 +69,8 @@ describe('ApiInterceptor', () => {
handleRes$.complete();
timer(0).subscribe(() => {
expect(spy.mock.calls[0][0] instanceof StartLoader).toBeTruthy();
expect(spy.mock.calls[1][0] instanceof StopLoader).toBeTruthy();
expect(spyAddRequest).toHaveBeenCalled();
expect(spyDeleteRequest).toHaveBeenCalled();
done();
});
});

7
npm/ng-packs/packages/core/src/lib/tests/lazy-load.service.spec.ts

@ -2,10 +2,12 @@ import { of, throwError } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { LazyLoadService } from '../services/lazy-load.service';
import { ScriptLoadingStrategy } from '../strategies';
import { ResourceWaitService } from '../services';
describe('LazyLoadService', () => {
describe('#load', () => {
const service = new LazyLoadService();
const resourceWaitService = new ResourceWaitService();
const service = new LazyLoadService(resourceWaitService);
const strategy = new ScriptLoadingStrategy('http://example.com/');
afterEach(() => {
@ -58,7 +60,8 @@ describe('LazyLoadService', () => {
});
describe('#remove', () => {
const service = new LazyLoadService();
const resourceWaitService = new ResourceWaitService();
const service = new LazyLoadService(resourceWaitService);
it('should remove an already lazy loaded element and return true', () => {
const script = document.createElement('script');

8
npm/ng-packs/packages/core/testing/src/lib/core-testing.module.ts

@ -4,12 +4,14 @@ import {
coreOptionsFactory,
CORE_OPTIONS,
LocalizationPipe,
RestService,
} from '@abp/ng.core';
import { APP_BASE_HREF } from '@angular/common';
import { ModuleWithProviders, NgModule } from '@angular/core';
import { provideRoutes } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { MockLocalizationPipe } from './pipes/mock-localization.pipe';
import { MockRestService } from './services/mock-rest.service';
/**
* CoreTestingModule is the module that will be used in tests
@ -21,7 +23,7 @@ import { MockLocalizationPipe } from './pipes/mock-localization.pipe';
declarations: [MockLocalizationPipe],
})
export class CoreTestingModule {
static forTest(
static withConfig(
{ baseHref = '/', routes = [], ...options } = {} as ABP.Test,
): ModuleWithProviders<CoreTestingModule> {
return {
@ -41,6 +43,10 @@ export class CoreTestingModule {
provide: LocalizationPipe,
useClass: MockLocalizationPipe,
},
{
provide: RestService,
useClass: MockRestService,
},
provideRoutes(routes),
],
};

1
npm/ng-packs/packages/core/testing/src/lib/services/index.ts

@ -0,0 +1 @@
export * from './mock-rest.service';

21
npm/ng-packs/packages/core/testing/src/lib/services/mock-rest.service.ts

@ -0,0 +1,21 @@
import { ABP, CORE_OPTIONS, EnvironmentService, RestService } from '@abp/ng.core';
import { HttpClient } from '@angular/common/http';
import { Inject, Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class MockRestService extends RestService {
constructor(
@Inject(CORE_OPTIONS) protected options: ABP.Root,
protected http: HttpClient,
protected environment: EnvironmentService,
) {
super(options, http, environment, null);
}
handleError(err: any): Observable<any> {
return throwError(err);
}
}

60
npm/ng-packs/packages/theme-shared/src/lib/components/loader-bar/loader-bar.component.ts

@ -1,9 +1,7 @@
import { StartLoader, StopLoader, SubscriptionService } from '@abp/ng.core';
import { HttpWaitService, RouterWaitService, SubscriptionService } from '@abp/ng.core';
import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
import { NavigationEnd, NavigationError, NavigationStart, Router } from '@angular/router';
import { Actions, ofActionSuccessful } from '@ngxs/store';
import { Subscription, timer } from 'rxjs';
import { filter } from 'rxjs/operators';
import { Router } from '@angular/router';
import { combineLatest, Subscription, timer } from 'rxjs';
@Component({
selector: 'abp-loader-bar',
@ -43,18 +41,14 @@ export class LoaderBarComponent implements OnDestroy, OnInit {
progressLevel = 0;
interval: Subscription;
interval = new Subscription();
timer: Subscription;
timer = new Subscription();
intervalPeriod = 350;
stopDelay = 800;
@Input()
filter = (action: StartLoader | StopLoader) =>
action.payload.url.indexOf('openid-configuration') < 0;
private readonly clearProgress = () => {
this.progressLevel = 0;
this.cdRef.detectChanges();
@ -78,63 +72,47 @@ export class LoaderBarComponent implements OnDestroy, OnInit {
}
constructor(
private actions: Actions,
private router: Router,
private cdRef: ChangeDetectorRef,
private subscription: SubscriptionService,
private httpWaitService: HttpWaitService,
private routerWaiterService: RouterWaitService,
) {}
private subscribeToLoadActions() {
this.subscription.addOne(
this.actions.pipe(ofActionSuccessful(StartLoader, StopLoader), filter(this.filter)),
action => {
if (action instanceof StartLoader) this.startLoading();
else this.stopLoading();
},
);
ngOnInit() {
this.subscribeLoading();
}
private subscribeToRouterEvents() {
subscribeLoading() {
this.subscription.addOne(
this.router.events.pipe(
filter(
event =>
event instanceof NavigationStart ||
event instanceof NavigationEnd ||
event instanceof NavigationError,
),
),
event => {
if (event instanceof NavigationStart) this.startLoading();
combineLatest([this.httpWaitService.getLoading$(), this.routerWaiterService.getLoading$()]),
([httpLoading, routerLoading]) => {
if (httpLoading || routerLoading) this.startLoading();
else this.stopLoading();
},
);
}
ngOnInit() {
this.subscribeToLoadActions();
this.subscribeToRouterEvents();
}
ngOnDestroy() {
if (this.interval) this.interval.unsubscribe();
this.interval.unsubscribe();
}
startLoading() {
if (this.isLoading || (this.interval && !this.interval.closed)) return;
if (this.isLoading || !this.interval.closed) return;
this.isLoading = true;
this.progressLevel = 0;
this.interval = timer(0, this.intervalPeriod).subscribe(this.reportProgress);
this.timer.unsubscribe();
}
stopLoading() {
if (this.interval) this.interval.unsubscribe();
this.interval.unsubscribe();
this.progressLevel = 100;
this.isLoading = false;
if (this.timer && !this.timer.closed) return;
if (!this.timer.closed) return;
this.timer = timer(this.stopDelay).subscribe(this.clearProgress);
}

7
npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts

@ -74,7 +74,6 @@ export class ErrorHandler {
private actions: Actions,
private router: Router,
private confirmationService: ConfirmationService,
private appRef: ApplicationRef,
private cfRes: ComponentFactoryResolver,
private rendererFactory: RendererFactory2,
private injector: Injector,
@ -281,14 +280,16 @@ export class ErrorHandler {
}
this.componentRef.instance.hideCloseIcon = this.httpErrorConfig.errorScreen.hideCloseIcon;
const appRef = this.injector.get(ApplicationRef);
if (this.canCreateCustomError(instance.status as ErrorScreenErrorCodes)) {
this.componentRef.instance.cfRes = this.cfRes;
this.componentRef.instance.appRef = this.appRef;
this.componentRef.instance.appRef = appRef;
this.componentRef.instance.injector = this.injector;
this.componentRef.instance.customComponent = this.httpErrorConfig.errorScreen.component;
}
this.appRef.attachView(this.componentRef.hostView);
appRef.attachView(this.componentRef.hostView);
renderer.appendChild(host, (this.componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0]);
const destroy$ = new Subject<void>();

4
npm/ng-packs/packages/theme-shared/src/lib/tests/confirmation.service.spec.ts

@ -13,7 +13,7 @@ import { ConfirmationService } from '../services';
exports: [ConfirmationComponent],
entryComponents: [ConfirmationComponent],
declarations: [ConfirmationComponent],
imports: [CoreTestingModule.forTest()],
imports: [CoreTestingModule.withConfig()],
})
export class MockModule {}
@ -22,7 +22,7 @@ describe('ConfirmationService', () => {
let service: ConfirmationService;
const createService = createServiceFactory({
service: ConfirmationService,
imports: [NgxsModule.forRoot(), CoreTestingModule.forTest(), MockModule],
imports: [NgxsModule.forRoot(), CoreTestingModule.withConfig(), MockModule],
});
beforeEach(() => {

2
npm/ng-packs/packages/theme-shared/src/lib/tests/error.handler.spec.ts

@ -31,7 +31,7 @@ const CONFIRMATION_BUTTONS = {
describe('ErrorHandler', () => {
const createService = createServiceFactory({
service: ErrorHandler,
imports: [NgxsModule.forRoot([]), CoreTestingModule.forTest(), MockModule],
imports: [NgxsModule.forRoot([]), CoreTestingModule.withConfig(), MockModule],
mocks: [OAuthService],
providers: [
{ provide: APP_BASE_HREF, useValue: '/' },

47
npm/ng-packs/packages/theme-shared/src/lib/tests/loader-bar.component.spec.ts

@ -1,47 +1,37 @@
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 { NavigationEnd, NavigationError, NavigationStart, Router } from '@angular/router';
import { createComponentFactory, Spectator, SpyObject } from '@ngneat/spectator/jest';
import { Subject, timer } from 'rxjs';
import { LoaderBarComponent } from '../components/loader-bar/loader-bar.component';
import { StartLoader, StopLoader, SubscriptionService } from '@abp/ng.core';
import { HttpWaitService, SubscriptionService } from '@abp/ng.core';
import { HttpRequest } from '@angular/common/http';
describe('LoaderBarComponent', () => {
let spectator: SpectatorHost<LoaderBarComponent>;
let spectator: Spectator<LoaderBarComponent>;
let router: SpyObject<Router>;
const events$ = new Subject();
const createHost = createHostFactory({
const createComponent = createComponentFactory({
component: LoaderBarComponent,
mocks: [Router],
imports: [NgxsModule.forRoot()],
detectChanges: false,
providers: [SubscriptionService],
providers: [SubscriptionService, { provide: Router, useValue: { events: events$ } }],
});
beforeEach(() => {
spectator = createHost('<abp-loader-bar></abp-loader-bar>');
spectator = createComponent({});
spectator.component.intervalPeriod = 1;
spectator.component.stopDelay = 1;
router = spectator.inject(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', done => {
spectator.detectChanges();
spectator.inject(Store).dispatch(new StartLoader(new HttpRequest('GET', 'test')));
const httpWaitService = spectator.inject(HttpWaitService);
httpWaitService.addRequest(new HttpRequest('GET', 'test'));
spectator.detectChanges();
setTimeout(() => {
expect(spectator.component.progressLevel > 0).toBeTruthy();
@ -51,7 +41,8 @@ describe('LoaderBarComponent', () => {
test.skip('should be interval unsubscribed', done => {
spectator.detectChanges();
spectator.inject(Store).dispatch(new StartLoader(new HttpRequest('GET', 'test')));
const httpWaitService = spectator.inject(HttpWaitService);
httpWaitService.addRequest(new HttpRequest('GET', 'test'));
expect(spectator.component.interval.closed).toBe(false);
timer(400).subscribe(() => {
@ -62,11 +53,11 @@ describe('LoaderBarComponent', () => {
it('should start and stop the loading with navigation', done => {
spectator.detectChanges();
(router as any).events.next(new NavigationStart(1, 'test'));
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'));
events$.next(new NavigationEnd(1, 'test', 'test'));
events$.next(new NavigationError(1, 'test', 'test'));
expect(spectator.component.progressLevel).toBe(100);
timer(2).subscribe(() => {
@ -77,10 +68,10 @@ describe('LoaderBarComponent', () => {
it('should stop the loading with navigation', done => {
spectator.detectChanges();
(router as any).events.next(new NavigationStart(1, 'test'));
events$.next(new NavigationStart(1, 'test'));
expect(spectator.component.interval.closed).toBe(false);
spectator.inject(Store).dispatch(new StopLoader(new HttpRequest('GET', 'test')));
events$.next(new NavigationEnd(1, 'testend', 'testend'));
expect(spectator.component.progressLevel).toBe(100);
timer(2).subscribe(() => {
@ -92,8 +83,8 @@ describe('LoaderBarComponent', () => {
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'));
events$.next(new NavigationStart(1, 'test'));
events$.next(new NavigationStart(1, 'test'));
done();
});
});

4
npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts

@ -11,7 +11,7 @@ import { ToasterService } from '../services/toaster.service';
exports: [ToastContainerComponent],
entryComponents: [ToastContainerComponent],
declarations: [ToastContainerComponent, ToastComponent],
imports: [CoreTestingModule.forTest()],
imports: [CoreTestingModule.withConfig()],
})
export class MockModule {}
const toastClassPrefix = 'abp-toast';
@ -21,7 +21,7 @@ describe('ToasterService', () => {
let service: ToasterService;
const createService = createServiceFactory({
service: ToasterService,
imports: [NgxsModule.forRoot(), CoreTestingModule.forTest(), MockModule],
imports: [NgxsModule.forRoot(), CoreTestingModule.withConfig(), MockModule],
});
beforeEach(() => {

28
npm/ng-packs/packages/theme-shared/src/lib/theme-shared.module.ts

@ -27,7 +27,7 @@ import { initLazyStyleHandler } from './handlers/lazy-style.handler';
import { RootParams } from './models/common';
import { THEME_SHARED_ROUTE_PROVIDERS } from './providers/route.provider';
import { THEME_SHARED_APPEND_CONTENT } from './tokens/append-content.token';
import { HTTP_ERROR_CONFIG, httpErrorConfigFactory } from './tokens/http-error.token';
import { httpErrorConfigFactory, HTTP_ERROR_CONFIG } from './tokens/http-error.token';
import { DateParserFormatter } from './utils/date-parser-formatter';
const declarationsWithExports = [
@ -48,17 +48,11 @@ const declarationsWithExports = [
LoadingDirective,
TableSortDirective,
];
@NgModule({
imports: [CoreModule, NgxDatatableModule, NgxValidateCoreModule, NgbPaginationModule],
declarations: [
...declarationsWithExports,
HttpErrorWrapperComponent,
ModalContainerComponent,
],
exports: [
NgxDatatableModule,
...declarationsWithExports,
],
declarations: [...declarationsWithExports, HttpErrorWrapperComponent, ModalContainerComponent],
exports: [NgxDatatableModule, ...declarationsWithExports],
providers: [DatePipe],
entryComponents: [
HttpErrorWrapperComponent,
@ -68,13 +62,23 @@ const declarationsWithExports = [
ConfirmationComponent,
],
})
export class ThemeSharedModule {
constructor(private errorHandler: ErrorHandler) {}
export class BaseThemeSharedModule {}
@NgModule({
imports: [BaseThemeSharedModule],
exports: [BaseThemeSharedModule],
})
export class ThemeSharedModule {
static forRoot(options = {} as RootParams): ModuleWithProviders<ThemeSharedModule> {
return {
ngModule: ThemeSharedModule,
providers: [
{
provide: APP_INITIALIZER,
multi: true,
deps: [ErrorHandler],
useFactory: noop,
},
THEME_SHARED_ROUTE_PROVIDERS,
{
provide: APP_INITIALIZER,

7
npm/ng-packs/packages/theme-shared/testing/ng-package.json

@ -0,0 +1,7 @@
{
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/theme-shared/testing",
"lib": {
"entryFile": "src/public-api.ts"
}
}

27
npm/ng-packs/packages/theme-shared/testing/src/lib/theme-shared-testing.module.ts

@ -0,0 +1,27 @@
import {
BaseThemeSharedModule,
DateParserFormatter,
THEME_SHARED_ROUTE_PROVIDERS,
} from '@abp/ng.theme.shared';
import { ModuleWithProviders, NgModule } from '@angular/core';
import { RouterTestingModule } from '@angular/router/testing';
import { NgbDateParserFormatter } from '@ng-bootstrap/ng-bootstrap';
/**
* ThemeSharedTestingModule is the module that will be used in tests
*/
@NgModule({
exports: [RouterTestingModule, BaseThemeSharedModule],
imports: [RouterTestingModule, BaseThemeSharedModule],
})
export class ThemeSharedTestingModule {
static withConfig(): ModuleWithProviders<ThemeSharedTestingModule> {
return {
ngModule: ThemeSharedTestingModule,
providers: [
THEME_SHARED_ROUTE_PROVIDERS,
{ provide: NgbDateParserFormatter, useClass: DateParserFormatter },
],
};
}
}

1
npm/ng-packs/packages/theme-shared/testing/src/public-api.ts

@ -0,0 +1 @@
export * from './lib/theme-shared-testing.module';

106
npm/ng-packs/yarn.lock

@ -2,12 +2,12 @@
# yarn lockfile v1
"@abp/ng.core@~4.1.0-rc.1":
version "4.1.0-rc.1"
resolved "https://registry.yarnpkg.com/@abp/ng.core/-/ng.core-4.1.0-rc.1.tgz#efbd35e8df0731e75b2195149269b0228ec4ae42"
integrity sha512-WhXHMlDSbYled+mW8faMW8qHUGVErh/E/3eOgfvhx4N2tGGs5w+A4EfjNVBBROcoLDwiX2q1L88WeNnrK1+OIQ==
"@abp/ng.core@~4.1.0-rc.2":
version "4.1.0-rc.2"
resolved "https://registry.yarnpkg.com/@abp/ng.core/-/ng.core-4.1.0-rc.2.tgz#5fe53658965af66fae655dfce4bf6a7ad7105032"
integrity sha512-NcjOn1HYIdLTdHPbWTiLywPp1jQ+zmoeknnb0q/JfUUDn5r5kPrCf85xiZBUo8e+2ViB5vXvkM5lOOD5RfES6A==
dependencies:
"@abp/utils" "^4.0.1"
"@abp/utils" "^4.1.0-rc.1"
"@angular/localize" "~10.0.10"
"@ngxs/store" "^3.7.0"
angular-oauth2-oidc "^10.0.0"
@ -17,35 +17,35 @@
ts-toolbelt "6.15.4"
tslib "^2.0.0"
"@abp/ng.feature-management@~4.1.0-rc.1":
version "4.1.0-rc.1"
resolved "https://registry.yarnpkg.com/@abp/ng.feature-management/-/ng.feature-management-4.1.0-rc.1.tgz#5237db2e5a0ea5a6511941864fa721a303b5612c"
integrity sha512-/9GP6ze127uMkHB2QxWJC2MXiEMTLtBhM0DXYlPZKI+Y+FrVOBoUTI3gNz+AqWFwbBAA4PqfVuThhoja5b29Sg==
"@abp/ng.feature-management@~4.1.0-rc.2":
version "4.1.0-rc.2"
resolved "https://registry.yarnpkg.com/@abp/ng.feature-management/-/ng.feature-management-4.1.0-rc.2.tgz#02e760bfa913276e694dbff545e39210a69b21bd"
integrity sha512-vf//thBD3ve8tkmAIan2FqQeHrO/sP8NVV83noGVMTpqKIAWIu7PBuSL3YqcNVOVxHLsO6EIwr63OAJytlvH6A==
dependencies:
"@abp/ng.theme.shared" "~4.1.0-rc.1"
"@abp/ng.theme.shared" "~4.1.0-rc.2"
tslib "^2.0.0"
"@abp/ng.identity@~4.1.0-rc.1":
version "4.1.0-rc.1"
resolved "https://registry.yarnpkg.com/@abp/ng.identity/-/ng.identity-4.1.0-rc.1.tgz#932fd10482e82400a87927d200c2d3c850cccef4"
integrity sha512-uh7Fy+X2qGiNZ58g2c1GkmJL9VnMPLsKzg9EugNV2VxbGYg4/sNmVvAeIV66x2hpDXETHCjm+7lYuZsqI/5Vew==
"@abp/ng.identity@~4.1.0-rc.2":
version "4.1.0-rc.2"
resolved "https://registry.yarnpkg.com/@abp/ng.identity/-/ng.identity-4.1.0-rc.2.tgz#381d956cebe2f3c272c59567ff424d3729adb6aa"
integrity sha512-4Wnx/iXAOgdexDYuNTV+DBdnjyfhcgca1ZiUSuEnSVDKePq0xvpGeKvpXzhhm9T3uXNsqYwqNq/X5jK3jd6mZg==
dependencies:
"@abp/ng.permission-management" "~4.1.0-rc.1"
"@abp/ng.theme.shared" "~4.1.0-rc.1"
"@abp/ng.permission-management" "~4.1.0-rc.2"
"@abp/ng.theme.shared" "~4.1.0-rc.2"
tslib "^2.0.0"
"@abp/ng.permission-management@~4.1.0-rc.1":
version "4.1.0-rc.1"
resolved "https://registry.yarnpkg.com/@abp/ng.permission-management/-/ng.permission-management-4.1.0-rc.1.tgz#de810f1d50f901cffb15f59756127e83109e79f7"
integrity sha512-AgPpmBKDYnMKmMXoiU9ewGKtn5hH9frO5tV0wjz46BjmO9kIwyap3BBeCFcZjhgVLxZnXi8D0WuzZW7mgQARIQ==
"@abp/ng.permission-management@~4.1.0-rc.2":
version "4.1.0-rc.2"
resolved "https://registry.yarnpkg.com/@abp/ng.permission-management/-/ng.permission-management-4.1.0-rc.2.tgz#b74402241886e156a0e72baddfbc0ebebb7576aa"
integrity sha512-6/Z/8KGKkAflfk6CoXk92StEELuP0xkwj2dvvFvnGpr2od9ELGWWqtiJ5Pjz6i5FQvrLdqcHqPh8x/vgr7QV9w==
dependencies:
"@abp/ng.theme.shared" "~4.1.0-rc.1"
"@abp/ng.theme.shared" "~4.1.0-rc.2"
tslib "^2.0.0"
"@abp/ng.schematics@~4.1.0-rc.1":
version "4.1.0-rc.1"
resolved "https://registry.yarnpkg.com/@abp/ng.schematics/-/ng.schematics-4.1.0-rc.1.tgz#42173b847cfc2f293245a96fe4732a9049b8ab7c"
integrity sha512-FU5Mat3ki6ARDmOK5WC4/AMXJC+61EknuH44SE9Y9PraXAYkJk+2Ha+1qAg+VLBQcEEVWLxIqMp+2Soc6d6oow==
"@abp/ng.schematics@~4.1.0-rc.2":
version "4.1.0-rc.2"
resolved "https://registry.yarnpkg.com/@abp/ng.schematics/-/ng.schematics-4.1.0-rc.2.tgz#31dada6fc1f69d0198f4fb3801b6009d6a0a0c09"
integrity sha512-yVi/C1IbwcOQfXUAe8FSlekdNfoqi/UQvTBQ19h/HGBBDxhqbv6QKjhkaVs/+EOAW8WHWCufyVtQ2/y/jrCeog==
dependencies:
"@angular-devkit/core" "~11.0.2"
"@angular-devkit/schematics" "~11.0.2"
@ -53,37 +53,37 @@
jsonc-parser "^2.3.0"
typescript "~3.9.2"
"@abp/ng.setting-management@~4.1.0-rc.1":
version "4.1.0-rc.1"
resolved "https://registry.yarnpkg.com/@abp/ng.setting-management/-/ng.setting-management-4.1.0-rc.1.tgz#d35083c211089683c4fb07f88523c01e3e5d8ce0"
integrity sha512-qKLV2IWkHbK5ohHMxbdzPqE1pvPPatmV0EidE79Rk4j5+WZXOXtNz5GEA2vLmF3CsuVjX90cJQdtY1bdZpvdVQ==
"@abp/ng.setting-management@~4.1.0-rc.2":
version "4.1.0-rc.2"
resolved "https://registry.yarnpkg.com/@abp/ng.setting-management/-/ng.setting-management-4.1.0-rc.2.tgz#4b61bff63fa9d68be5f1c7b8c47049cc1bd8b5a8"
integrity sha512-Df2QS0bsytytUSkQ0KrI/m4pVTpQS708fwl8t3KcpeQ4hlgdg6LtTmhUaY/j6k8M1RJHaKvjPE9Jg6R2daLNGg==
dependencies:
"@abp/ng.theme.shared" "~4.1.0-rc.1"
"@abp/ng.theme.shared" "~4.1.0-rc.2"
tslib "^2.0.0"
"@abp/ng.tenant-management@~4.1.0-rc.1":
version "4.1.0-rc.1"
resolved "https://registry.yarnpkg.com/@abp/ng.tenant-management/-/ng.tenant-management-4.1.0-rc.1.tgz#be6740c8a7ac844c7100a46fb88bc96ce386e17d"
integrity sha512-OymGkg5BzHiraUC0FcWPm6JN84FgYNZ3YuLTAZd/iHmqQVoj51ymTK8dBOn7sw49vWlAj/WvGN4Z9tT/JS40zg==
"@abp/ng.tenant-management@~4.1.0-rc.2":
version "4.1.0-rc.2"
resolved "https://registry.yarnpkg.com/@abp/ng.tenant-management/-/ng.tenant-management-4.1.0-rc.2.tgz#b75b60db124e5246476821da2bfeebd5e5da09b6"
integrity sha512-AnDiMa/M4xSwiSXjyIsBY13BNxm+JMhWiIEb9WAPlk8IUaNDJZH9zHJH/HQSUHdy6dFCmutl5Ezi6U1J9ZHpPQ==
dependencies:
"@abp/ng.feature-management" "~4.1.0-rc.1"
"@abp/ng.theme.shared" "~4.1.0-rc.1"
"@abp/ng.feature-management" "~4.1.0-rc.2"
"@abp/ng.theme.shared" "~4.1.0-rc.2"
tslib "^2.0.0"
"@abp/ng.theme.basic@~4.1.0-rc.1":
version "4.1.0-rc.1"
resolved "https://registry.yarnpkg.com/@abp/ng.theme.basic/-/ng.theme.basic-4.1.0-rc.1.tgz#311e1ee4490803d43b1b1286620f1efa0fe3f459"
integrity sha512-nTf9UaupTxT0UgBx/SwaVuhtutUXFqGGq2dBKI0JNxltgfykLhDXUOTlUnymLlsyu09DJv8OIZbCX6PJAMV1GA==
"@abp/ng.theme.basic@~4.1.0-rc.2":
version "4.1.0-rc.2"
resolved "https://registry.yarnpkg.com/@abp/ng.theme.basic/-/ng.theme.basic-4.1.0-rc.2.tgz#4c0ccb5386a09cf7d89efaee59c8920265032361"
integrity sha512-2NjHymzE/sgbZ8e+CJ4iMemB+mD6e/VSKA2EkCaekPpXDlp0Z3f2yyhm0jwYqCQPsmCjykdtTpR266yLQOs7ug==
dependencies:
"@abp/ng.theme.shared" "~4.1.0-rc.1"
"@abp/ng.theme.shared" "~4.1.0-rc.2"
tslib "^2.0.0"
"@abp/ng.theme.shared@~4.1.0-rc.1":
version "4.1.0-rc.1"
resolved "https://registry.yarnpkg.com/@abp/ng.theme.shared/-/ng.theme.shared-4.1.0-rc.1.tgz#08c051cafd1364563943f7f8b6d067955227cc7e"
integrity sha512-oNPGXI6gyesDnzHq/x7QuXKr0ISwgz9YaKg2bvzZOCvyZ0usL2P4h/4sQvV9ThCYjDdkVKN+cdW+KNvalJ415w==
"@abp/ng.theme.shared@~4.1.0-rc.2":
version "4.1.0-rc.2"
resolved "https://registry.yarnpkg.com/@abp/ng.theme.shared/-/ng.theme.shared-4.1.0-rc.2.tgz#eaf524ef26f5433ec7ea01d402ba071c42ce1aa6"
integrity sha512-d6dVhV2wer7eeHoT8Y91Bqf7m2r3FVexUp7R+/f93564swuceZGZWSsgntwpHkNdDJaxhLUJ8tG5XMe2deEGTQ==
dependencies:
"@abp/ng.core" "~4.1.0-rc.1"
"@abp/ng.core" "~4.1.0-rc.2"
"@fortawesome/fontawesome-free" "^5.14.0"
"@ng-bootstrap/ng-bootstrap" "^7.0.0"
"@ngx-validate/core" "^0.0.13"
@ -92,13 +92,6 @@
chart.js "^2.9.3"
tslib "^2.0.0"
"@abp/utils@^4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-4.0.1.tgz#9a4cb420266c49d8084776bd31c86681d4d4d125"
integrity sha512-nI2ZyaNpvohr75p8jeMPWze+hX+mV47EHI+Zloa4GgGmJqrULdG71kYh45R+jGmMTbQL6huaXGnpz4gNF9TGyQ==
dependencies:
just-compare "^1.3.0"
"@abp/utils@^4.1.0-rc.1":
version "4.1.0-rc.1"
resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-4.1.0-rc.1.tgz#2863867985db9d178a5ce4347309f060f1ce6142"
@ -106,6 +99,13 @@
dependencies:
just-compare "^1.3.0"
"@abp/utils@^4.1.0-rc.2":
version "4.1.0-rc.2"
resolved "https://registry.yarnpkg.com/@abp/utils/-/utils-4.1.0-rc.2.tgz#eb6dbf0ee493d0f050b37347d2d6d283098aedae"
integrity sha512-V2k5I89lVBoeGIKgg4p2H9GlMAcDWbctwKZPVwBEMVEVm1uTR2xQAWdTdSFd5Q8I8Xsf/aIG8ELM7l5j2h7/zQ==
dependencies:
just-compare "^1.3.0"
"@angular-builders/jest@^10.0.0":
version "10.0.1"
resolved "https://registry.yarnpkg.com/@angular-builders/jest/-/jest-10.0.1.tgz#a1a6fb5d11b5d54c051bdaa2012b5f046371560c"

Loading…
Cancel
Save