mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-15 05:53:03 +00:00
71429: Feature and Authorization tests
This commit is contained in:
@@ -33,6 +33,9 @@ import { NotificationsServiceStub } from '../../../../shared/testing/notificatio
|
|||||||
import { TranslateLoaderMock } from '../../../../shared/mocks/translate-loader.mock';
|
import { TranslateLoaderMock } from '../../../../shared/mocks/translate-loader.mock';
|
||||||
import { AuthService } from '../../../../core/auth/auth.service';
|
import { AuthService } from '../../../../core/auth/auth.service';
|
||||||
import { AuthServiceStub } from '../../../../shared/testing/auth-service.stub';
|
import { AuthServiceStub } from '../../../../shared/testing/auth-service.stub';
|
||||||
|
import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service';
|
||||||
|
import { GroupDataService } from '../../../../core/eperson/group-data.service';
|
||||||
|
import { createPaginatedList } from '../../../../shared/testing/utils.test';
|
||||||
|
|
||||||
describe('EPersonFormComponent', () => {
|
describe('EPersonFormComponent', () => {
|
||||||
let component: EPersonFormComponent;
|
let component: EPersonFormComponent;
|
||||||
@@ -43,6 +46,8 @@ describe('EPersonFormComponent', () => {
|
|||||||
let mockEPeople;
|
let mockEPeople;
|
||||||
let ePersonDataServiceStub: any;
|
let ePersonDataServiceStub: any;
|
||||||
let authService: AuthServiceStub;
|
let authService: AuthServiceStub;
|
||||||
|
let authorizationService: AuthorizationDataService;
|
||||||
|
let groupsDataService: GroupDataService;
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
mockEPeople = [EPersonMock, EPersonMock2];
|
mockEPeople = [EPersonMock, EPersonMock2];
|
||||||
@@ -108,6 +113,13 @@ describe('EPersonFormComponent', () => {
|
|||||||
builderService = getMockFormBuilderService();
|
builderService = getMockFormBuilderService();
|
||||||
translateService = getMockTranslateService();
|
translateService = getMockTranslateService();
|
||||||
authService = new AuthServiceStub();
|
authService = new AuthServiceStub();
|
||||||
|
authorizationService = jasmine.createSpyObj('authorizationService', {
|
||||||
|
isAuthenticated: observableOf(true)
|
||||||
|
});
|
||||||
|
groupsDataService = jasmine.createSpyObj('groupsDataService', {
|
||||||
|
findAllByHref: createSuccessfulRemoteDataObject$(createPaginatedList([])),
|
||||||
|
getGroupRegistryRouterLink: ''
|
||||||
|
});
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule,
|
imports: [CommonModule, NgbModule, FormsModule, ReactiveFormsModule, BrowserModule,
|
||||||
TranslateModule.forRoot({
|
TranslateModule.forRoot({
|
||||||
@@ -130,6 +142,8 @@ describe('EPersonFormComponent', () => {
|
|||||||
{ provide: RemoteDataBuildService, useValue: {} },
|
{ provide: RemoteDataBuildService, useValue: {} },
|
||||||
{ provide: HALEndpointService, useValue: {} },
|
{ provide: HALEndpointService, useValue: {} },
|
||||||
{ provide: AuthService, useValue: authService },
|
{ provide: AuthService, useValue: authService },
|
||||||
|
{ provide: AuthorizationDataService, useValue: authorizationService },
|
||||||
|
{ provide: GroupDataService, useValue: groupsDataService },
|
||||||
EPeopleRegistryComponent
|
EPeopleRegistryComponent
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
@@ -245,7 +245,7 @@ export class EPersonFormComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
this.canImpersonate$ = this.epersonService.getActiveEPerson().pipe(
|
this.canImpersonate$ = this.epersonService.getActiveEPerson().pipe(
|
||||||
switchMap((eperson) => this.authorizationService.isAuthenticated(FeatureType.LoginOnBehalfOf, eperson.self))
|
switchMap((eperson) => this.authorizationService.isAuthenticated(FeatureType.LoginOnBehalfOf, hasValue(eperson) ? eperson.self : undefined))
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -15,13 +15,18 @@ import { By } from '@angular/platform-browser';
|
|||||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
|
||||||
|
|
||||||
describe('AdminSidebarComponent', () => {
|
describe('AdminSidebarComponent', () => {
|
||||||
let comp: AdminSidebarComponent;
|
let comp: AdminSidebarComponent;
|
||||||
let fixture: ComponentFixture<AdminSidebarComponent>;
|
let fixture: ComponentFixture<AdminSidebarComponent>;
|
||||||
const menuService = new MenuServiceStub();
|
const menuService = new MenuServiceStub();
|
||||||
|
let authorizationService: AuthorizationDataService;
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
|
authorizationService = jasmine.createSpyObj('authorizationService', {
|
||||||
|
isAuthenticated: observableOf(true)
|
||||||
|
});
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [TranslateModule.forRoot(), NoopAnimationsModule, RouterTestingModule],
|
imports: [TranslateModule.forRoot(), NoopAnimationsModule, RouterTestingModule],
|
||||||
declarations: [AdminSidebarComponent],
|
declarations: [AdminSidebarComponent],
|
||||||
@@ -31,6 +36,7 @@ describe('AdminSidebarComponent', () => {
|
|||||||
{ provide: CSSVariableService, useClass: CSSVariableServiceStub },
|
{ provide: CSSVariableService, useClass: CSSVariableServiceStub },
|
||||||
{ provide: AuthService, useClass: AuthServiceStub },
|
{ provide: AuthService, useClass: AuthServiceStub },
|
||||||
{ provide: ActivatedRoute, useValue: {} },
|
{ provide: ActivatedRoute, useValue: {} },
|
||||||
|
{ provide: AuthorizationDataService, useValue: authorizationService },
|
||||||
{
|
{
|
||||||
provide: NgbModal, useValue: {
|
provide: NgbModal, useValue: {
|
||||||
open: () => {/*comment*/}
|
open: () => {/*comment*/}
|
||||||
|
@@ -0,0 +1,162 @@
|
|||||||
|
import { AuthorizationDataService } from './authorization-data.service';
|
||||||
|
import { SiteDataService } from '../site-data.service';
|
||||||
|
import { AuthService } from '../../auth/auth.service';
|
||||||
|
import { Site } from '../../shared/site.model';
|
||||||
|
import { EPerson } from '../../eperson/models/eperson.model';
|
||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { FindListOptions } from '../request.models';
|
||||||
|
import { FeatureType } from './feature-type';
|
||||||
|
import { hasValue } from '../../../shared/empty.util';
|
||||||
|
import { RequestParam } from '../../cache/models/request-param.model';
|
||||||
|
import { Authorization } from '../../shared/authorization.model';
|
||||||
|
import { RemoteData } from '../remote-data';
|
||||||
|
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
||||||
|
import { createPaginatedList } from '../../../shared/testing/utils.test';
|
||||||
|
|
||||||
|
describe('AuthorizationDataService', () => {
|
||||||
|
let service: AuthorizationDataService;
|
||||||
|
let siteService: SiteDataService;
|
||||||
|
let authService: AuthService;
|
||||||
|
|
||||||
|
let site: Site;
|
||||||
|
let ePerson: EPerson;
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
site = Object.assign(new Site(), {
|
||||||
|
id: 'test-site',
|
||||||
|
_links: {
|
||||||
|
self: { href: 'test-site-href' }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ePerson = Object.assign(new EPerson(), {
|
||||||
|
id: 'test-eperson',
|
||||||
|
uuid: 'test-eperson'
|
||||||
|
});
|
||||||
|
siteService = jasmine.createSpyObj('siteService', {
|
||||||
|
find: observableOf(site)
|
||||||
|
});
|
||||||
|
authService = {
|
||||||
|
isAuthenticated: () => observableOf(true),
|
||||||
|
getAuthenticatedUserFromStore: () => observableOf(ePerson)
|
||||||
|
} as AuthService;
|
||||||
|
service = new AuthorizationDataService(undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, authService, siteService);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
init();
|
||||||
|
spyOn(service, 'searchBy').and.returnValue(observableOf(undefined));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('searchByObject', () => {
|
||||||
|
const objectUrl = 'fake-object-url';
|
||||||
|
const ePersonUuid = 'fake-eperson-uuid';
|
||||||
|
|
||||||
|
function createExpected(objectUrl: string, ePersonUuid?: string, featureId?: FeatureType): FindListOptions {
|
||||||
|
const searchParams = [new RequestParam('uri', objectUrl)];
|
||||||
|
if (hasValue(featureId)) {
|
||||||
|
searchParams.push(new RequestParam('feature', featureId));
|
||||||
|
}
|
||||||
|
if (hasValue(ePersonUuid)) {
|
||||||
|
searchParams.push(new RequestParam('eperson', ePersonUuid));
|
||||||
|
}
|
||||||
|
return Object.assign(new FindListOptions(), { searchParams });
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('when no arguments are provided and a user is authenticated', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
service.searchByObject().subscribe();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call searchBy with the site\'s url and authenticated user\'s uuid', () => {
|
||||||
|
expect(service.searchBy).toHaveBeenCalledWith('object', createExpected(site.self, ePerson.uuid));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when no arguments except for a feature are provided and a user is authenticated', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
service.searchByObject(FeatureType.LoginOnBehalfOf).subscribe();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call searchBy with the site\'s url, authenticated user\'s uuid and the feature', () => {
|
||||||
|
expect(service.searchBy).toHaveBeenCalledWith('object', createExpected(site.self, ePerson.uuid, FeatureType.LoginOnBehalfOf));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when a feature and object url are provided, but no user uuid and a user is authenticated', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
service.searchByObject(FeatureType.LoginOnBehalfOf, objectUrl).subscribe();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call searchBy with the object\'s url, authenticated user\'s uuid and the feature', () => {
|
||||||
|
expect(service.searchBy).toHaveBeenCalledWith('object', createExpected(objectUrl, ePerson.uuid, FeatureType.LoginOnBehalfOf));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when all arguments are provided', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
service.searchByObject(FeatureType.LoginOnBehalfOf, objectUrl, ePersonUuid).subscribe();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call searchBy with the object\'s url, user\'s uuid and the feature', () => {
|
||||||
|
expect(service.searchBy).toHaveBeenCalledWith('object', createExpected(objectUrl, ePersonUuid, FeatureType.LoginOnBehalfOf));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when no arguments are provided and no user is authenticated', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
spyOn(authService, 'isAuthenticated').and.returnValue(observableOf(false));
|
||||||
|
service.searchByObject().subscribe();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call searchBy with the site\'s url', () => {
|
||||||
|
expect(service.searchBy).toHaveBeenCalledWith('object', createExpected(site.self));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('isAuthenticated', () => {
|
||||||
|
const validPayload = [
|
||||||
|
Object.assign(new Authorization())
|
||||||
|
]
|
||||||
|
const emptyPayload = [];
|
||||||
|
|
||||||
|
describe('when searchByObject returns a 401', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
spyOn(service, 'searchByObject').and.returnValue(observableOf(new RemoteData(false, false, true, undefined, undefined, 401)));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false', (done) => {
|
||||||
|
service.isAuthenticated().subscribe((result) => {
|
||||||
|
expect(result).toEqual(false);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when searchByObject returns an empty list', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
spyOn(service, 'searchByObject').and.returnValue(createSuccessfulRemoteDataObject$(createPaginatedList(emptyPayload)));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false', (done) => {
|
||||||
|
service.isAuthenticated().subscribe((result) => {
|
||||||
|
expect(result).toEqual(false);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when searchByObject returns a valid list', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
spyOn(service, 'searchByObject').and.returnValue(createSuccessfulRemoteDataObject$(createPaginatedList(validPayload)));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true', (done) => {
|
||||||
|
service.isAuthenticated().subscribe((result) => {
|
||||||
|
expect(result).toEqual(true);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@@ -0,0 +1,67 @@
|
|||||||
|
import { FeatureAuthorizationGuard } from './feature-authorization.guard';
|
||||||
|
import { AuthorizationDataService } from '../authorization-data.service';
|
||||||
|
import { FeatureType } from '../feature-type';
|
||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test implementation of abstract class FeatureAuthorizationGuard
|
||||||
|
* Provide the return values of the overwritten getters as constructor arguments
|
||||||
|
*/
|
||||||
|
class FeatureAuthorizationGuardImpl extends FeatureAuthorizationGuard {
|
||||||
|
constructor(protected authorizationService: AuthorizationDataService,
|
||||||
|
protected featureType: FeatureType,
|
||||||
|
protected objectUrl: string,
|
||||||
|
protected ePersonUuid: string) {
|
||||||
|
super(authorizationService);
|
||||||
|
}
|
||||||
|
|
||||||
|
getFeatureType(): FeatureType {
|
||||||
|
return this.featureType;
|
||||||
|
}
|
||||||
|
|
||||||
|
getObjectUrl(): string {
|
||||||
|
return this.objectUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
getEPersonUuid(): string {
|
||||||
|
return this.ePersonUuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('FeatureAuthorizationGuard', () => {
|
||||||
|
let guard: FeatureAuthorizationGuard;
|
||||||
|
let authorizationService: AuthorizationDataService;
|
||||||
|
|
||||||
|
let featureType: FeatureType;
|
||||||
|
let objectUrl: string;
|
||||||
|
let ePersonUuid: string;
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
featureType = FeatureType.LoginOnBehalfOf;
|
||||||
|
objectUrl = 'fake-object-url';
|
||||||
|
ePersonUuid = 'fake-eperson-uuid';
|
||||||
|
|
||||||
|
authorizationService = jasmine.createSpyObj('authorizationService', {
|
||||||
|
isAuthenticated: observableOf(true)
|
||||||
|
});
|
||||||
|
guard = new FeatureAuthorizationGuardImpl(authorizationService, featureType, objectUrl, ePersonUuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
init();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('canActivate', () => {
|
||||||
|
it('should call authorizationService.isAuthenticated with the appropriate arguments', () => {
|
||||||
|
guard.canActivate(undefined, undefined).subscribe();
|
||||||
|
expect(authorizationService.isAuthenticated).toHaveBeenCalledWith(featureType, objectUrl, ePersonUuid);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('canLoad', () => {
|
||||||
|
it('should call authorizationService.isAuthenticated with the appropriate arguments', () => {
|
||||||
|
guard.canLoad(undefined, undefined).subscribe();
|
||||||
|
expect(authorizationService.isAuthenticated).toHaveBeenCalledWith(featureType, objectUrl, ePersonUuid);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Reference in New Issue
Block a user