63667: Extract update tracker

This commit is contained in:
Yana De Pauw
2019-07-10 11:14:21 +02:00
parent 395509a19a
commit cdb2c30bd4
3 changed files with 183 additions and 1 deletions

View File

@@ -138,6 +138,7 @@ import { RoleDirective } from './roles/role.directive';
import { UserMenuComponent } from './auth-nav-menu/user-menu/user-menu.component'; import { UserMenuComponent } from './auth-nav-menu/user-menu/user-menu.component';
import { ClaimedTaskActionsReturnToPoolComponent } from './mydspace-actions/claimed-task/return-to-pool/claimed-task-actions-return-to-pool.component'; import { ClaimedTaskActionsReturnToPoolComponent } from './mydspace-actions/claimed-task/return-to-pool/claimed-task-actions-return-to-pool.component';
import { ItemDetailPreviewFieldComponent } from './object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview-field/item-detail-preview-field.component'; import { ItemDetailPreviewFieldComponent } from './object-detail/my-dspace-result-detail-element/item-detail-preview/item-detail-preview-field/item-detail-preview-field.component';
import { AbstractTrackableComponent } from './trackable/abstract-trackable.component';
const MODULES = [ const MODULES = [
// Do NOT include UniversalModule, HttpModule, or JsonpModule here // Do NOT include UniversalModule, HttpModule, or JsonpModule here
@@ -257,7 +258,8 @@ const COMPONENTS = [
ItemSearchResultListElementComponent, ItemSearchResultListElementComponent,
TypedItemSearchResultListElementComponent, TypedItemSearchResultListElementComponent,
ItemTypeSwitcherComponent, ItemTypeSwitcherComponent,
BrowseByComponent BrowseByComponent,
AbstractTrackableComponent
]; ];
const ENTRY_COMPONENTS = [ const ENTRY_COMPONENTS = [
@@ -311,6 +313,7 @@ const SHARED_ITEM_PAGE_COMPONENTS = [
const PROVIDERS = [ const PROVIDERS = [
TruncatableService, TruncatableService,
MockAdminGuard, MockAdminGuard,
AbstractTrackableComponent,
{ {
provide: DYNAMIC_FORM_CONTROL_MAP_FN, provide: DYNAMIC_FORM_CONTROL_MAP_FN,
useValue: dsDynamicFormControlMapFn useValue: dsDynamicFormControlMapFn

View File

@@ -0,0 +1,101 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AbstractTrackableComponent } from './abstract-trackable.component';
import { INotification, Notification } from '../notifications/models/notification.model';
import { NotificationType } from '../notifications/models/notification-type';
import { of as observableOf } from 'rxjs';
import { TranslateModule } from '@ngx-translate/core';
import { ObjectUpdatesService } from '../../core/data/object-updates/object-updates.service';
import { NotificationsService } from '../notifications/notifications.service';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { TestScheduler } from 'rxjs/testing';
import { getTestScheduler } from 'jasmine-marbles';
describe('AbstractTrackableComponent', () => {
let comp: AbstractTrackableComponent;
let fixture: ComponentFixture<AbstractTrackableComponent>;
let objectUpdatesService;
let scheduler: TestScheduler;
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 url = 'http://test-url.com/test-url';
beforeEach(async(() => {
objectUpdatesService = jasmine.createSpyObj('objectUpdatesService',
{
saveAddFieldUpdate: {},
discardFieldUpdates: {},
reinstateFieldUpdates: observableOf(true),
initialize: {},
hasUpdates: observableOf(true),
isReinstatable: observableOf(false), // should always return something --> its in ngOnInit
isValidPage: observableOf(true)
}
);
scheduler = getTestScheduler();
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot()],
declarations: [AbstractTrackableComponent],
providers: [
{provide: ObjectUpdatesService, useValue: objectUpdatesService},
{provide: NotificationsService, useValue: notificationsService},
], schemas: [
NO_ERRORS_SCHEMA
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AbstractTrackableComponent);
comp = fixture.componentInstance;
comp.url = url;
fixture.detectChanges();
});
it('should discard object updates', () => {
comp.discard();
expect(objectUpdatesService.discardFieldUpdates).toHaveBeenCalledWith(url, infoNotification);
});
it('should undo the discard of object updates', () => {
comp.reinstate();
expect(objectUpdatesService.reinstateFieldUpdates).toHaveBeenCalledWith(url);
});
describe('isReinstatable', () => {
beforeEach(() => {
objectUpdatesService.isReinstatable.and.returnValue(observableOf(true));
});
it('should return an observable that emits true', () => {
const expected = '(a|)';
scheduler.expectObservable(comp.isReinstatable()).toBe(expected, {a: true});
});
});
describe('hasChanges', () => {
beforeEach(() => {
objectUpdatesService.hasUpdates.and.returnValue(observableOf(true));
});
it('should return an observable that emits true', () => {
const expected = '(a|)';
scheduler.expectObservable(comp.hasChanges()).toBe(expected, {a: true});
});
});
});

View File

@@ -0,0 +1,78 @@
import { ObjectUpdatesService } from '../../core/data/object-updates/object-updates.service';
import { NotificationsService } from '../notifications/notifications.service';
import { TranslateService } from '@ngx-translate/core';
import { Observable } from 'rxjs';
import { Component } from '@angular/core';
/**
* Abstract Component that is able to track changes made in the inheriting component using the ObjectUpdateService
*/
@Component({
selector: 'ds-abstract-trackable',
template: ''
})
export class AbstractTrackableComponent {
/**
* The time span for being able to undo discarding changes
*/
public discardTimeOut: number;
public message: string;
public url: string;
public notificationsPrefix = 'static-pages.form.notification';
constructor(
public objectUpdatesService: ObjectUpdatesService,
public notificationsService: NotificationsService,
public translateService: TranslateService,
) {
}
/**
* Request the object updates service to discard all current changes to this item
* Shows a notification to remind the user that they can undo this
*/
discard() {
const undoNotification = this.notificationsService.info(this.getNotificationTitle('discarded'), this.getNotificationContent('discarded'), {timeOut: this.discardTimeOut});
this.objectUpdatesService.discardFieldUpdates(this.url, undoNotification);
}
/**
* Request the object updates service to undo discarding all changes to this item
*/
reinstate() {
this.objectUpdatesService.reinstateFieldUpdates(this.url);
}
/**
* Checks whether or not the object is currently reinstatable
*/
isReinstatable(): Observable<boolean> {
return this.objectUpdatesService.isReinstatable(this.url);
}
/**
* Checks whether or not there are currently updates for this object
*/
hasChanges(): Observable<boolean> {
return this.objectUpdatesService.hasUpdates(this.url);
}
/**
* Get translated notification title
* @param key
*/
private getNotificationTitle(key: string) {
return this.translateService.instant(this.notificationsPrefix + key + '.title');
}
/**
* Get translated notification content
* @param key
*/
private getNotificationContent(key: string) {
return this.translateService.instant(this.notificationsPrefix + key + '.content');
}
}