Skip to content

Commit 018df05

Browse files
Merge branch 'dspace-cris-2024_02_x' into ux-plus-cris-2024_02_x
2 parents f3926ba + d048ae3 commit 018df05

File tree

14 files changed

+263
-100
lines changed

14 files changed

+263
-100
lines changed

src/app/collection-page/delete-collection-page/delete-collection-page.component.spec.ts

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,49 @@ import { of as observableOf } from 'rxjs';
1212

1313
import { DSONameService } from '../../core/breadcrumbs/dso-name.service';
1414
import { CollectionDataService } from '../../core/data/collection-data.service';
15-
import { RequestService } from '../../core/data/request.service';
15+
import {
16+
DSPACE_OBJECT_DELETION_SCRIPT_NAME,
17+
ScriptDataService,
18+
} from '../../core/data/processes/script-data.service';
19+
import { Collection } from '../../core/shared/collection.model';
20+
import { ProcessParameter } from '../../process-page/processes/process-parameter.model';
1621
import { DSONameServiceMock } from '../../shared/mocks/dso-name.service.mock';
1722
import { NotificationsService } from '../../shared/notifications/notifications.service';
23+
import {
24+
createFailedRemoteDataObject$,
25+
createSuccessfulRemoteDataObject$,
26+
} from '../../shared/remote-data.utils';
27+
import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub';
1828
import { DeleteCollectionPageComponent } from './delete-collection-page.component';
1929

2030
describe('DeleteCollectionPageComponent', () => {
31+
32+
let scriptService;
2133
let comp: DeleteCollectionPageComponent;
34+
let notificationService: NotificationsServiceStub;
2235
let fixture: ComponentFixture<DeleteCollectionPageComponent>;
2336

37+
const mockCollection: Collection = Object.assign(new Collection(), {
38+
uuid: 'test-uuid',
39+
id: 'test-uuid',
40+
name: 'Test Collection',
41+
type: 'collection',
42+
});
43+
2444
beforeEach(waitForAsync(() => {
45+
notificationService = new NotificationsServiceStub();
46+
scriptService = jasmine.createSpyObj('scriptService', {
47+
invoke: createSuccessfulRemoteDataObject$({ processId: '123' }),
48+
});
49+
2550
TestBed.configureTestingModule({
2651
imports: [TranslateModule.forRoot(), CommonModule, RouterTestingModule, DeleteCollectionPageComponent],
2752
providers: [
2853
{ provide: DSONameService, useValue: new DSONameServiceMock() },
2954
{ provide: CollectionDataService, useValue: {} },
3055
{ provide: ActivatedRoute, useValue: { data: observableOf({ dso: { payload: {} } }) } },
31-
{ provide: NotificationsService, useValue: {} },
32-
{ provide: RequestService, useValue: {} },
56+
{ provide: NotificationsService, useValue: notificationService },
57+
{ provide: ScriptDataService, useValue: scriptService },
3358
],
3459
schemas: [NO_ERRORS_SCHEMA],
3560
}).compileComponents();
@@ -41,9 +66,37 @@ describe('DeleteCollectionPageComponent', () => {
4166
fixture.detectChanges();
4267
});
4368

44-
describe('frontendURL', () => {
45-
it('should have the right frontendURL set', () => {
46-
expect((comp as any).frontendURL).toEqual('/collections/');
69+
it('should create', () => {
70+
expect(comp).toBeTruthy();
71+
});
72+
73+
it('should have the right frontendURL set', () => {
74+
expect((comp as any).frontendURL).toEqual('/collections/');
75+
});
76+
77+
describe('onConfirm', () => {
78+
it('should invoke the deletion script with correct params, show success notification and redirect on success', (done) => {
79+
const parameterValues: ProcessParameter[] = [
80+
Object.assign(new ProcessParameter(), { name: '-i', value: mockCollection.uuid }),
81+
];
82+
(scriptService.invoke as jasmine.Spy).and.returnValue(createSuccessfulRemoteDataObject$({ processId: '123' }));
83+
comp.onConfirm(mockCollection);
84+
setTimeout(() => {
85+
expect(scriptService.invoke).toHaveBeenCalledWith(DSPACE_OBJECT_DELETION_SCRIPT_NAME, parameterValues, []);
86+
expect(notificationService.success).toHaveBeenCalledWith('collection.delete.notification.success');
87+
expect(notificationService.process).toHaveBeenCalledWith('123', 5000, jasmine.any(Object));
88+
done();
89+
}, 0);
90+
});
91+
92+
it('error notification is shown', (done) => {
93+
(scriptService.invoke as jasmine.Spy).and.returnValue(createFailedRemoteDataObject$('Error', 500));
94+
comp.onConfirm(mockCollection);
95+
setTimeout(() => {
96+
expect(notificationService.error).toHaveBeenCalledWith('collection.delete.notification.fail');
97+
done();
98+
}, 0);
4799
});
48100
});
101+
49102
});

src/app/collection-page/delete-collection-page/delete-collection-page.component.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414

1515
import { DSONameService } from '../../core/breadcrumbs/dso-name.service';
1616
import { CollectionDataService } from '../../core/data/collection-data.service';
17+
import { ScriptDataService } from '../../core/data/processes/script-data.service';
1718
import { Collection } from '../../core/shared/collection.model';
1819
import { BtnDisabledDirective } from '../../shared/btn-disabled.directive';
1920
import { DeleteComColPageComponent } from '../../shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component';
@@ -46,7 +47,8 @@ export class DeleteCollectionPageComponent extends DeleteComColPageComponent<Col
4647
protected route: ActivatedRoute,
4748
protected notifications: NotificationsService,
4849
protected translate: TranslateService,
50+
protected scriptDataService: ScriptDataService,
4951
) {
50-
super(dsoDataService, dsoNameService, router, route, notifications, translate);
52+
super(dsoDataService, dsoNameService, router, route, notifications, translate, scriptDataService);
5153
}
5254
}

src/app/community-page/delete-community-page/delete-community-page.component.spec.ts

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,60 @@ import {
55
TestBed,
66
waitForAsync,
77
} from '@angular/core/testing';
8-
import { ActivatedRoute } from '@angular/router';
8+
import {
9+
ActivatedRoute,
10+
Router,
11+
} from '@angular/router';
912
import { RouterTestingModule } from '@angular/router/testing';
1013
import { TranslateModule } from '@ngx-translate/core';
11-
import { of as observableOf } from 'rxjs';
14+
import { of } from 'rxjs';
1215

1316
import { DSONameService } from '../../core/breadcrumbs/dso-name.service';
1417
import { CommunityDataService } from '../../core/data/community-data.service';
15-
import { RequestService } from '../../core/data/request.service';
18+
import {
19+
DSPACE_OBJECT_DELETION_SCRIPT_NAME,
20+
ScriptDataService,
21+
} from '../../core/data/processes/script-data.service';
22+
import { Community } from '../../core/shared/community.model';
23+
import { ProcessParameter } from '../../process-page/processes/process-parameter.model';
1624
import { DSONameServiceMock } from '../../shared/mocks/dso-name.service.mock';
1725
import { NotificationsService } from '../../shared/notifications/notifications.service';
26+
import {
27+
createFailedRemoteDataObject$,
28+
createSuccessfulRemoteDataObject$,
29+
} from '../../shared/remote-data.utils';
30+
import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub';
1831
import { DeleteCommunityPageComponent } from './delete-community-page.component';
1932

2033
describe('DeleteCommunityPageComponent', () => {
2134
let comp: DeleteCommunityPageComponent;
2235
let fixture: ComponentFixture<DeleteCommunityPageComponent>;
36+
let scriptService;
37+
let notificationService: NotificationsServiceStub;
38+
let router;
39+
40+
const mockCommunity: Community = Object.assign(new Community(), {
41+
uuid: 'test-uuid',
42+
id: 'test-uuid',
43+
name: 'Test Community',
44+
type: 'community',
45+
});
2346

2447
beforeEach(waitForAsync(() => {
48+
notificationService = new NotificationsServiceStub();
49+
scriptService = jasmine.createSpyObj('scriptService', {
50+
invoke: createSuccessfulRemoteDataObject$({ processId: '123' }),
51+
});
52+
router = jasmine.createSpyObj('router', ['navigateByUrl', 'navigate']);
2553
TestBed.configureTestingModule({
2654
imports: [TranslateModule.forRoot(), CommonModule, RouterTestingModule, DeleteCommunityPageComponent],
2755
providers: [
2856
{ provide: DSONameService, useValue: new DSONameServiceMock() },
2957
{ provide: CommunityDataService, useValue: {} },
30-
{ provide: ActivatedRoute, useValue: { data: observableOf({ dso: { payload: {} } }) } },
31-
{ provide: NotificationsService, useValue: {} },
32-
{ provide: RequestService, useValue: {} },
58+
{ provide: ActivatedRoute, useValue: { data: of({ dso: { payload: mockCommunity } }) } },
59+
{ provide: NotificationsService, useValue: notificationService },
60+
{ provide: ScriptDataService, useValue: scriptService },
61+
{ provide: Router, useValue: router },
3362
],
3463
schemas: [NO_ERRORS_SCHEMA],
3564
}).compileComponents();
@@ -41,9 +70,37 @@ describe('DeleteCommunityPageComponent', () => {
4170
fixture.detectChanges();
4271
});
4372

44-
describe('frontendURL', () => {
45-
it('should have the right frontendURL set', () => {
46-
expect((comp as any).frontendURL).toEqual('/communities/');
73+
it('should create', () => {
74+
expect(comp).toBeTruthy();
75+
});
76+
77+
it('should have the right frontendURL set', () => {
78+
expect((comp as any).frontendURL).toEqual('/communities/');
79+
});
80+
81+
describe('onConfirm', () => {
82+
it('should invoke the deletion script with correct params, show success notification and redirect on success', (done) => {
83+
const parameterValues: ProcessParameter[] = [
84+
Object.assign(new ProcessParameter(), { name: '-i', value: mockCommunity.uuid }),
85+
];
86+
(scriptService.invoke as jasmine.Spy).and.returnValue(createSuccessfulRemoteDataObject$({ processId: '123' }));
87+
comp.onConfirm(mockCommunity);
88+
setTimeout(() => {
89+
expect(scriptService.invoke).toHaveBeenCalledWith(DSPACE_OBJECT_DELETION_SCRIPT_NAME, parameterValues, []);
90+
expect(notificationService.success).toHaveBeenCalledWith('community.delete.notification.success');
91+
expect(notificationService.process).toHaveBeenCalledWith('123', 5000, jasmine.any(Object));
92+
done();
93+
}, 0);
94+
});
95+
96+
it('error notification is shown', (done) => {
97+
(scriptService.invoke as jasmine.Spy).and.returnValue(createFailedRemoteDataObject$('Error', 500));
98+
comp.onConfirm(mockCommunity);
99+
setTimeout(() => {
100+
expect(notificationService.error).toHaveBeenCalledWith('community.delete.notification.fail');
101+
done();
102+
}, 0);
47103
});
48104
});
105+
49106
});

src/app/community-page/delete-community-page/delete-community-page.component.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414

1515
import { DSONameService } from '../../core/breadcrumbs/dso-name.service';
1616
import { CommunityDataService } from '../../core/data/community-data.service';
17+
import { ScriptDataService } from '../../core/data/processes/script-data.service';
1718
import { Community } from '../../core/shared/community.model';
1819
import { BtnDisabledDirective } from '../../shared/btn-disabled.directive';
1920
import { DeleteComColPageComponent } from '../../shared/comcol/comcol-forms/delete-comcol-page/delete-comcol-page.component';
@@ -46,8 +47,9 @@ export class DeleteCommunityPageComponent extends DeleteComColPageComponent<Comm
4647
protected route: ActivatedRoute,
4748
protected notifications: NotificationsService,
4849
protected translate: TranslateService,
50+
protected scriptDataService: ScriptDataService,
4951
) {
50-
super(dsoDataService, dsoNameService, router, route, notifications, translate);
52+
super(dsoDataService, dsoNameService, router, route, notifications, translate, scriptDataService);
5153
}
5254

5355
}

src/app/core/data/processes/script-data.service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export const BATCH_IMPORT_SCRIPT_NAME = 'import';
3434
export const BATCH_EXPORT_SCRIPT_NAME = 'export';
3535
export const ITEM_EXPORT_SCRIPT_NAME = 'item-export';
3636
export const BULK_ITEM_EXPORT_SCRIPT_NAME = 'bulk-item-export';
37+
export const DSPACE_OBJECT_DELETION_SCRIPT_NAME = 'dspace-object-deletion';
3738

3839
@Injectable({ providedIn: 'root' })
3940
export class ScriptDataService extends IdentifiableDataService<Script> implements FindAllData<Script> {

src/app/core/itemexportformat/item-export-format.service.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,10 @@ export class ItemExportFormatService extends IdentifiableDataService<ItemExportF
200200
.filter((searchFilter) => searchFilter.key.includes('f.'))
201201
.map((searchFilter) => {
202202
const key = searchFilter.key.replace('f.', '');
203-
return searchFilter.values.map((filterValue) => `${key}=${filterValue}`).join('&');
203+
return searchFilter.values.map((filterValue) => {
204+
const baseValue = `${key}=${filterValue}`;
205+
return searchFilter.operator ? `${baseValue},${searchFilter.operator}` : baseValue;
206+
}).join('&');
204207
})
205208
.join('&');
206209
return [...parameterValues, Object.assign(new ProcessParameter(), { name: '-sf', value })];

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ <h5 (click)="setSelected(typeDto.relationshipType, !selected)">
8787

8888
<div class="space-children-mr">
8989
<button [dsBtnDisabled]="isDeleting$ | async" (click)="performAction()"
90-
class="btn btn-outline-secondary perform-action">{{confirmMessage | translate}}
90+
class="btn btn-danger perform-action">{{confirmMessage | translate}}
9191
</button>
9292
<button [dsBtnDisabled]="isDeleting$ | async" [routerLink]="[itemPageRoute, 'edit']"
9393
class="btn btn-outline-secondary cancel">

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

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,23 @@ import { LinkService } from '../../../core/cache/builders/link.service';
2323
import { EntityTypeDataService } from '../../../core/data/entity-type-data.service';
2424
import { ItemDataService } from '../../../core/data/item-data.service';
2525
import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service';
26+
import {
27+
DSPACE_OBJECT_DELETION_SCRIPT_NAME,
28+
ScriptDataService,
29+
} from '../../../core/data/processes/script-data.service';
2630
import { RelationshipDataService } from '../../../core/data/relationship-data.service';
2731
import { RelationshipTypeDataService } from '../../../core/data/relationship-type-data.service';
2832
import { Item } from '../../../core/shared/item.model';
2933
import { ItemType } from '../../../core/shared/item-relationships/item-type.model';
3034
import { Relationship } from '../../../core/shared/item-relationships/relationship.model';
3135
import { RelationshipType } from '../../../core/shared/item-relationships/relationship-type.model';
36+
import { Process } from '../../../process-page/processes/process.model';
37+
import { ProcessParameter } from '../../../process-page/processes/process-parameter.model';
3238
import { getMockThemeService } from '../../../shared/mocks/theme-service.mock';
3339
import { NotificationsService } from '../../../shared/notifications/notifications.service';
3440
import { ListableObjectComponentLoaderComponent } from '../../../shared/object-collection/shared/listable-object/listable-object-component-loader.component';
3541
import {
42+
createFailedRemoteDataObject,
3643
createSuccessfulRemoteDataObject,
3744
createSuccessfulRemoteDataObject$,
3845
} from '../../../shared/remote-data.utils';
@@ -64,10 +71,13 @@ let linkService;
6471
let entityTypeService;
6572
let notificationsServiceStub;
6673
let typesSelection;
74+
let scriptDataService;
6775

6876
describe('ItemDeleteComponent', () => {
6977
beforeEach(waitForAsync(() => {
70-
78+
scriptDataService = {
79+
invoke: jasmine.createSpy('invoke').and.returnValue(createSuccessfulRemoteDataObject$({ processId: '123' })),
80+
};
7181
mockItem = Object.assign(new Item(), {
7282
id: 'fake-id',
7383
uuid: 'fake-uuid',
@@ -176,6 +186,7 @@ describe('ItemDeleteComponent', () => {
176186
{ provide: RelationshipTypeDataService, useValue: {} },
177187
{ provide: LinkService, useValue: linkService },
178188
{ provide: ThemeService, useValue: getMockThemeService() },
189+
{ provide: ScriptDataService, useValue: scriptDataService },
179190
], schemas: [
180191
CUSTOM_ELEMENTS_SCHEMA,
181192
],
@@ -205,15 +216,17 @@ describe('ItemDeleteComponent', () => {
205216

206217
describe('performAction', () => {
207218
describe(`when there are entitytypes`, () => {
208-
it('should call delete function from the ItemDataService', () => {
219+
it('should call delete function from the scriptDataService', () => {
209220
spyOn(comp, 'notify');
210221
comp.performAction();
211-
expect(mockItemDataService.delete)
212-
.toHaveBeenCalledWith(mockItem.id, types.filter((type) => typesSelection[type]).map((type) => type.id));
222+
expect(scriptDataService.invoke)
223+
.toHaveBeenCalledWith(DSPACE_OBJECT_DELETION_SCRIPT_NAME, [
224+
Object.assign(new ProcessParameter(), { name: '-i', value: mockItem.uuid }),
225+
], []);
213226
expect(comp.notify).toHaveBeenCalled();
214227
});
215228

216-
it('should call delete function from the ItemDataService with empty types', () => {
229+
it('should call delete function from the scriptDataService with empty types', () => {
217230

218231
spyOn(comp, 'notify');
219232
jasmine.getEnv().allowRespy(true);
@@ -222,7 +235,10 @@ describe('ItemDeleteComponent', () => {
222235

223236
comp.performAction();
224237

225-
expect(mockItemDataService.delete).toHaveBeenCalledWith(mockItem.id, []);
238+
expect(scriptDataService.invoke)
239+
.toHaveBeenCalledWith(DSPACE_OBJECT_DELETION_SCRIPT_NAME, [
240+
Object.assign(new ProcessParameter(), { name: '-i', value: mockItem.uuid }),
241+
], []);
226242
expect(comp.notify).toHaveBeenCalled();
227243
});
228244
});
@@ -236,25 +252,27 @@ describe('ItemDeleteComponent', () => {
236252
);
237253
});
238254

239-
it('should call delete function from the ItemDataService', () => {
255+
it('should call delete function from the scriptDataService', waitForAsync(() => {
240256
spyOn(comp, 'notify');
241257
comp.performAction();
242-
expect(mockItemDataService.delete)
243-
.toHaveBeenCalledWith(mockItem.id, types.filter((type) => typesSelection[type]).map((type) => type.id));
258+
expect(scriptDataService.invoke).toHaveBeenCalledWith(DSPACE_OBJECT_DELETION_SCRIPT_NAME, [
259+
Object.assign(new ProcessParameter(), { name: '-i', value: mockItem.uuid }),
260+
], []);
244261
expect(comp.notify).toHaveBeenCalled();
245-
});
262+
}));
246263
});
247-
});
248-
describe('notify', () => {
249-
it('should navigate to the homepage on successful deletion of the item', () => {
250-
comp.notify(true);
251-
expect(routerStub.navigate).toHaveBeenCalledWith(['']);
264+
describe('notify', () => {
265+
it('should navigate to the homepage on successful deletion of the item', () => {
266+
comp.notify(createSuccessfulRemoteDataObject(Object.assign(new Process(), { id: '123' })));
267+
expect(routerStub.navigate).toHaveBeenCalledWith(['']);
268+
});
252269
});
253-
});
254-
describe('notify', () => {
255-
it('should navigate to the item edit page on failed deletion of the item', () => {
256-
comp.notify(false);
257-
expect(routerStub.navigate).toHaveBeenCalledWith([getItemEditRoute(mockItem)]);
270+
describe('notify', () => {
271+
it('should navigate to the item edit page on failed deletion of the item', () => {
272+
comp.item = mockItem;
273+
comp.notify(createFailedRemoteDataObject());
274+
expect(routerStub.navigate).toHaveBeenCalledWith([getItemEditRoute(mockItem)]);
275+
});
258276
});
259277
});
260278
});

0 commit comments

Comments
 (0)