update tests & add if condition to permissions directive
This commit is contained in:
parent
53b8442167
commit
8b07e0d31b
@ -3,6 +3,7 @@ import { IqserPermissionsModule } from '.';
|
||||
import { ComponentFixture, ComponentFixtureAutoDetect, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||
import { IqserPermissionsService } from './services/permissions.service';
|
||||
import { IqserRolesService } from './services/roles.service';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
|
||||
class BaseTestComponent {
|
||||
isAuthorized() {}
|
||||
@ -184,16 +185,7 @@ describe('Permission directive with roles array', () => {
|
||||
it('should show the component when key of role is the same', fakeAsync(() => {
|
||||
permissionsService.add(awesomePermission);
|
||||
rolesService.add({ ADMIN: [awesomePermission] });
|
||||
tick();
|
||||
|
||||
const content = getFixtureContent();
|
||||
expect(content).toBeTruthy();
|
||||
expect(content.innerHTML).toEqual('123');
|
||||
}));
|
||||
|
||||
it('should show the component when there is permission', fakeAsync(() => {
|
||||
permissionsService.add(awesomePermission);
|
||||
rolesService.add({ ADMIN: ['AWESOME'] });
|
||||
rolesService.add({ GUEST: [awesomePermission] });
|
||||
tick();
|
||||
|
||||
const content = getFixtureContent();
|
||||
@ -204,6 +196,7 @@ describe('Permission directive with roles array', () => {
|
||||
it('should hide the component when user deletes all roles', fakeAsync(() => {
|
||||
permissionsService.add(awesomePermission);
|
||||
rolesService.add({ ADMIN: [awesomePermission] });
|
||||
rolesService.add({ GUEST: [awesomePermission] });
|
||||
tick();
|
||||
|
||||
const content = getFixtureContent();
|
||||
@ -216,9 +209,10 @@ describe('Permission directive with roles array', () => {
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
}));
|
||||
|
||||
it('should hide the component when user deletes one roles', fakeAsync(() => {
|
||||
it('should hide the component when user deletes one role', fakeAsync(() => {
|
||||
permissionsService.add(awesomePermission);
|
||||
rolesService.add({ ADMIN: [awesomePermission] });
|
||||
rolesService.add({ GUEST: [awesomePermission] });
|
||||
tick();
|
||||
|
||||
const content = getFixtureContent();
|
||||
@ -329,6 +323,7 @@ describe('Permission directive angular testing different async functions in role
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
|
||||
rolesService.add({ ADMIN: () => Promise.resolve(true) });
|
||||
rolesService.add({ GUEST: () => Promise.resolve(true) });
|
||||
tick();
|
||||
|
||||
const content = getFixtureContent();
|
||||
@ -340,6 +335,7 @@ describe('Permission directive angular testing different async functions in role
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
|
||||
rolesService.add({ ADMIN: () => Promise.resolve(false) });
|
||||
rolesService.add({ GUEST: () => Promise.resolve(true) });
|
||||
tick();
|
||||
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
@ -348,32 +344,29 @@ describe('Permission directive angular testing different async functions in role
|
||||
it('should not show the component when promise rejects', fakeAsync(() => {
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
|
||||
rolesService.add({ ADMIN: () => Promise.reject() });
|
||||
rolesService.add({ ADMIN: () => Promise.resolve(true) });
|
||||
rolesService.add({ GUEST: () => Promise.reject() });
|
||||
tick();
|
||||
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
}));
|
||||
|
||||
it('should show the component when one of the promises fulfills', fakeAsync(() => {
|
||||
it('should hide the component when one of the promises fulfills', fakeAsync(() => {
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
|
||||
rolesService.add({ ADMIN: () => Promise.reject(), GUEST: () => Promise.resolve(true) });
|
||||
tick();
|
||||
|
||||
const content = getFixtureContent();
|
||||
expect(content).toBeTruthy();
|
||||
expect(content.innerHTML).toEqual('<div>123</div>');
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
}));
|
||||
|
||||
it('should show the component when one of the promises fulfills with true value', fakeAsync(() => {
|
||||
it('should hide the component when one of the promises fulfills with true value', fakeAsync(() => {
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
|
||||
rolesService.add({ ADMIN: () => Promise.reject(), GUEST: () => Promise.resolve(true) });
|
||||
tick();
|
||||
|
||||
const content = getFixtureContent();
|
||||
expect(content).toBeTruthy();
|
||||
expect(content.innerHTML).toEqual('<div>123</div>');
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
}));
|
||||
|
||||
it('should not show the component when all promises fails', fakeAsync(() => {
|
||||
@ -385,38 +378,23 @@ describe('Permission directive angular testing different async functions in role
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
}));
|
||||
|
||||
it('should show the component when one of promises returns true', fakeAsync(() => {
|
||||
it('should hide the component when one of promises returns true', fakeAsync(() => {
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
|
||||
rolesService.add({ GUEST: () => true, ADMIN: () => Promise.reject() });
|
||||
tick();
|
||||
|
||||
const content = getFixtureContent();
|
||||
expect(content).toBeTruthy();
|
||||
expect(content.innerHTML).toEqual('<div>123</div>');
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
}));
|
||||
|
||||
it('should show the component when 1 passes second fails', fakeAsync(() => {
|
||||
it('should hide the component when 1 passes second fails', fakeAsync(() => {
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
|
||||
rolesService.add({ ADMIN: () => Promise.reject() });
|
||||
rolesService.add({ ADMIN: ['AWESOME'] });
|
||||
rolesService.add({ GUEST: ['AWESOME'] });
|
||||
tick();
|
||||
|
||||
const content = getFixtureContent();
|
||||
expect(content).toBeTruthy();
|
||||
expect(content.innerHTML).toEqual('<div>123</div>');
|
||||
}));
|
||||
|
||||
it('should show the component when one rejects but another one fulfils', fakeAsync(() => {
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
|
||||
rolesService.add({ ADMIN: () => Promise.reject(), GUEST: ['AWESOME'] });
|
||||
tick();
|
||||
|
||||
const content = getFixtureContent();
|
||||
expect(content).toBeTruthy();
|
||||
expect(content.innerHTML).toEqual('<div>123</div>');
|
||||
}));
|
||||
});
|
||||
|
||||
@ -806,3 +784,154 @@ describe('Permissions directive with an empty array', () => {
|
||||
expect(content.innerHTML).toEqual(`123`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Permission directive with true if condition', () => {
|
||||
@Component({
|
||||
template: ` <ng-template [allow]="'ADMIN'" [allowIf]="true">
|
||||
<div>123</div>
|
||||
</ng-template>`,
|
||||
})
|
||||
class TestComponent extends BaseTestComponent {}
|
||||
|
||||
beforeEach(() => configureTestBed(TestComponent));
|
||||
|
||||
it('should show the component when permission is present', fakeAsync(() => {
|
||||
permissionsService.add(ADMIN);
|
||||
tick();
|
||||
|
||||
const content = getFixtureContent();
|
||||
expect(content).toBeTruthy();
|
||||
expect(content.innerHTML).toEqual('123');
|
||||
}));
|
||||
|
||||
it('should hide the component when permission is absent', fakeAsync(() => {
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('Permission directive with true if condition', () => {
|
||||
@Component({
|
||||
template: ` <ng-template [allow]="'ADMIN'" [allowIf]="false">
|
||||
<div>123</div>
|
||||
</ng-template>`,
|
||||
})
|
||||
class TestComponent extends BaseTestComponent {}
|
||||
|
||||
beforeEach(() => configureTestBed(TestComponent));
|
||||
|
||||
it('should hide the component when permission is present', fakeAsync(() => {
|
||||
permissionsService.add(ADMIN);
|
||||
tick();
|
||||
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
}));
|
||||
|
||||
it('should hide the component when permission is absent', fakeAsync(() => {
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('Permission directive with true promise if condition', () => {
|
||||
@Component({
|
||||
template: ` <ng-template [allow]="'ADMIN'" [allowIf]="condition">
|
||||
<div>123</div>
|
||||
</ng-template>`,
|
||||
})
|
||||
class TestComponent extends BaseTestComponent {
|
||||
condition = Promise.resolve(true);
|
||||
}
|
||||
|
||||
beforeEach(() => configureTestBed(TestComponent));
|
||||
|
||||
it('should show the component when permission is present', fakeAsync(() => {
|
||||
permissionsService.add(ADMIN);
|
||||
tick();
|
||||
|
||||
const content = getFixtureContent();
|
||||
expect(content).toBeTruthy();
|
||||
expect(content.innerHTML).toEqual('123');
|
||||
}));
|
||||
|
||||
it('should hide the component when permission is absent', fakeAsync(() => {
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('Permission directive with false promise if condition', () => {
|
||||
@Component({
|
||||
template: ` <div *allow="'ADMIN'; if: condition">
|
||||
<div>123</div>
|
||||
</div>`,
|
||||
})
|
||||
class TestComponent extends BaseTestComponent {
|
||||
condition = Promise.resolve(false);
|
||||
}
|
||||
|
||||
beforeEach(() => configureTestBed(TestComponent));
|
||||
|
||||
it('should hide the component when permission is present', fakeAsync(() => {
|
||||
permissionsService.add(ADMIN);
|
||||
tick();
|
||||
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
}));
|
||||
|
||||
it('should hide the component when permission is absent', fakeAsync(() => {
|
||||
expect(getFixtureContent()).toEqual(null);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('Permissions directive with then block and if condition', () => {
|
||||
@Component({
|
||||
template: `
|
||||
<div *allow="['THEN_BLOCK']; if: condition; else: elseBlock; then: thenBlock">main</div>
|
||||
|
||||
<ng-template #elseBlock>
|
||||
<div>elseBlockContent</div>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #thenBlock>
|
||||
<div>thenBlockContent</div>
|
||||
</ng-template>
|
||||
`,
|
||||
})
|
||||
class TestComponent extends BaseTestComponent {
|
||||
condition = new BehaviorSubject(true);
|
||||
}
|
||||
|
||||
beforeEach(() => configureTestBed(TestComponent));
|
||||
|
||||
it('should show else block when permission missing', fakeAsync(() => {
|
||||
const content = getFixtureContent();
|
||||
expect(content).toBeTruthy();
|
||||
expect(content.innerHTML).toEqual(`elseBlockContent`);
|
||||
}));
|
||||
|
||||
it('should show then block when permission added', fakeAsync(() => {
|
||||
permissionsService.add('THEN_BLOCK');
|
||||
tick();
|
||||
|
||||
const content = getFixtureContent();
|
||||
expect(content).toBeTruthy();
|
||||
expect(content.innerHTML).toEqual(`thenBlockContent`);
|
||||
}));
|
||||
|
||||
it('should show else block when permission added but condition is false', fakeAsync(() => {
|
||||
permissionsService.add('THEN_BLOCK');
|
||||
(fixture.componentInstance as TestComponent).condition.next(false);
|
||||
tick();
|
||||
|
||||
const content = getFixtureContent();
|
||||
expect(content).toBeTruthy();
|
||||
expect(content.innerHTML).toEqual(`elseBlockContent`);
|
||||
}));
|
||||
|
||||
it('should show else block when permission is missing and condition is false', fakeAsync(() => {
|
||||
(fixture.componentInstance as TestComponent).condition.next(false);
|
||||
tick();
|
||||
|
||||
const content = getFixtureContent();
|
||||
expect(content).toBeTruthy();
|
||||
expect(content.innerHTML).toEqual(`elseBlockContent`);
|
||||
}));
|
||||
});
|
||||
|
||||
@ -12,12 +12,13 @@ import {
|
||||
ɵstringify as stringify,
|
||||
} from '@angular/core';
|
||||
|
||||
import { merge, Subject, Subscription, switchMap } from 'rxjs';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { BehaviorSubject, combineLatest, merge, Observable, of, Subject, Subscription, switchMap } from 'rxjs';
|
||||
import { map, tap } from 'rxjs/operators';
|
||||
|
||||
import { IqserRolesService } from './services/roles.service';
|
||||
import { IqserPermissionsService } from './services/permissions.service';
|
||||
import { List } from '../utils';
|
||||
import { isBoolean } from './utils';
|
||||
|
||||
@Directive({
|
||||
selector: '[allow]',
|
||||
@ -45,6 +46,7 @@ export class IqserPermissionsDirective implements OnDestroy, OnInit {
|
||||
|
||||
readonly #updateView = new Subject<void>();
|
||||
readonly #subscription = new Subscription();
|
||||
readonly #if = new BehaviorSubject<Promise<boolean> | Observable<boolean>>(of(true));
|
||||
|
||||
constructor(
|
||||
private readonly _permissionsService: IqserPermissionsService,
|
||||
@ -54,7 +56,17 @@ export class IqserPermissionsDirective implements OnDestroy, OnInit {
|
||||
templateRef: TemplateRef<unknown>,
|
||||
) {
|
||||
this.#thenTemplateRef = templateRef;
|
||||
this.#subscription = this.#updateView.pipe(switchMap(() => this.#waitForRolesAndPermissions())).subscribe();
|
||||
|
||||
const ifCondition$ = this.#if.pipe(
|
||||
switchMap(condition => condition),
|
||||
tap(console.log),
|
||||
);
|
||||
this.#subscription = combineLatest([ifCondition$, this.#updateView])
|
||||
.pipe(
|
||||
switchMap(([ifCondition]) => this.#waitForRolesAndPermissions().pipe(map(hasPermission => ifCondition && hasPermission))),
|
||||
tap(isAllowed => (isAllowed ? this.#showThenBlock() : this.#showElseBlock())),
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
@Input()
|
||||
@ -79,6 +91,15 @@ export class IqserPermissionsDirective implements OnDestroy, OnInit {
|
||||
this.#updateView.next();
|
||||
}
|
||||
|
||||
@Input()
|
||||
set allowIf(value: boolean | Promise<boolean> | Observable<boolean>) {
|
||||
if (isBoolean(value)) {
|
||||
this.#if.next(of(value));
|
||||
} else {
|
||||
this.#if.next(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
This assures that when the directive has an empty input (such as [allow]="") the view is updated
|
||||
*/
|
||||
@ -91,17 +112,18 @@ export class IqserPermissionsDirective implements OnDestroy, OnInit {
|
||||
}
|
||||
|
||||
#waitForRolesAndPermissions() {
|
||||
return merge(this._permissionsService.permissions$, this._rolesService.roles$).pipe(tap(() => this.#validate()));
|
||||
return merge(this._permissionsService.permissions$, this._rolesService.roles$).pipe(switchMap(() => this.#validate()));
|
||||
}
|
||||
|
||||
#validate(): void {
|
||||
#validate() {
|
||||
if (!this.#permissions) {
|
||||
return this.#showThenBlock();
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
const promises = [this._permissionsService.has(this.#permissions), this._rolesService.has(this.#permissions)];
|
||||
const result = Promise.all(promises).then(([hasPermission, hasRole]) => hasPermission || hasRole);
|
||||
result.then(isAllowed => (isAllowed ? this.#showThenBlock() : this.#showElseBlock())).catch(() => this.#showElseBlock());
|
||||
return Promise.all(promises)
|
||||
.then(([hasPermission, hasRole]) => hasPermission || hasRole)
|
||||
.catch(() => false);
|
||||
}
|
||||
|
||||
#showElseBlock() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user