115046: Fixed failing tests & added new test to cover added code

(cherry picked from commit 479adf6519)
This commit is contained in:
Alexandre Vryghem
2024-05-14 17:46:43 +02:00
parent 71d033bf50
commit 1338712048
12 changed files with 668 additions and 190 deletions

View File

@@ -237,7 +237,7 @@ export class RelationshipDataService extends IdentifiableDataService<Relationshi
* Method to remove an item that's part of a relationship from the cache
* @param item The item to remove from the cache
*/
public refreshRelationshipItemsInCache(item) {
public refreshRelationshipItemsInCache(item: Item): void {
this.objectCache.remove(item._links.self.href);
this.requestService.removeByHrefSubstring(item.uuid);
observableCombineLatest([

View File

@@ -1,16 +1,303 @@
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(() => {
TestBed.configureTestingModule({});
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);
});
it('should be created', () => {
expect(service).toBeTruthy();
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);
// TODO currently this isn't done yet
// expect(itemService.invalidateByHref).toHaveBeenCalledWith(relationshipItem2.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);
});
});
});

View File

@@ -5,6 +5,7 @@ import {
BehaviorSubject,
EMPTY,
Observable,
Subscription,
} from 'rxjs';
import {
concatMap,
@@ -120,7 +121,7 @@ export class EditItemRelationshipsService {
/**
* Sends all initial values of this item to the object updates service
*/
public initializeOriginalFields(item: Item, url: string) {
public initializeOriginalFields(item: Item, url: string): Subscription {
return this.relationshipService.getRelatedItems(item).pipe(
take(1),
).subscribe((items: Item[]) => {
@@ -168,7 +169,7 @@ export class EditItemRelationshipsService {
* - Success notification in case there's at least one successful response
* @param responses
*/
displayNotifications(responses: RemoteData<NoContent>[]) {
displayNotifications(responses: RemoteData<NoContent>[]): void {
const failedResponses = responses.filter((response: RemoteData<NoContent>) => response.hasFailed);
const successfulResponses = responses.filter((response: RemoteData<NoContent>) => response.hasSucceeded);
@@ -186,7 +187,7 @@ export class EditItemRelationshipsService {
* Get translated notification title
* @param key
*/
getNotificationTitle(key: string) {
getNotificationTitle(key: string): string {
return this.translateService.instant(this.notificationsPrefix + key + '.title');
}
@@ -194,7 +195,7 @@ export class EditItemRelationshipsService {
* Get translated notification content
* @param key
*/
getNotificationContent(key: string) {
getNotificationContent(key: string): string {
return this.translateService.instant(this.notificationsPrefix + key + '.content');
}

View File

@@ -10,19 +10,17 @@ import {
import { By } from '@angular/platform-browser';
import {
ActivatedRoute,
Router,
RouterModule,
} from '@angular/router';
import { provideMockStore } from '@ngrx/store/testing';
import { TranslateModule } from '@ngx-translate/core';
import { cold } from 'jasmine-marbles';
import { of as observableOf } from 'rxjs';
import { AuthRequestService } from 'src/app/core/auth/auth-request.service';
import { CookieService } from 'src/app/core/services/cookie.service';
import { HardRedirectService } from 'src/app/core/services/hard-redirect.service';
import { ActivatedRouteStub } from 'src/app/shared/testing/active-router.stub';
import { AuthRequestServiceStub } from 'src/app/shared/testing/auth-request-service.stub';
import { APP_CONFIG } from '../../../../../config/app-config.interface';
import { environment } from '../../../../../environments/environment.test';
import { REQUEST } from '../../../../../express.tokens';
import { AuthRequestService } from '../../../../core/auth/auth-request.service';
import { LinkService } from '../../../../core/cache/builders/link.service';
import { ConfigurationDataService } from '../../../../core/data/configuration-data.service';
import { FieldChangeType } from '../../../../core/data/object-updates/field-change-type.model';
@@ -31,6 +29,8 @@ import { RelationshipDataService } from '../../../../core/data/relationship-data
import { RelationshipTypeDataService } from '../../../../core/data/relationship-type-data.service';
import { GroupDataService } from '../../../../core/eperson/group-data.service';
import { PaginationService } from '../../../../core/pagination/pagination.service';
import { CookieService } from '../../../../core/services/cookie.service';
import { HardRedirectService } from '../../../../core/services/hard-redirect.service';
import { LinkHeadService } from '../../../../core/services/link-head.service';
import { ConfigurationProperty } from '../../../../core/shared/configuration-property.model';
import { Item } from '../../../../core/shared/item.model';
@@ -40,51 +40,55 @@ import { RelationshipType } from '../../../../core/shared/item-relationships/rel
import { SearchConfigurationService } from '../../../../core/shared/search/search-configuration.service';
import { XSRFService } from '../../../../core/xsrf/xsrf.service';
import { HostWindowService } from '../../../../shared/host-window.service';
import { RouterMock } from '../../../../shared/mocks/router.mock';
import { SelectableListService } from '../../../../shared/object-list/selectable-list/selectable-list.service';
import { PaginationComponent } from '../../../../shared/pagination/pagination.component';
import { PaginationComponentOptions } from '../../../../shared/pagination/pagination-component-options.model';
import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils';
import { ActivatedRouteStub } from '../../../../shared/testing/active-router.stub';
import { AuthRequestServiceStub } from '../../../../shared/testing/auth-request-service.stub';
import { EditItemRelationshipsServiceStub } from '../../../../shared/testing/edit-item-relationships.service.stub';
import { HostWindowServiceStub } from '../../../../shared/testing/host-window-service.stub';
import { PaginationServiceStub } from '../../../../shared/testing/pagination-service.stub';
import { SearchConfigurationServiceStub } from '../../../../shared/testing/search-configuration-service.stub';
import { createPaginatedList } from '../../../../shared/testing/utils.test';
import { EditItemRelationshipsService } from '../edit-item-relationships.service';
import { EditRelationshipListComponent } from './edit-relationship-list.component';
let comp: EditRelationshipListComponent;
let fixture: ComponentFixture<EditRelationshipListComponent>;
let de: DebugElement;
let linkService;
let objectUpdatesService;
let relationshipService;
let selectableListService;
let paginationService;
let hostWindowService;
let hardRedirectService;
const relationshipTypeService = {};
const url = 'http://test-url.com/test-url';
let item;
let entityType;
let relatedEntityType;
let author1;
let author2;
let fieldUpdate1;
let fieldUpdate2;
let relationships;
let relationshipType;
let paginationOptions;
describe('EditRelationshipListComponent', () => {
let comp: EditRelationshipListComponent;
let fixture: ComponentFixture<EditRelationshipListComponent>;
let de: DebugElement;
let linkService;
let objectUpdatesService;
let relationshipService;
let selectableListService;
let paginationService: PaginationServiceStub;
let hostWindowService: HostWindowServiceStub;
let hardRedirectService;
const relationshipTypeService = {};
let editItemRelationshipsService: EditItemRelationshipsServiceStub;
const url = 'http://test-url.com/test-url';
let itemLeft: Item;
let entityTypeLeft: ItemType;
let entityTypeRight: ItemType;
let itemRight1: Item;
let itemRight2: Item;
let fieldUpdate1;
let fieldUpdate2;
let relationships: Relationship[];
let relationshipType: RelationshipType;
let paginationOptions: PaginationComponentOptions;
const resetComponent = () => {
fixture = TestBed.createComponent(EditRelationshipListComponent);
comp = fixture.componentInstance;
de = fixture.debugElement;
comp.item = item;
comp.itemType = entityType;
comp.item = itemLeft;
comp.itemType = entityTypeLeft;
comp.url = url;
comp.relationshipType = relationshipType;
comp.hasChanges = observableOf(false);
@@ -101,29 +105,26 @@ describe('EditRelationshipListComponent', () => {
},
};
hardRedirectService = jasmine.createSpyObj('hardRedirectService', ['redirect']);
beforeEach(waitForAsync(() => {
entityType = Object.assign(new ItemType(), {
id: 'Publication',
uuid: 'Publication',
label: 'Publication',
function init(leftType: string, rightType: string): void {
entityTypeLeft = Object.assign(new ItemType(), {
id: leftType,
uuid: leftType,
label: leftType,
});
relatedEntityType = Object.assign(new ItemType(), {
id: 'Author',
uuid: 'Author',
label: 'Author',
entityTypeRight = Object.assign(new ItemType(), {
id: rightType,
uuid: rightType,
label: rightType,
});
relationshipType = Object.assign(new RelationshipType(), {
id: '1',
uuid: '1',
leftType: createSuccessfulRemoteDataObject$(entityType),
rightType: createSuccessfulRemoteDataObject$(relatedEntityType),
leftwardType: 'isAuthorOfPublication',
rightwardType: 'isPublicationOfAuthor',
leftType: createSuccessfulRemoteDataObject$(entityTypeLeft),
rightType: createSuccessfulRemoteDataObject$(entityTypeRight),
leftwardType: `is${rightType}Of${leftType}`,
rightwardType: `is${leftType}Of${rightType}`,
});
paginationOptions = Object.assign(new PaginationComponentOptions(), {
@@ -132,13 +133,13 @@ describe('EditRelationshipListComponent', () => {
currentPage: 1,
});
author1 = Object.assign(new Item(), {
id: 'author1',
uuid: 'author1',
itemRight1 = Object.assign(new Item(), {
id: `${rightType}-1`,
uuid: `${rightType}-1`,
});
author2 = Object.assign(new Item(), {
id: 'author2',
uuid: 'author2',
itemRight2 = Object.assign(new Item(), {
id: `${rightType}-2`,
uuid: `${rightType}-2`,
});
relationships = [
@@ -147,25 +148,25 @@ describe('EditRelationshipListComponent', () => {
id: '2',
uuid: '2',
relationshipType: createSuccessfulRemoteDataObject$(relationshipType),
leftItem: createSuccessfulRemoteDataObject$(item),
rightItem: createSuccessfulRemoteDataObject$(author1),
leftItem: createSuccessfulRemoteDataObject$(itemLeft),
rightItem: createSuccessfulRemoteDataObject$(itemRight1),
}),
Object.assign(new Relationship(), {
self: url + '/3',
id: '3',
uuid: '3',
relationshipType: createSuccessfulRemoteDataObject$(relationshipType),
leftItem: createSuccessfulRemoteDataObject$(item),
rightItem: createSuccessfulRemoteDataObject$(author2),
leftItem: createSuccessfulRemoteDataObject$(itemLeft),
rightItem: createSuccessfulRemoteDataObject$(itemRight2),
}),
];
item = Object.assign(new Item(), {
itemLeft = Object.assign(new Item(), {
_links: {
self: { href: 'fake-item-url/publication' },
},
id: 'publication',
uuid: 'publication',
id: `1-${leftType}`,
uuid: `1-${leftType}`,
relationships: createSuccessfulRemoteDataObject$(createPaginatedList(relationships)),
});
@@ -197,7 +198,7 @@ describe('EditRelationshipListComponent', () => {
relationshipService = jasmine.createSpyObj('relationshipService',
{
getRelatedItemsByLabel: createSuccessfulRemoteDataObject$(createPaginatedList([author1, author2])),
getRelatedItemsByLabel: createSuccessfulRemoteDataObject$(createPaginatedList([itemRight1, itemRight2])),
getItemRelationshipsByLabel: createSuccessfulRemoteDataObject$(createPaginatedList(relationships)),
isLeftItem: observableOf(true),
},
@@ -233,14 +234,14 @@ describe('EditRelationshipListComponent', () => {
})),
});
const environmentUseThumbs = {
browseBy: {
showThumbnails: true,
},
};
editItemRelationshipsService = new EditItemRelationshipsServiceStub();
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), EditRelationshipListComponent],
imports: [
EditRelationshipListComponent,
RouterModule.forRoot([]),
TranslateModule.forRoot(),
],
providers: [
provideMockStore({ initialState }),
{ provide: ObjectUpdatesService, useValue: objectUpdatesService },
@@ -251,15 +252,15 @@ describe('EditRelationshipListComponent', () => {
{ provide: HostWindowService, useValue: hostWindowService },
{ provide: RelationshipTypeDataService, useValue: relationshipTypeService },
{ provide: GroupDataService, useValue: groupDataService },
{ provide: Router, useValue: new RouterMock() },
{ provide: LinkHeadService, useValue: linkHeadService },
{ provide: ConfigurationDataService, useValue: configurationDataService },
{ provide: SearchConfigurationService, useValue: new SearchConfigurationServiceStub() },
{ provide: EditItemRelationshipsService, useValue: editItemRelationshipsService },
{ provide: ActivatedRoute, useValue: new ActivatedRouteStub() },
{ provide: AuthRequestService, useValue: new AuthRequestServiceStub() },
{ provide: HardRedirectService, useValue: hardRedirectService },
{ provide: XSRFService, useValue: {} },
{ provide: APP_CONFIG, useValue: environmentUseThumbs },
{ provide: APP_CONFIG, useValue: environment },
{ provide: REQUEST, useValue: {} },
CookieService,
], schemas: [
@@ -268,7 +269,10 @@ describe('EditRelationshipListComponent', () => {
}).compileComponents();
resetComponent();
}));
}
describe('Publication - Author relationship', () => {
beforeEach(waitForAsync(() => init('Publication', 'Author')));
describe('changeType is REMOVE', () => {
beforeEach(() => {
@@ -316,8 +320,8 @@ describe('EditRelationshipListComponent', () => {
relationshipType = Object.assign(new RelationshipType(), {
id: '1',
uuid: '1',
leftType: createSuccessfulRemoteDataObject$(entityType), // publication
rightType: createSuccessfulRemoteDataObject$(relatedEntityType), // author
leftType: createSuccessfulRemoteDataObject$(entityTypeLeft), // publication
rightType: createSuccessfulRemoteDataObject$(entityTypeRight), // author
leftwardType: 'isAuthorOfPublication',
rightwardType: 'isPublicationOfAuthor',
});
@@ -340,8 +344,8 @@ describe('EditRelationshipListComponent', () => {
relationshipType = Object.assign(new RelationshipType(), {
id: '1',
uuid: '1',
leftType: createSuccessfulRemoteDataObject$(relatedEntityType), // author
rightType: createSuccessfulRemoteDataObject$(entityType), // publication
leftType: createSuccessfulRemoteDataObject$(entityTypeRight), // author
rightType: createSuccessfulRemoteDataObject$(entityTypeLeft), // publication
leftwardType: 'isPublicationOfAuthor',
rightwardType: 'isAuthorOfPublication',
});
@@ -377,5 +381,15 @@ describe('EditRelationshipListComponent', () => {
});
});
});
describe('OrgUnit - OrgUnit relationship', () => {
beforeEach(waitForAsync(() => init('OrgUnit', 'OrgUnit')));
it('should emit the relatedEntityType$ even for same entity relationships', () => {
expect(comp.relatedEntityType$).toBeObservable(cold('(a|)', {
a: entityTypeRight,
}));
});
});
});

View File

@@ -50,7 +50,6 @@ import { RelationshipIdentifiable } from '../../../../core/data/object-updates/o
import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service';
import { PaginatedList } from '../../../../core/data/paginated-list.model';
import { RelationshipDataService } from '../../../../core/data/relationship-data.service';
import { RelationshipTypeDataService } from '../../../../core/data/relationship-type-data.service';
import { RemoteData } from '../../../../core/data/remote-data';
import { PaginationService } from '../../../../core/pagination/pagination.service';
import { Collection } from '../../../../core/shared/collection.model';
@@ -146,7 +145,7 @@ export class EditRelationshipListComponent implements OnInit, OnDestroy {
*/
private currentItemIsLeftItem$: BehaviorSubject<boolean> = new BehaviorSubject(undefined);
private relatedEntityType$: Observable<ItemType>;
relatedEntityType$: Observable<ItemType>;
/**
* The translation key for the entity type
@@ -208,7 +207,6 @@ export class EditRelationshipListComponent implements OnInit, OnDestroy {
protected objectUpdatesService: ObjectUpdatesService,
protected linkService: LinkService,
protected relationshipService: RelationshipDataService,
protected relationshipTypeService: RelationshipTypeDataService,
protected modalService: NgbModal,
protected paginationService: PaginationService,
protected selectableListService: SelectableListService,

View File

@@ -44,6 +44,7 @@ import {
createSuccessfulRemoteDataObject,
createSuccessfulRemoteDataObject$,
} from '../../../shared/remote-data.utils';
import { ItemDataServiceStub } from '../../../shared/testing/item-data.service.stub';
import { relationshipTypes } from '../../../shared/testing/relationship-types.mock';
import { RouterStub } from '../../../shared/testing/router.stub';
import { createPaginatedList } from '../../../shared/testing/utils.test';
@@ -72,7 +73,7 @@ const notificationsService = jasmine.createSpyObj('notificationsService',
const router = new RouterStub();
let relationshipTypeService;
let routeStub;
let itemService;
let itemService: ItemDataServiceStub;
const url = 'http://test-url.com/test-url';
router.url = url;
@@ -157,10 +158,7 @@ describe('ItemRelationshipsComponent', () => {
changeType: FieldChangeType.REMOVE,
};
itemService = jasmine.createSpyObj('itemService', {
findByHref: createSuccessfulRemoteDataObject$(item),
findById: createSuccessfulRemoteDataObject$(item),
});
itemService = new ItemDataServiceStub();
routeStub = {
data: observableOf({}),
parent: {
@@ -251,6 +249,8 @@ describe('ItemRelationshipsComponent', () => {
}));
beforeEach(() => {
spyOn(itemService, 'findByHref').and.returnValue(item);
spyOn(itemService, 'findById').and.returnValue(item);
fixture = TestBed.createComponent(ItemRelationshipsComponent);
comp = fixture.componentInstance;
de = fixture.debugElement;

View File

@@ -4,12 +4,19 @@ import {
} from 'rxjs';
import { CacheableObject } from '../../core/cache/cacheable-object.model';
import { RemoteData } from '../../core/data/remote-data';
import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils';
import { FollowLinkConfig } from '../utils/follow-link-config.model';
/**
* Stub class for {@link BaseDataService}
*/
export abstract class BaseDataServiceStub<T extends CacheableObject> {
findByHref(_href$: string | Observable<string>, _useCachedVersionIfAvailable = true, _reRequestOnStale = true, ..._linksToFollow: FollowLinkConfig<T>[]): Observable<RemoteData<T>> {
return createSuccessfulRemoteDataObject$(undefined);
}
invalidateByHref(_href: string): Observable<boolean> {
return observableOf(true);
}

View File

@@ -0,0 +1,48 @@
/* eslint-disable no-empty, @typescript-eslint/no-empty-function */
import {
Observable,
Subscription,
} from 'rxjs';
import {
DeleteRelationship,
RelationshipIdentifiable,
} from '../../core/data/object-updates/object-updates.reducer';
import { RemoteData } from '../../core/data/remote-data';
import { Item } from '../../core/shared/item.model';
import { Relationship } from '../../core/shared/item-relationships/relationship.model';
import { NoContent } from '../../core/shared/NoContent.model';
import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils';
/**
* Stub class of {@link EditItemRelationshipsService}
*/
export class EditItemRelationshipsServiceStub {
submit(_item: Item, _url: string): void {
}
initializeOriginalFields(_item: Item, _url: string): Subscription {
return new Subscription();
}
deleteRelationship(_deleteRelationship: DeleteRelationship): Observable<RemoteData<NoContent>> {
return createSuccessfulRemoteDataObject$({});
}
addRelationship(_addRelationship: RelationshipIdentifiable): Observable<RemoteData<Relationship>> {
return createSuccessfulRemoteDataObject$(undefined);
}
displayNotifications(_responses: RemoteData<NoContent>[]): void {
}
getNotificationTitle(_key: string): string {
return '';
}
getNotificationContent(_key: string): string {
return '';
}
}

View File

@@ -0,0 +1,5 @@
/**
* Stub class of {@link EntityTypeDataService}
*/
export class EntityTypeDataServiceStub {
}

View File

@@ -0,0 +1,8 @@
import { Item } from '../../core/shared/item.model';
import { IdentifiableDataServiceStub } from './identifiable-data-service.stub';
/**
* Stub class of {@link ItemDataService}
*/
export class ItemDataServiceStub extends IdentifiableDataServiceStub<Item> {
}

View File

@@ -0,0 +1,24 @@
/* eslint-disable no-empty, @typescript-eslint/no-empty-function */
import {
Observable,
of as observableOf,
} from 'rxjs';
import { FieldUpdates } from '../../core/data/object-updates/field-updates.model';
import { Identifiable } from '../../core/data/object-updates/identifiable.model';
import { PatchOperationService } from '../../core/data/object-updates/patch-operation-service/patch-operation.service';
import { GenericConstructor } from '../../core/shared/generic-constructor';
/**
* Stub class of {@link ObjectUpdatesService}
*/
export class ObjectUpdatesServiceStub {
initialize(_url: string, _fields: Identifiable[], _lastModified: Date, _patchOperationService?: GenericConstructor<PatchOperationService>): void {
}
getFieldUpdates(_url: string, _initialFields: Identifiable[], _ignoreStates?: boolean): Observable<FieldUpdates> {
return observableOf({});
}
}

View File

@@ -0,0 +1,86 @@
/* eslint-disable no-empty, @typescript-eslint/no-empty-function */
import {
Observable,
of as observableOf,
} from 'rxjs';
import { FindListOptions } from '../../core/data/find-list-options.model';
import { PaginatedList } from '../../core/data/paginated-list.model';
import { RemoteData } from '../../core/data/remote-data';
import { DSpaceObject } from '../../core/shared/dspace-object.model';
import { Item } from '../../core/shared/item.model';
import { Relationship } from '../../core/shared/item-relationships/relationship.model';
import { MetadataValue } from '../../core/shared/metadata.models';
import { MetadataRepresentation } from '../../core/shared/metadata-representation/metadata-representation.model';
import { NoContent } from '../../core/shared/NoContent.model';
import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils';
import { FollowLinkConfig } from '../utils/follow-link-config.model';
/**
* Stub class of {@link RelationshipDataService}
*/
export class RelationshipDataServiceStub {
deleteRelationship(_id: string, _copyVirtualMetadata: string, _shouldRefresh = true): Observable<RemoteData<NoContent>> {
return createSuccessfulRemoteDataObject$({});
}
addRelationship(_typeId: string, _item1: Item, _item2: Item, _leftwardValue?: string, _rightwardValue?: string, _shouldRefresh = true): Observable<RemoteData<Relationship>> {
return createSuccessfulRemoteDataObject$(new Relationship());
}
refreshRelationshipItemsInCache(_item: Item): void {
}
getItemRelationshipsArray(_item: Item, ..._linksToFollow: FollowLinkConfig<Relationship>[]): Observable<Relationship[]> {
return observableOf([]);
}
getRelatedItems(_item: Item): Observable<Item[]> {
return observableOf([]);
}
getRelatedItemsByLabel(_item: Item, _label: string, _options?: FindListOptions): Observable<RemoteData<PaginatedList<Item>>> {
return createSuccessfulRemoteDataObject$(new PaginatedList<Item>());
}
getItemRelationshipsByLabel(_item: Item, _label: string, _options?: FindListOptions, _useCachedVersionIfAvailable = true, _reRequestOnStale = true, ..._linksToFollow: FollowLinkConfig<Relationship>[]): Observable<RemoteData<PaginatedList<Relationship>>> {
return createSuccessfulRemoteDataObject$(new PaginatedList<Relationship>());
}
getRelationshipByItemsAndLabel(_item1: Item, _item2: Item, _label: string, _options?: FindListOptions): Observable<Relationship> {
return observableOf(new Relationship());
}
setNameVariant(_listID: string, _itemID: string, _nameVariant: string): void {
}
getNameVariant(_listID: string, _itemID: string): Observable<string> {
return observableOf('');
}
updateNameVariant(_item1: Item, _item2: Item, _relationshipLabel: string, _nameVariant: string): Observable<RemoteData<Relationship>> {
return createSuccessfulRemoteDataObject$(new Relationship());
}
isLeftItem(_relationship: Relationship, _item: Item): Observable<boolean> {
return observableOf(false);
}
update(_object: Relationship): Observable<RemoteData<Relationship>> {
return createSuccessfulRemoteDataObject$(new Relationship());
}
searchByItemsAndType(_typeId: string, _itemUuid: string, _relationshipLabel: string, _arrayOfItemIds: string[]): Observable<RemoteData<PaginatedList<Relationship>>> {
return createSuccessfulRemoteDataObject$(new PaginatedList<Relationship>());
}
searchBy(_searchMethod: string, _options?: FindListOptions, _useCachedVersionIfAvailable?: boolean, _reRequestOnStale?: boolean, ..._linksToFollow: FollowLinkConfig<Relationship>[]): Observable<RemoteData<PaginatedList<Relationship>>> {
return createSuccessfulRemoteDataObject$(new PaginatedList<Relationship>());
}
resolveMetadataRepresentation(_metadatum: MetadataValue, _parentItem: DSpaceObject, _itemType: string): Observable<MetadataRepresentation> {
return observableOf({} as MetadataRepresentation);
}
}