mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-18 07:23:03 +00:00
61142: ItemRelationshipComponent test + item de-caching
This commit is contained in:
@@ -28,7 +28,7 @@ import { MetadataSchema } from '../../../core/metadata/metadataschema.model';
|
||||
import { MetadataField } from '../../../core/metadata/metadatafield.model';
|
||||
import { Metadata } from '../../../core/shared/metadata.utils';
|
||||
|
||||
let comp: ItemMetadataComponent;
|
||||
let comp: any;
|
||||
let fixture: ComponentFixture<ItemMetadataComponent>;
|
||||
let de: DebugElement;
|
||||
let el: HTMLElement;
|
||||
|
@@ -0,0 +1,234 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { ItemRelationshipsComponent } from './item-relationships.component';
|
||||
import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { INotification, Notification } from '../../../shared/notifications/models/notification.model';
|
||||
import { NotificationType } from '../../../shared/notifications/models/notification-type';
|
||||
import { RouterStub } from '../../../shared/testing/router-stub';
|
||||
import { TestScheduler } from 'rxjs/testing';
|
||||
import { SharedModule } from '../../../shared/shared.module';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { ItemDataService } from '../../../core/data/item-data.service';
|
||||
import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
||||
import { GLOBAL_CONFIG } from '../../../../config';
|
||||
import { RelationshipType } from '../../../core/shared/item-relationships/relationship-type.model';
|
||||
import { ResourceType } from '../../../core/shared/resource-type';
|
||||
import { Relationship } from '../../../core/shared/item-relationships/relationship.model';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
import { RemoteData } from '../../../core/data/remote-data';
|
||||
import { Item } from '../../../core/shared/item.model';
|
||||
import { PaginatedList } from '../../../core/data/paginated-list';
|
||||
import { PageInfo } from '../../../core/shared/page-info.model';
|
||||
import { FieldChangeType } from '../../../core/data/object-updates/object-updates.actions';
|
||||
import { RelationshipService } from '../../../core/data/relationship.service';
|
||||
import { ObjectCacheService } from '../../../core/cache/object-cache.service';
|
||||
import { getTestScheduler } from 'jasmine-marbles';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { RestResponse } from '../../../core/cache/response.models';
|
||||
|
||||
let comp: any;
|
||||
let fixture: ComponentFixture<ItemRelationshipsComponent>;
|
||||
let de: DebugElement;
|
||||
let el: HTMLElement;
|
||||
let objectUpdatesService;
|
||||
let relationshipService;
|
||||
let objectCache;
|
||||
const infoNotification: INotification = new Notification('id', NotificationType.Info, 'info');
|
||||
const warningNotification: INotification = new Notification('id', NotificationType.Warning, 'warning');
|
||||
const successNotification: INotification = new Notification('id', NotificationType.Success, 'success');
|
||||
const notificationsService = jasmine.createSpyObj('notificationsService',
|
||||
{
|
||||
info: infoNotification,
|
||||
warning: warningNotification,
|
||||
success: successNotification
|
||||
}
|
||||
);
|
||||
const router = new RouterStub();
|
||||
let routeStub;
|
||||
let itemService;
|
||||
|
||||
const url = 'http://test-url.com/test-url';
|
||||
router.url = url;
|
||||
|
||||
let scheduler: TestScheduler;
|
||||
let item;
|
||||
let author1;
|
||||
let author2;
|
||||
let fieldUpdate1;
|
||||
let fieldUpdate2;
|
||||
let relationships;
|
||||
let relationshipType;
|
||||
|
||||
describe('ItemRelationshipsComponent', () => {
|
||||
beforeEach(async(() => {
|
||||
const date = new Date();
|
||||
|
||||
relationshipType = Object.assign(new RelationshipType(), {
|
||||
type: ResourceType.RelationshipType,
|
||||
id: '1',
|
||||
uuid: '1',
|
||||
leftLabel: 'isAuthorOfPublication',
|
||||
rightLabel: 'isPublicationOfAuthor'
|
||||
});
|
||||
|
||||
relationships = [
|
||||
Object.assign(new Relationship(), {
|
||||
self: url + '/2',
|
||||
id: '2',
|
||||
uuid: '2',
|
||||
leftId: 'author1',
|
||||
rightId: 'publication',
|
||||
relationshipType: observableOf(new RemoteData(false, false, true, undefined, relationshipType))
|
||||
}),
|
||||
Object.assign(new Relationship(), {
|
||||
self: url + '/3',
|
||||
id: '3',
|
||||
uuid: '3',
|
||||
leftId: 'author2',
|
||||
rightId: 'publication',
|
||||
relationshipType: observableOf(new RemoteData(false, false, true, undefined, relationshipType))
|
||||
})
|
||||
];
|
||||
|
||||
item = Object.assign(new Item(), {
|
||||
self: 'fake-item-url/publication',
|
||||
id: 'publication',
|
||||
uuid: 'publication',
|
||||
relationships: observableOf(new RemoteData(false, false, true, undefined, new PaginatedList(new PageInfo(), relationships))),
|
||||
lastModified: date
|
||||
});
|
||||
|
||||
author1 = Object.assign(new Item(), {
|
||||
id: 'author1',
|
||||
uuid: 'author1'
|
||||
});
|
||||
author2 = Object.assign(new Item(), {
|
||||
id: 'author2',
|
||||
uuid: 'author2'
|
||||
});
|
||||
|
||||
fieldUpdate1 = {
|
||||
field: author1,
|
||||
changeType: undefined
|
||||
};
|
||||
fieldUpdate2 = {
|
||||
field: author2,
|
||||
changeType: FieldChangeType.REMOVE
|
||||
};
|
||||
|
||||
itemService = jasmine.createSpyObj('itemService', {
|
||||
findById: observableOf(new RemoteData(false, false, true, undefined, item))
|
||||
});
|
||||
routeStub = {
|
||||
parent: {
|
||||
data: observableOf({ item: new RemoteData(false, false, true, null, item) })
|
||||
}
|
||||
};
|
||||
|
||||
objectUpdatesService = jasmine.createSpyObj('objectUpdatesService',
|
||||
{
|
||||
getFieldUpdates: observableOf({
|
||||
[author1.uuid]: fieldUpdate1,
|
||||
[author2.uuid]: fieldUpdate2
|
||||
}),
|
||||
getFieldUpdatesExclusive: observableOf({
|
||||
[author1.uuid]: fieldUpdate1,
|
||||
[author2.uuid]: fieldUpdate2
|
||||
}),
|
||||
saveAddFieldUpdate: {},
|
||||
discardFieldUpdates: {},
|
||||
reinstateFieldUpdates: observableOf(true),
|
||||
initialize: {},
|
||||
getUpdatedFields: observableOf([author1, author2]),
|
||||
getLastModified: observableOf(date),
|
||||
hasUpdates: observableOf(true),
|
||||
isReinstatable: observableOf(false), // should always return something --> its in ngOnInit
|
||||
isValidPage: observableOf(true)
|
||||
}
|
||||
);
|
||||
|
||||
relationshipService = jasmine.createSpyObj('relationshipService',
|
||||
{
|
||||
getItemRelationshipLabels: observableOf(['isAuthorOfPublication']),
|
||||
getRelatedItems: observableOf([author1, author2]),
|
||||
getRelatedItemsByLabel: observableOf([author1, author2]),
|
||||
getItemRelationshipsArray: observableOf(relationships),
|
||||
deleteRelationship: observableOf(new RestResponse(true, 200, 'OK'))
|
||||
}
|
||||
);
|
||||
|
||||
objectCache = jasmine.createSpyObj('objectCache', {
|
||||
remove: undefined
|
||||
});
|
||||
|
||||
scheduler = getTestScheduler();
|
||||
TestBed.configureTestingModule({
|
||||
imports: [SharedModule, TranslateModule.forRoot()],
|
||||
declarations: [ItemRelationshipsComponent],
|
||||
providers: [
|
||||
{ provide: ItemDataService, useValue: itemService },
|
||||
{ provide: ObjectUpdatesService, useValue: objectUpdatesService },
|
||||
{ provide: Router, useValue: router },
|
||||
{ provide: ActivatedRoute, useValue: routeStub },
|
||||
{ provide: NotificationsService, useValue: notificationsService },
|
||||
{ provide: GLOBAL_CONFIG, useValue: { item: { edit: { undoTimeout: 10 } } } as any },
|
||||
{ provide: RelationshipService, useValue: relationshipService },
|
||||
{ provide: ObjectCacheService, useValue: objectCache }
|
||||
], schemas: [
|
||||
NO_ERRORS_SCHEMA
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ItemRelationshipsComponent);
|
||||
comp = fixture.componentInstance;
|
||||
de = fixture.debugElement;
|
||||
el = de.nativeElement;
|
||||
comp.url = url;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
describe('discard', () => {
|
||||
beforeEach(() => {
|
||||
comp.discard();
|
||||
});
|
||||
|
||||
it('it should call discardFieldUpdates on the objectUpdatesService with the correct url and notification', () => {
|
||||
expect(objectUpdatesService.discardFieldUpdates).toHaveBeenCalledWith(url, infoNotification);
|
||||
});
|
||||
});
|
||||
|
||||
describe('reinstate', () => {
|
||||
beforeEach(() => {
|
||||
comp.reinstate();
|
||||
});
|
||||
|
||||
it('it should call reinstateFieldUpdates on the objectUpdatesService with the correct url', () => {
|
||||
expect(objectUpdatesService.reinstateFieldUpdates).toHaveBeenCalledWith(url);
|
||||
});
|
||||
});
|
||||
|
||||
describe('changeType is REMOVE', () => {
|
||||
beforeEach(() => {
|
||||
fieldUpdate1.changeType = FieldChangeType.REMOVE;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
it('the div should have class alert-danger', () => {
|
||||
const element = de.queryAll(By.css('.relationship-row'))[1].nativeElement;
|
||||
expect(element.classList).toContain('alert-danger');
|
||||
});
|
||||
});
|
||||
|
||||
describe('submit', () => {
|
||||
beforeEach(() => {
|
||||
comp.submit();
|
||||
});
|
||||
|
||||
it('it should delete the correct relationship and de-cache the current item', () => {
|
||||
expect(relationshipService.deleteRelationship).toHaveBeenCalledWith(relationships[1].uuid);
|
||||
expect(objectCache.remove).toHaveBeenCalledWith(item.self);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -16,6 +16,9 @@ import { FieldChangeType } from '../../../core/data/object-updates/object-update
|
||||
import { Relationship } from '../../../core/shared/item-relationships/relationship.model';
|
||||
import { RestResponse } from '../../../core/cache/response.models';
|
||||
import { isNotEmptyOperator } from '../../../shared/empty.util';
|
||||
import { RemoteData } from '../../../core/data/remote-data';
|
||||
import { ObjectCacheService } from '../../../core/cache/object-cache.service';
|
||||
import { getSucceededRemoteData } from '../../../core/shared/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-item-relationships',
|
||||
@@ -40,7 +43,8 @@ export class ItemRelationshipsComponent extends AbstractItemUpdateComponent {
|
||||
protected translateService: TranslateService,
|
||||
@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig,
|
||||
protected route: ActivatedRoute,
|
||||
protected relationshipService: RelationshipService
|
||||
protected relationshipService: RelationshipService,
|
||||
protected objectCache: ObjectCacheService
|
||||
) {
|
||||
super(itemService, objectUpdatesService, router, notificationsService, translateService, EnvConfig, route);
|
||||
}
|
||||
@@ -100,6 +104,8 @@ export class ItemRelationshipsComponent extends AbstractItemUpdateComponent {
|
||||
).subscribe((responses: RestResponse[]) => {
|
||||
// Make sure the lists are up-to-date and send a notification that the removal was successful
|
||||
// TODO: Fix lists refreshing correctly
|
||||
this.objectCache.remove(this.item.self);
|
||||
this.itemService.findById(this.item.id).pipe(getSucceededRemoteData(), take(1)).subscribe((itemRD: RemoteData<Item>) => this.item = itemRD.payload);
|
||||
this.initializeOriginalFields();
|
||||
this.initializeUpdates();
|
||||
this.notificationsService.success(this.getNotificationTitle('saved'), this.getNotificationContent('saved'));
|
||||
|
Reference in New Issue
Block a user