diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 0000000..9eefed0 --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,21 @@ +export default { + displayName: 'common-ui', + preset: 'jest-preset-angular', + setupFilesAfterEnv: ['./setup-jest.ts'], + coverageDirectory: '../../coverage/libs/common-ui', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: './tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/setup-jest.ts b/setup-jest.ts new file mode 100644 index 0000000..1100b3e --- /dev/null +++ b/setup-jest.ts @@ -0,0 +1 @@ +import 'jest-preset-angular/setup-jest'; diff --git a/src/lib/permissions/directives/allow/allow.directive.spec.ts b/src/lib/permissions/directives/allow.directive.spec.ts similarity index 99% rename from src/lib/permissions/directives/allow/allow.directive.spec.ts rename to src/lib/permissions/directives/allow.directive.spec.ts index 67be7d7..a43485a 100644 --- a/src/lib/permissions/directives/allow/allow.directive.spec.ts +++ b/src/lib/permissions/directives/allow.directive.spec.ts @@ -1,9 +1,9 @@ import { ChangeDetectionStrategy, Component, Type } from '@angular/core'; -import { IqserPermissionsModule } from '../../index'; import { ComponentFixture, ComponentFixtureAutoDetect, fakeAsync, TestBed, tick } from '@angular/core/testing'; -import { IqserPermissionsService } from '../../services/permissions.service'; -import { IqserRolesService } from '../../services/roles.service'; +import { IqserPermissionsService } from '../services/permissions.service'; +import { IqserRolesService } from '../services/roles.service'; import { BehaviorSubject } from 'rxjs'; +import { IqserAllowDirective } from './allow.directive'; class BaseTestComponent { isAuthorized() {} @@ -23,7 +23,7 @@ let isUnauthorizedSpy: jest.SpyInstance; function configureTestBed(component: Type) { TestBed.configureTestingModule({ declarations: [component], - imports: [IqserPermissionsModule.forRoot()], + imports: [IqserAllowDirective], providers: [{ provide: ComponentFixtureAutoDetect, useValue: true }], }); diff --git a/src/lib/permissions/directives/allow/allow.directive.ts b/src/lib/permissions/directives/allow.directive.ts similarity index 93% rename from src/lib/permissions/directives/allow/allow.directive.ts rename to src/lib/permissions/directives/allow.directive.ts index 7b5a3d3..395013d 100644 --- a/src/lib/permissions/directives/allow/allow.directive.ts +++ b/src/lib/permissions/directives/allow.directive.ts @@ -1,11 +1,12 @@ import { Directive, Input, OnDestroy, OnInit, TemplateRef } from '@angular/core'; import { Observable } from 'rxjs'; -import { List } from '../../../utils'; -import { assertTemplate, IqserPermissionsDirective } from '../permissions.directive'; +import { List } from '../../utils'; +import { assertTemplate, IqserPermissionsDirective } from './permissions.directive'; @Directive({ selector: '[allow]', + standalone: true, }) export class IqserAllowDirective extends IqserPermissionsDirective implements OnDestroy, OnInit { /** diff --git a/src/lib/permissions/directives/deny/deny.directive.spec.ts b/src/lib/permissions/directives/deny.directive.spec.ts similarity index 99% rename from src/lib/permissions/directives/deny/deny.directive.spec.ts rename to src/lib/permissions/directives/deny.directive.spec.ts index 0952f78..27ef4d5 100644 --- a/src/lib/permissions/directives/deny/deny.directive.spec.ts +++ b/src/lib/permissions/directives/deny.directive.spec.ts @@ -1,9 +1,9 @@ import { ChangeDetectionStrategy, Component, Type } from '@angular/core'; -import { IqserPermissionsModule } from '../../index'; import { ComponentFixture, ComponentFixtureAutoDetect, fakeAsync, TestBed, tick } from '@angular/core/testing'; -import { IqserPermissionsService } from '../../services/permissions.service'; -import { IqserRolesService } from '../../services/roles.service'; +import { IqserPermissionsService } from '../services/permissions.service'; +import { IqserRolesService } from '../services/roles.service'; import { BehaviorSubject } from 'rxjs'; +import { IqserDenyDirective } from './deny.directive'; class BaseTestComponent { isAuthorized() {} @@ -23,7 +23,7 @@ let isUnauthorizedSpy: jest.SpyInstance; function configureTestBed(component: Type) { TestBed.configureTestingModule({ declarations: [component], - imports: [IqserPermissionsModule.forRoot()], + imports: [IqserDenyDirective], providers: [{ provide: ComponentFixtureAutoDetect, useValue: true }], }); diff --git a/src/lib/permissions/directives/deny/deny.directive.ts b/src/lib/permissions/directives/deny.directive.ts similarity index 92% rename from src/lib/permissions/directives/deny/deny.directive.ts rename to src/lib/permissions/directives/deny.directive.ts index 7e55fa6..adf6821 100644 --- a/src/lib/permissions/directives/deny/deny.directive.ts +++ b/src/lib/permissions/directives/deny.directive.ts @@ -1,11 +1,12 @@ import { Directive, Input, OnDestroy, OnInit, TemplateRef } from '@angular/core'; import { Observable } from 'rxjs'; -import { List } from '../../../utils'; -import { assertTemplate, IqserPermissionsDirective } from '../permissions.directive'; +import { List } from '../../utils'; +import { assertTemplate, IqserPermissionsDirective } from './permissions.directive'; @Directive({ selector: '[deny]', + standalone: true, }) export class IqserDenyDirective extends IqserPermissionsDirective implements OnDestroy, OnInit { /** diff --git a/src/lib/permissions/index.ts b/src/lib/permissions/index.ts index b255d47..f007ac4 100644 --- a/src/lib/permissions/index.ts +++ b/src/lib/permissions/index.ts @@ -3,5 +3,4 @@ export * from './services/permissions-guard.service'; export * from './services/permissions.service'; export * from './services/roles.service'; export * from './directives/permissions.directive'; -export * from './permissions.module'; export * from './utils'; diff --git a/src/lib/permissions/permissions.module.ts b/src/lib/permissions/permissions.module.ts deleted file mode 100644 index c5dd2ec..0000000 --- a/src/lib/permissions/permissions.module.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { NgModule, Optional } from '@angular/core'; -import { IqserAllowDirective } from './directives/allow/allow.directive'; -import { IqserPermissionsService } from './services/permissions.service'; -import { IqserPermissionsGuard } from './services/permissions-guard.service'; -import { IqserRolesService } from './services/roles.service'; -import { IqserDenyDirective } from './directives/deny/deny.directive'; - -@NgModule({ - declarations: [IqserAllowDirective, IqserDenyDirective], - exports: [IqserAllowDirective, IqserDenyDirective], -}) -export class IqserPermissionsModule { - constructor(@Optional() permissionsService: IqserPermissionsService) { - if (!permissionsService) { - throw new Error('Call forRoot() in AppModule to use IqserPermissionsModule'); - } - } - - static forRoot() { - return { - ngModule: IqserPermissionsModule, - providers: [IqserPermissionsService, IqserPermissionsGuard, IqserRolesService], - }; - } -} diff --git a/src/lib/permissions/services/permissions-guard.service.spec.ts b/src/lib/permissions/services/permissions-guard.service.spec.ts index 316408a..f044fcf 100644 --- a/src/lib/permissions/services/permissions-guard.service.spec.ts +++ b/src/lib/permissions/services/permissions-guard.service.spec.ts @@ -1,6 +1,6 @@ import { TestBed } from '@angular/core/testing'; import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router'; -import { IqserActivatedRouteSnapshot, IqserPermissionsModule } from '..'; +import { IqserActivatedRouteSnapshot } from '..'; import { IqserPermissionsService } from './permissions.service'; import { IqserRolesService } from './roles.service'; import { IqserPermissionsGuard } from './permissions-guard.service'; @@ -23,7 +23,6 @@ function configureTestBed() { routerNavigationSpy = jest.spyOn(router, 'navigate'); TestBed.configureTestingModule({ - imports: [IqserPermissionsModule.forRoot()], providers: [ { provide: Router, diff --git a/src/lib/permissions/services/permissions-guard.service.ts b/src/lib/permissions/services/permissions-guard.service.ts index 14e25e6..6d95ae1 100644 --- a/src/lib/permissions/services/permissions-guard.service.ts +++ b/src/lib/permissions/services/permissions-guard.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, CanLoad, Route, Router, RouterStateSnapshot } from '@angular/router'; +import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, CanMatch, Route, Router, RouterStateSnapshot } from '@angular/router'; import { firstValueFrom, from, of } from 'rxjs'; import { first, mergeMap } from 'rxjs/operators'; @@ -19,12 +19,14 @@ import { isArray, isFunction, isRedirectWithParameters, isString, transformPermi import { List } from '../../utils'; export interface IqserPermissionsData { - allow: string | List; - redirectTo?: RedirectTo | RedirectToFn; + readonly allow: string | List; + readonly redirectTo?: RedirectTo | RedirectToFn; } -@Injectable() -export class IqserPermissionsGuard implements CanActivate, CanLoad, CanActivateChild { +@Injectable({ + providedIn: 'root', +}) +export class IqserPermissionsGuard implements CanActivate, CanMatch, CanActivateChild { constructor( private readonly _permissionsService: IqserPermissionsService, private readonly _rolesService: IqserRolesService, @@ -39,7 +41,7 @@ export class IqserPermissionsGuard implements CanActivate, CanLoad, CanActivateC return this.#checkPermissions(childRoute, state); } - canLoad(route: IqserRoute) { + canMatch(route: IqserRoute) { return this.#checkPermissions(route); } diff --git a/src/lib/permissions/services/permissions.service.spec.ts b/src/lib/permissions/services/permissions.service.spec.ts index 46d7480..e8f3d3f 100644 --- a/src/lib/permissions/services/permissions.service.spec.ts +++ b/src/lib/permissions/services/permissions.service.spec.ts @@ -1,5 +1,4 @@ import { TestBed } from '@angular/core/testing'; -import { IqserPermissionsModule } from '../permissions.module'; import { IqserPermissionsService } from './permissions.service'; const ADMIN = 'ADMIN' as const; @@ -12,11 +11,7 @@ describe('Permissions Service', () => { return Object.keys(permissionsService.get()).length; } - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [IqserPermissionsModule.forRoot()], - }); - + beforeEach(async () => { permissionsService = TestBed.inject(IqserPermissionsService); }); diff --git a/src/lib/permissions/services/permissions.service.ts b/src/lib/permissions/services/permissions.service.ts index f2f8529..948e2aa 100644 --- a/src/lib/permissions/services/permissions.service.ts +++ b/src/lib/permissions/services/permissions.service.ts @@ -7,7 +7,9 @@ import { IqserPermissions, PermissionValidationFn } from '../types'; import { List } from '../../utils'; import { map } from 'rxjs/operators'; -@Injectable() +@Injectable({ + providedIn: 'root', +}) export class IqserPermissionsService { readonly permissions$: Observable; readonly #permissions$ = new BehaviorSubject({}); diff --git a/src/lib/permissions/services/roles.service.spec.ts b/src/lib/permissions/services/roles.service.spec.ts index 6f6d786..ed21d18 100644 --- a/src/lib/permissions/services/roles.service.spec.ts +++ b/src/lib/permissions/services/roles.service.spec.ts @@ -2,7 +2,6 @@ import { TestBed } from '@angular/core/testing'; import { RoleValidationFn } from '../types'; import { IqserRolesService } from './roles.service'; import { IqserPermissionsService } from './permissions.service'; -import { IqserPermissionsModule } from '../permissions.module'; const ADMIN = 'ADMIN' as const; @@ -19,10 +18,6 @@ describe('Roles Service', () => { } beforeEach(() => { - TestBed.configureTestingModule({ - imports: [IqserPermissionsModule.forRoot()], - }); - rolesService = TestBed.inject(IqserRolesService); permissionsService = TestBed.inject(IqserPermissionsService); }); diff --git a/src/lib/permissions/services/roles.service.ts b/src/lib/permissions/services/roles.service.ts index ca5f3be..82bb1c6 100644 --- a/src/lib/permissions/services/roles.service.ts +++ b/src/lib/permissions/services/roles.service.ts @@ -6,7 +6,9 @@ import { isArray, isBoolean, isString, toArray } from '../utils'; import { List } from '../../utils'; import { IqserPermissionsService } from './permissions.service'; -@Injectable() +@Injectable({ + providedIn: 'root', +}) export class IqserRolesService { readonly roles$: Observable; readonly #roles$ = new BehaviorSubject({}); diff --git a/src/lib/permissions/types.ts b/src/lib/permissions/types.ts index 77aec2a..c2ba713 100644 --- a/src/lib/permissions/types.ts +++ b/src/lib/permissions/types.ts @@ -31,12 +31,14 @@ export type PermissionValidationFn = (name: string, store: IqserPermissions) => export type IqserActivatedRouteSnapshot = ActivatedRouteSnapshot & { data?: { permissions?: IqserPermissionsRouterData; + reuse?: boolean; }; }; export type IqserRoute = Route & { data?: { permissions?: IqserPermissionsRouterData; + reuse?: boolean; }; children?: List;