Skip to content

Commit 74a6e3c

Browse files
committed
Fix issue where an item with an empty or invalid entity type couldn't be deleted
1 parent acb842e commit 74a6e3c

File tree

2 files changed

+65
-26
lines changed

2 files changed

+65
-26
lines changed

src/app/item-page/edit-item-page/item-delete/item-delete.component.spec.ts

Lines changed: 55 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { ItemType } from '../../../core/shared/item-relationships/item-type.mode
33
import { Relationship } from '../../../core/shared/item-relationships/relationship.model';
44
import { Item } from '../../../core/shared/item.model';
55
import { RouterStub } from '../../../shared/testing/router.stub';
6-
import { of as observableOf } from 'rxjs';
6+
import { of as observableOf, EMPTY } from 'rxjs';
77
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service.stub';
88
import { CommonModule } from '@angular/common';
99
import { FormsModule } from '@angular/forms';
@@ -24,6 +24,8 @@ import { RelationshipType } from '../../../core/shared/item-relationships/relati
2424
import { EntityTypeService } from '../../../core/data/entity-type.service';
2525
import { getItemEditRoute } from '../../item-page-routing-paths';
2626
import { createPaginatedList } from '../../../shared/testing/utils.test';
27+
import { RelationshipTypeService } from '../../../core/data/relationship-type.service';
28+
import { LinkService } from '../../../core/cache/builders/link.service';
2729

2830
let comp: ItemDeleteComponent;
2931
let fixture: ComponentFixture<ItemDeleteComponent>;
@@ -40,6 +42,7 @@ let mockItemDataService: ItemDataService;
4042
let routeStub;
4143
let objectUpdatesServiceStub;
4244
let relationshipService;
45+
let linkService;
4346
let entityTypeService;
4447
let notificationsServiceStub;
4548
let typesSelection;
@@ -52,7 +55,12 @@ describe('ItemDeleteComponent', () => {
5255
uuid: 'fake-uuid',
5356
handle: 'fake/handle',
5457
lastModified: '2018',
55-
isWithdrawn: true
58+
isWithdrawn: true,
59+
metadata: {
60+
'dspace.entity.type': [
61+
{ value: 'Person' }
62+
]
63+
}
5664
});
5765

5866
itemType = Object.assign(new ItemType(), {
@@ -129,6 +137,12 @@ describe('ItemDeleteComponent', () => {
129137
}
130138
);
131139

140+
linkService = jasmine.createSpyObj('linkService',
141+
{
142+
resolveLinks: relationships[0],
143+
}
144+
);
145+
132146
notificationsServiceStub = new NotificationsServiceStub();
133147

134148
TestBed.configureTestingModule({
@@ -142,6 +156,8 @@ describe('ItemDeleteComponent', () => {
142156
{ provide: ObjectUpdatesService, useValue: objectUpdatesServiceStub },
143157
{ provide: RelationshipService, useValue: relationshipService },
144158
{ provide: EntityTypeService, useValue: entityTypeService },
159+
{ provide: RelationshipTypeService, useValue: {} },
160+
{ provide: LinkService, useValue: linkService },
145161
], schemas: [
146162
CUSTOM_ELEMENTS_SCHEMA
147163
]
@@ -166,25 +182,45 @@ describe('ItemDeleteComponent', () => {
166182
});
167183

168184
describe('performAction', () => {
169-
it('should call delete function from the ItemDataService', () => {
170-
spyOn(comp, 'notify');
171-
comp.performAction();
172-
expect(mockItemDataService.delete)
173-
.toHaveBeenCalledWith(mockItem.id, types.filter((type) => typesSelection[type]).map((type) => type.id));
174-
expect(comp.notify).toHaveBeenCalled();
185+
describe(`when there are entitytypes`, () => {
186+
it('should call delete function from the ItemDataService', () => {
187+
spyOn(comp, 'notify');
188+
comp.performAction();
189+
expect(mockItemDataService.delete)
190+
.toHaveBeenCalledWith(mockItem.id, types.filter((type) => typesSelection[type]).map((type) => type.id));
191+
expect(comp.notify).toHaveBeenCalled();
192+
});
193+
194+
it('should call delete function from the ItemDataService with empty types', () => {
195+
196+
spyOn(comp, 'notify');
197+
jasmine.getEnv().allowRespy(true);
198+
spyOn(entityTypeService, 'getEntityTypeRelationships').and.returnValue([]);
199+
comp.ngOnInit();
200+
201+
comp.performAction();
202+
203+
expect(mockItemDataService.delete).toHaveBeenCalledWith(mockItem.id, []);
204+
expect(comp.notify).toHaveBeenCalled();
205+
});
175206
});
176207

177-
it('should call delete function from the ItemDataService with empty types', () => {
178-
179-
spyOn(comp, 'notify');
180-
jasmine.getEnv().allowRespy(true);
181-
spyOn(entityTypeService, 'getEntityTypeRelationships').and.returnValue([]);
182-
comp.ngOnInit();
183-
184-
comp.performAction();
185-
186-
expect(mockItemDataService.delete).toHaveBeenCalledWith(mockItem.id, []);
187-
expect(comp.notify).toHaveBeenCalled();
208+
describe(`when there are no entity types`, () => {
209+
beforeEach(() => {
210+
(comp as any).entityTypeService = jasmine.createSpyObj('entityTypeService',
211+
{
212+
getEntityTypeByLabel: EMPTY,
213+
}
214+
);
215+
});
216+
217+
it('should call delete function from the ItemDataService', () => {
218+
spyOn(comp, 'notify');
219+
comp.performAction();
220+
expect(mockItemDataService.delete)
221+
.toHaveBeenCalledWith(mockItem.id, types.filter((type) => typesSelection[type]).map((type) => type.id));
222+
expect(comp.notify).toHaveBeenCalled();
223+
});
188224
});
189225
});
190226
describe('notify', () => {

src/app/item-page/edit-item-page/item-delete/item-delete.component.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { Component, Input, OnInit } from '@angular/core';
2-
import {defaultIfEmpty, filter, map, switchMap, take} from 'rxjs/operators';
3-
import { AbstractSimpleItemActionComponent } from '../simple-item-action/abstract-simple-item-action.component';
2+
import { defaultIfEmpty, filter, map, switchMap, take } from 'rxjs/operators';
3+
import {
4+
AbstractSimpleItemActionComponent
5+
} from '../simple-item-action/abstract-simple-item-action.component';
46
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
57
import {
68
combineLatest as observableCombineLatest,
@@ -32,6 +34,7 @@ import { followLink } from '../../../shared/utils/follow-link-config.model';
3234
import { getItemEditRoute } from '../../item-page-routing-paths';
3335
import { RemoteData } from '../../../core/data/remote-data';
3436
import { NoContent } from '../../../core/shared/NoContent.model';
37+
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
3538

3639
@Component({
3740
selector: 'ds-item-delete',
@@ -60,7 +63,7 @@ export class ItemDeleteComponent
6063
* A list of the relationship types for which this item has relations as an observable.
6164
* The list doesn't contain duplicates.
6265
*/
63-
types$: Observable<RelationshipType[]>;
66+
types$: BehaviorSubject<RelationshipType[]> = new BehaviorSubject([]);
6467

6568
/**
6669
* A map which stores the relationships of this item for each type as observable lists
@@ -113,8 +116,8 @@ export class ItemDeleteComponent
113116
this.url = this.router.url;
114117

115118
const label = this.item.firstMetadataValue('dspace.entity.type');
116-
if (label !== undefined) {
117-
this.types$ = this.entityTypeService.getEntityTypeByLabel(label).pipe(
119+
if (isNotEmpty(label)) {
120+
this.entityTypeService.getEntityTypeByLabel(label).pipe(
118121
getFirstSucceededRemoteData(),
119122
getRemoteDataPayload(),
120123
switchMap((entityType) => this.entityTypeService.getEntityTypeRelationships(entityType.id)),
@@ -138,9 +141,9 @@ export class ItemDeleteComponent
138141
),
139142
);
140143
})
141-
);
144+
).subscribe((types: RelationshipType[]) => this.types$.next(types));
142145
} else {
143-
this.types$ = observableOf([]);
146+
this.types$.next([]);
144147
}
145148

146149
this.types$.pipe(

0 commit comments

Comments
 (0)