diff --git a/src/app/core/data/version-data.service.spec.ts b/src/app/core/data/version-data.service.spec.ts new file mode 100644 index 0000000000..5a8caf31be --- /dev/null +++ b/src/app/core/data/version-data.service.spec.ts @@ -0,0 +1,181 @@ +import { HttpClient } from '@angular/common/http'; +import { of as observableOf } from 'rxjs'; +import { TestScheduler } from 'rxjs/testing'; + +import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { ObjectCacheService } from '../cache/object-cache.service'; +import { HALEndpointService } from '../shared/hal-endpoint.service'; +import { RequestService } from './request.service'; +import { PageInfo } from '../shared/page-info.model'; +import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { RequestEntry } from './request.reducer'; +import { HrefOnlyDataService } from './href-only-data.service'; +import { getMockHrefOnlyDataService } from '../../shared/mocks/href-only-data.service.mock'; + +import { Store } from '@ngrx/store'; +import { CoreState } from '../core.reducers'; +import { RestResponse } from '../cache/response.models'; +import { cold, getTestScheduler, hot } from 'jasmine-marbles'; +import { Item } from '../shared/item.model'; +import { VersionDataService } from './version-data.service'; +import { Version } from '../shared/version.model'; +import { VersionHistory } from '../shared/version-history.model'; +import { followLink } from '../../shared/utils/follow-link-config.model'; + + +describe('VersionDataService test', () => { + let scheduler: TestScheduler; + let service: VersionDataService; + let requestService: RequestService; + let rdbService: RemoteDataBuildService; + let objectCache: ObjectCacheService; + let halService: HALEndpointService; + let hrefOnlyDataService: HrefOnlyDataService; + let responseCacheEntry: RequestEntry; + + const item = Object.assign(new Item(), { + id: '1234-1234', + uuid: '1234-1234', + bundles: observableOf({}), + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'dc.type': [ + { + language: null, + value: 'Article' + } + ], + 'dc.contributor.author': [ + { + language: 'en_US', + value: 'Smith, Donald' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '2015-06-26' + } + ] + } + }); + const itemRD = createSuccessfulRemoteDataObject(item); + + const versionHistory = Object.assign(new VersionHistory(), { + id: '1', + draftVersion: true, + }); + + const mockVersion: Version = Object.assign(new Version(), { + item: createSuccessfulRemoteDataObject$(item), + versionhistory: createSuccessfulRemoteDataObject$(versionHistory), + version: 1, + }); + const mockVersionRD = createSuccessfulRemoteDataObject(mockVersion); + + const endpointURL = `https://rest.api/rest/api/versioning/versions`; + const findByIdRequestURL = `https://rest.api/rest/api/versioning/versions/${mockVersion.id}`; + const findByIdRequestURL$ = observableOf(findByIdRequestURL); + + const requestUUID = '8b3c613a-5a4b-438b-9686-be1d5b4a1c5a'; + + objectCache = {} as ObjectCacheService; + const notificationsService = {} as NotificationsService; + const http = {} as HttpClient; + const comparator = {} as any; + const comparatorEntry = {} as any; + const store = {} as Store; + const pageInfo = new PageInfo(); + + function initTestService() { + hrefOnlyDataService = getMockHrefOnlyDataService(); + return new VersionDataService( + requestService, + rdbService, + store, + objectCache, + halService, + notificationsService, + http, + comparatorEntry + ); + } + + describe('', () => { + beforeEach(() => { + + scheduler = getTestScheduler(); + + halService = jasmine.createSpyObj('halService', { + getEndpoint: cold('a', { a: endpointURL }) + }); + responseCacheEntry = new RequestEntry(); + responseCacheEntry.request = { href: 'https://rest.api/' } as any; + responseCacheEntry.response = new RestResponse(true, 200, 'Success'); + + requestService = jasmine.createSpyObj('requestService', { + generateRequestId: requestUUID, + send: true, + removeByHrefSubstring: {}, + getByHref: observableOf(responseCacheEntry), + getByUUID: observableOf(responseCacheEntry), + }); + rdbService = jasmine.createSpyObj('rdbService', { + buildSingle: hot('(a|)', { + a: mockVersionRD + }) + }); + + service = initTestService(); + + spyOn((service as any), 'findByHref').and.callThrough(); + spyOn((service as any), 'getIDHrefObs').and.returnValue(findByIdRequestURL$); + }); + + afterEach(() => { + service = null; + }); + + describe('getHistoryFromVersion', () => { + it('should proxy the call to DataService.findByHref', () => { + scheduler.schedule(() => service.getHistoryFromVersion(mockVersion, true, true)); + scheduler.flush(); + + expect((service as any).findByHref).toHaveBeenCalledWith(findByIdRequestURL$, true, true, followLink('versionhistory')); + }); + + it('should return a VersionHistory', () => { + const result = service.getHistoryFromVersion(mockVersion, true, true); + const expected = cold('(a|)', { + a: versionHistory + }); + expect(result).toBeObservable(expected); + }); + + it('should return an EMPTY observable when version is not given', () => { + const result = service.getHistoryFromVersion(null); + const expected = cold('|'); + expect(result).toBeObservable(expected); + }); + }); + + describe('getHistoryIdFromVersion', () => { + it('should return the version history id', () => { + spyOn((service as any), 'getHistoryFromVersion').and.returnValue(observableOf(versionHistory)); + + const result = service.getHistoryIdFromVersion(mockVersion); + const expected = cold('(a|)', { + a: versionHistory.id + }); + expect(result).toBeObservable(expected); + }); + }); + }); + +}); diff --git a/src/app/core/data/version-data.service.ts b/src/app/core/data/version-data.service.ts index f310b9a530..70231122c3 100644 --- a/src/app/core/data/version-data.service.ts +++ b/src/app/core/data/version-data.service.ts @@ -10,7 +10,6 @@ import { HALEndpointService } from '../shared/hal-endpoint.service'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { HttpClient } from '@angular/common/http'; import { DefaultChangeAnalyzer } from './default-change-analyzer.service'; -import { FindListOptions } from './request.models'; import { EMPTY, Observable } from 'rxjs'; import { dataService } from '../cache/builders/build-decorators'; import { VERSION } from '../shared/version.resource-type'; @@ -18,6 +17,7 @@ import { VersionHistory } from '../shared/version-history.model'; import { followLink } from '../../shared/utils/follow-link-config.model'; import { getFirstSucceededRemoteDataPayload } from '../shared/operators'; import { map, switchMap } from 'rxjs/operators'; +import { isNotEmpty } from '../../shared/empty.util'; /** * Service responsible for handling requests related to the Version object @@ -39,21 +39,18 @@ export class VersionDataService extends DataService { super(); } - /** - * Get the endpoint for browsing versions - */ - getBrowseEndpoint(options: FindListOptions = {}, linkPath?: string): Observable { - return this.halService.getEndpoint(this.linkPath); - } - /** * Get the version history for the given version * @param version + * @param useCachedVersionIfAvailable If this is true, the request will only be sent if there's + * no valid cached version. Defaults to true + * @param reRequestOnStale Whether or not the request should automatically be re- + * requested after the response becomes stale */ - getHistoryFromVersion$(version: Version): Observable { - return version ? this.findById(version.id, false, true, followLink('versionhistory')).pipe( + getHistoryFromVersion(version: Version, useCachedVersionIfAvailable = false, reRequestOnStale = true): Observable { + return isNotEmpty(version) ? this.findById(version.id, useCachedVersionIfAvailable, reRequestOnStale, followLink('versionhistory')).pipe( getFirstSucceededRemoteDataPayload(), - switchMap((res) => res.versionhistory), + switchMap((res: Version) => res.versionhistory), getFirstSucceededRemoteDataPayload(), ) : EMPTY; } @@ -62,9 +59,9 @@ export class VersionDataService extends DataService { * Get the ID of the version history for the given version * @param version */ - getHistoryIdFromVersion$(version: Version): Observable { - return this.getHistoryFromVersion$(version).pipe( - map((versionHistory) => versionHistory.id), + getHistoryIdFromVersion(version: Version): Observable { + return this.getHistoryFromVersion(version).pipe( + map((versionHistory: VersionHistory) => versionHistory.id), ); } diff --git a/src/app/core/data/version-history-data.service.ts b/src/app/core/data/version-history-data.service.ts index ef537b72aa..4268516e6b 100644 --- a/src/app/core/data/version-history-data.service.ts +++ b/src/app/core/data/version-history-data.service.ts @@ -175,7 +175,7 @@ export class VersionHistoryDataService extends DataService { if (res.hasSucceeded && !res.hasNoContent) { return of(res).pipe( getFirstSucceededRemoteDataPayload(), - switchMap((version) => this.versionDataService.getHistoryFromVersion$(version)), + switchMap((version) => this.versionDataService.getHistoryFromVersion(version)), map((versionHistory) => versionHistory ? versionHistory.draftVersion : false), ); } else { @@ -201,7 +201,7 @@ export class VersionHistoryDataService extends DataService { * @param version */ getVersionHistoryFromVersion$(version: Version): Observable { - return this.versionDataService.getHistoryIdFromVersion$(version).pipe( + return this.versionDataService.getHistoryIdFromVersion(version).pipe( take(1), switchMap((res) => this.findById(res)), getFirstSucceededRemoteDataPayload(), diff --git a/src/app/shared/item/item-versions/item-versions.component.ts b/src/app/shared/item/item-versions/item-versions.component.ts index edde745a02..aa00ab1d9e 100644 --- a/src/app/shared/item/item-versions/item-versions.component.ts +++ b/src/app/shared/item/item-versions/item-versions.component.ts @@ -345,7 +345,7 @@ export class ItemVersionsComponent implements OnInit { tap((newVersionRD: RemoteData) => { this.itemVersionShared.notifyCreateNewVersion(newVersionRD); if (newVersionRD.hasSucceeded) { - const versionHistory$ = this.versionService.getHistoryFromVersion$(version).pipe( + const versionHistory$ = this.versionService.getHistoryFromVersion(version).pipe( tap((versionHistory: VersionHistory) => { this.itemService.invalidateItemCache(this.item.uuid); this.versionHistoryService.invalidateVersionHistoryCache(versionHistory.id);