mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00

- Fixed issue making it impossible to add new relationships until the page is refreshed after deleting an existing one (only when you refreshed the page after creating the initial relationship) - Fixed NPE in DsDynamicLookupRelationModalComponent - Grouped buttons on relationship page in order to assure that they always have the same behaviour
302 lines
12 KiB
TypeScript
302 lines
12 KiB
TypeScript
import { TestBed } from '@angular/core/testing';
|
|
import { TranslateModule } from '@ngx-translate/core';
|
|
import { of as observableOf } from 'rxjs';
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
|
|
import { EntityTypeDataService } from '../../../core/data/entity-type-data.service';
|
|
import { ItemDataService } from '../../../core/data/item-data.service';
|
|
import { FieldChangeType } from '../../../core/data/object-updates/field-change-type.model';
|
|
import { FieldUpdate } from '../../../core/data/object-updates/field-update.model';
|
|
import { FieldUpdates } from '../../../core/data/object-updates/field-updates.model';
|
|
import {
|
|
DeleteRelationship,
|
|
RelationshipIdentifiable,
|
|
} from '../../../core/data/object-updates/object-updates.reducer';
|
|
import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service';
|
|
import { RelationshipDataService } from '../../../core/data/relationship-data.service';
|
|
import { Item } from '../../../core/shared/item.model';
|
|
import { ItemType } from '../../../core/shared/item-relationships/item-type.model';
|
|
import { Relationship } from '../../../core/shared/item-relationships/relationship.model';
|
|
import { RelationshipType } from '../../../core/shared/item-relationships/relationship-type.model';
|
|
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
|
import {
|
|
createFailedRemoteDataObject,
|
|
createSuccessfulRemoteDataObject,
|
|
createSuccessfulRemoteDataObject$,
|
|
} from '../../../shared/remote-data.utils';
|
|
import { EntityTypeDataServiceStub } from '../../../shared/testing/entity-type-data.service.stub';
|
|
import { ItemDataServiceStub } from '../../../shared/testing/item-data.service.stub';
|
|
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub';
|
|
import { ObjectUpdatesServiceStub } from '../../../shared/testing/object-updates.service.stub';
|
|
import { RelationshipDataServiceStub } from '../../../shared/testing/relationship-data.service.stub';
|
|
import { EditItemRelationshipsService } from './edit-item-relationships.service';
|
|
|
|
describe('EditItemRelationshipsService', () => {
|
|
let service: EditItemRelationshipsService;
|
|
|
|
let itemService: ItemDataServiceStub;
|
|
let objectUpdatesService: ObjectUpdatesServiceStub;
|
|
let notificationsService: NotificationsServiceStub;
|
|
let relationshipService: RelationshipDataServiceStub;
|
|
let entityTypeDataService: EntityTypeDataServiceStub;
|
|
|
|
let currentItem: Item;
|
|
|
|
let relationshipItem1: Item;
|
|
let relationshipIdentifiable1: RelationshipIdentifiable;
|
|
let relationship1: Relationship;
|
|
|
|
let relationshipItem2: Item;
|
|
let relationshipIdentifiable2: RelationshipIdentifiable;
|
|
let relationship2: Relationship;
|
|
|
|
let orgUnitType: ItemType;
|
|
let orgUnitToOrgUnitType: RelationshipType;
|
|
|
|
beforeEach(() => {
|
|
itemService = new ItemDataServiceStub();
|
|
objectUpdatesService = new ObjectUpdatesServiceStub();
|
|
notificationsService = new NotificationsServiceStub();
|
|
relationshipService = new RelationshipDataServiceStub();
|
|
entityTypeDataService = new EntityTypeDataServiceStub();
|
|
|
|
TestBed.configureTestingModule({
|
|
imports: [
|
|
TranslateModule.forRoot(),
|
|
],
|
|
providers: [
|
|
{ provide: ItemDataService, useValue: itemService },
|
|
{ provide: ObjectUpdatesService, useValue: objectUpdatesService },
|
|
{ provide: NotificationsService, useValue: notificationsService },
|
|
{ provide: RelationshipDataService, useValue: relationshipService },
|
|
{ provide: EntityTypeDataService, useValue: entityTypeDataService },
|
|
],
|
|
});
|
|
service = TestBed.inject(EditItemRelationshipsService);
|
|
});
|
|
|
|
beforeEach(() => {
|
|
currentItem = Object.assign(new Item(), {
|
|
uuid: uuidv4(),
|
|
metadata: {
|
|
'dspace.entity.type': 'OrgUnit',
|
|
},
|
|
_links: {
|
|
self: {
|
|
href: 'selfLink1',
|
|
},
|
|
},
|
|
});
|
|
|
|
relationshipItem1 = Object.assign(new Item(), {
|
|
uuid: uuidv4(),
|
|
metadata: {
|
|
'dspace.entity.type': 'OrgUnit',
|
|
},
|
|
_links: {
|
|
self: {
|
|
href: 'selfLink2',
|
|
},
|
|
},
|
|
});
|
|
relationshipIdentifiable1 = {
|
|
originalItem: currentItem,
|
|
relatedItem: relationshipItem1,
|
|
type: orgUnitToOrgUnitType,
|
|
uuid: `1-${relationshipItem1.uuid}`,
|
|
} as RelationshipIdentifiable;
|
|
relationship1 = Object.assign(new Relationship(), {
|
|
_links: {
|
|
leftItem: currentItem._links.self,
|
|
rightItem: relationshipItem1._links.self,
|
|
},
|
|
});
|
|
|
|
relationshipItem2 = Object.assign(new Item(), {
|
|
uuid: uuidv4(),
|
|
metadata: {
|
|
'dspace.entity.type': 'OrgUnit',
|
|
},
|
|
_links: {
|
|
self: {
|
|
href: 'selfLink3',
|
|
},
|
|
},
|
|
});
|
|
relationshipIdentifiable2 = {
|
|
originalItem: currentItem,
|
|
relatedItem: relationshipItem2,
|
|
type: orgUnitToOrgUnitType,
|
|
uuid: `1-${relationshipItem2.uuid}`,
|
|
} as RelationshipIdentifiable;
|
|
relationship2 = Object.assign(new Relationship(), {
|
|
_links: {
|
|
leftItem: currentItem._links.self,
|
|
rightItem: relationshipItem2._links.self,
|
|
},
|
|
});
|
|
|
|
orgUnitType = Object.assign(new ItemType(), {
|
|
id: '2',
|
|
label: 'OrgUnit',
|
|
});
|
|
orgUnitToOrgUnitType = Object.assign(new RelationshipType(), {
|
|
id: '1',
|
|
leftMaxCardinality: null,
|
|
leftMinCardinality: 0,
|
|
leftType: createSuccessfulRemoteDataObject$(orgUnitType),
|
|
leftwardType: 'isOrgUnitOfOrgUnit',
|
|
rightMaxCardinality: null,
|
|
rightMinCardinality: 0,
|
|
rightType: createSuccessfulRemoteDataObject$(orgUnitType),
|
|
rightwardType: 'isOrgUnitOfOrgUnit',
|
|
uuid: 'relationshiptype-1',
|
|
});
|
|
});
|
|
|
|
describe('submit', () => {
|
|
let fieldUpdateAddRelationship1: FieldUpdate;
|
|
let fieldUpdateRemoveRelationship2: FieldUpdate;
|
|
|
|
beforeEach(() => {
|
|
fieldUpdateAddRelationship1 = {
|
|
changeType: FieldChangeType.ADD,
|
|
field: relationshipIdentifiable1,
|
|
};
|
|
fieldUpdateRemoveRelationship2 = {
|
|
changeType: FieldChangeType.REMOVE,
|
|
field: relationshipIdentifiable2,
|
|
};
|
|
|
|
spyOn(service, 'addRelationship').withArgs(relationshipIdentifiable1).and.returnValue(createSuccessfulRemoteDataObject$(relationship1));
|
|
spyOn(service, 'deleteRelationship').withArgs(relationshipIdentifiable2 as DeleteRelationship).and.returnValue(createSuccessfulRemoteDataObject$({}));
|
|
spyOn(itemService, 'invalidateByHref').and.callThrough();
|
|
});
|
|
|
|
it('should support performing multiple relationships manipulations in one submit() call', () => {
|
|
spyOn(objectUpdatesService, 'getFieldUpdates').and.returnValue(observableOf({
|
|
[`1-${relationshipItem1.uuid}`]: fieldUpdateAddRelationship1,
|
|
[`1-${relationshipItem2.uuid}`]: fieldUpdateRemoveRelationship2,
|
|
} as FieldUpdates));
|
|
service.submit(currentItem, `/entities/orgunit/${currentItem.uuid}/edit/relationships`);
|
|
|
|
expect(service.addRelationship).toHaveBeenCalledWith(relationshipIdentifiable1);
|
|
expect(service.deleteRelationship).toHaveBeenCalledWith(relationshipIdentifiable2 as DeleteRelationship);
|
|
|
|
expect(itemService.invalidateByHref).toHaveBeenCalledWith(currentItem.self);
|
|
expect(itemService.invalidateByHref).toHaveBeenCalledWith(relationshipItem1.self);
|
|
|
|
expect(notificationsService.success).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|
|
|
|
describe('deleteRelationship', () => {
|
|
beforeEach(() => {
|
|
spyOn(relationshipService, 'deleteRelationship').and.callThrough();
|
|
});
|
|
|
|
it('should pass "all" as copyVirtualMetadata when the user want to keep the data on both sides', () => {
|
|
service.deleteRelationship({
|
|
uuid: relationshipItem1.uuid,
|
|
keepLeftVirtualMetadata: true,
|
|
keepRightVirtualMetadata: true,
|
|
} as DeleteRelationship);
|
|
|
|
expect(relationshipService.deleteRelationship).toHaveBeenCalledWith(relationshipItem1.uuid, 'all', false);
|
|
});
|
|
|
|
it('should pass "left" as copyVirtualMetadata when the user only want to keep the data on the left side', () => {
|
|
service.deleteRelationship({
|
|
uuid: relationshipItem1.uuid,
|
|
keepLeftVirtualMetadata: true,
|
|
keepRightVirtualMetadata: false,
|
|
} as DeleteRelationship);
|
|
|
|
expect(relationshipService.deleteRelationship).toHaveBeenCalledWith(relationshipItem1.uuid, 'left', false);
|
|
});
|
|
|
|
it('should pass "right" as copyVirtualMetadata when the user only want to keep the data on the right side', () => {
|
|
service.deleteRelationship({
|
|
uuid: relationshipItem1.uuid,
|
|
keepLeftVirtualMetadata: false,
|
|
keepRightVirtualMetadata: true,
|
|
} as DeleteRelationship);
|
|
|
|
expect(relationshipService.deleteRelationship).toHaveBeenCalledWith(relationshipItem1.uuid, 'right', false);
|
|
});
|
|
|
|
it('should pass "none" as copyVirtualMetadata when the user doesn\'t want to keep the virtual metadata', () => {
|
|
service.deleteRelationship({
|
|
uuid: relationshipItem1.uuid,
|
|
keepLeftVirtualMetadata: false,
|
|
keepRightVirtualMetadata: false,
|
|
} as DeleteRelationship);
|
|
|
|
expect(relationshipService.deleteRelationship).toHaveBeenCalledWith(relationshipItem1.uuid, 'none', false);
|
|
});
|
|
});
|
|
|
|
describe('addRelationship', () => {
|
|
beforeEach(() => {
|
|
spyOn(relationshipService, 'addRelationship').and.callThrough();
|
|
});
|
|
|
|
it('should call the addRelationship from relationshipService correctly when original item is on the right', () => {
|
|
service.addRelationship({
|
|
originalItem: currentItem,
|
|
originalIsLeft: false,
|
|
relatedItem: relationshipItem1,
|
|
type: orgUnitToOrgUnitType,
|
|
uuid: `1-${relationshipItem1.uuid}`,
|
|
} as RelationshipIdentifiable);
|
|
expect(relationshipService.addRelationship).toHaveBeenCalledWith(orgUnitToOrgUnitType.id, relationshipItem1, currentItem, undefined, null, false);
|
|
});
|
|
|
|
it('should call the addRelationship from relationshipService correctly when original item is on the left', () => {
|
|
service.addRelationship({
|
|
originalItem: currentItem,
|
|
originalIsLeft: true,
|
|
relatedItem: relationshipItem1,
|
|
type: orgUnitToOrgUnitType,
|
|
uuid: `1-${relationshipItem1.uuid}`,
|
|
} as RelationshipIdentifiable);
|
|
|
|
expect(relationshipService.addRelationship).toHaveBeenCalledWith(orgUnitToOrgUnitType.id, currentItem, relationshipItem1, null, undefined, false);
|
|
});
|
|
});
|
|
|
|
describe('displayNotifications', () => {
|
|
it('should show one success notification when multiple requests succeeded', () => {
|
|
service.displayNotifications([
|
|
createSuccessfulRemoteDataObject({}),
|
|
createSuccessfulRemoteDataObject({}),
|
|
]);
|
|
|
|
expect(notificationsService.success).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('should show one success notification even when some requests failed', () => {
|
|
service.displayNotifications([
|
|
createSuccessfulRemoteDataObject({}),
|
|
createFailedRemoteDataObject('Request Failed'),
|
|
createSuccessfulRemoteDataObject({}),
|
|
]);
|
|
|
|
expect(notificationsService.success).toHaveBeenCalledTimes(1);
|
|
expect(notificationsService.error).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('should show a separate error notification for each failed request', () => {
|
|
service.displayNotifications([
|
|
createSuccessfulRemoteDataObject({}),
|
|
createFailedRemoteDataObject('Request Failed 1'),
|
|
createSuccessfulRemoteDataObject({}),
|
|
createFailedRemoteDataObject('Request Failed 2'),
|
|
]);
|
|
|
|
expect(notificationsService.success).toHaveBeenCalledTimes(1);
|
|
expect(notificationsService.error).toHaveBeenCalledTimes(2);
|
|
});
|
|
});
|
|
});
|