mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-09 19:13:08 +00:00
115046: Fixed failing tests & added new test to cover added code
(cherry picked from commit 479adf6519
)
This commit is contained in:
@@ -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([
|
||||
|
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -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');
|
||||
|
||||
}
|
||||
|
@@ -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,
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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 '';
|
||||
}
|
||||
|
||||
}
|
5
src/app/shared/testing/entity-type-data.service.stub.ts
Normal file
5
src/app/shared/testing/entity-type-data.service.stub.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Stub class of {@link EntityTypeDataService}
|
||||
*/
|
||||
export class EntityTypeDataServiceStub {
|
||||
}
|
8
src/app/shared/testing/item-data.service.stub.ts
Normal file
8
src/app/shared/testing/item-data.service.stub.ts
Normal 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> {
|
||||
}
|
24
src/app/shared/testing/object-updates.service.stub.ts
Normal file
24
src/app/shared/testing/object-updates.service.stub.ts
Normal 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({});
|
||||
}
|
||||
|
||||
}
|
86
src/app/shared/testing/relationship-data.service.stub.ts
Normal file
86
src/app/shared/testing/relationship-data.service.stub.ts
Normal 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);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user