Skip to content

Commit 5e27741

Browse files
authored
Merge pull request DSpace#2183 from atmire/w2p-100302_Live-import-issues-7.5
Fix Live Import issues
2 parents 4847fc6 + 2a90214 commit 5e27741

9 files changed

Lines changed: 145 additions & 14 deletions

src/app/core/data/base/base-data.service.spec.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,62 @@ describe('BaseDataService', () => {
641641
});
642642
});
643643

644+
describe('hasCachedResponse', () => {
645+
it('should return false when the request will be dispatched', (done) => {
646+
const result = service.hasCachedResponse('test-href');
647+
648+
result.subscribe((hasCachedResponse) => {
649+
expect(hasCachedResponse).toBeFalse();
650+
done();
651+
});
652+
});
653+
654+
it('should return true when the request will not be dispatched', (done) => {
655+
(requestService.shouldDispatchRequest as jasmine.Spy).and.returnValue(false);
656+
const result = service.hasCachedResponse('test-href');
657+
658+
result.subscribe((hasCachedResponse) => {
659+
expect(hasCachedResponse).toBeTrue();
660+
done();
661+
});
662+
});
663+
});
664+
665+
describe('hasCachedErrorResponse', () => {
666+
it('should return false when no response is cached', (done) => {
667+
spyOn(service,'hasCachedResponse').and.returnValue(observableOf(false));
668+
const result = service.hasCachedErrorResponse('test-href');
669+
670+
result.subscribe((hasCachedErrorResponse) => {
671+
expect(hasCachedErrorResponse).toBeFalse();
672+
done();
673+
});
674+
});
675+
it('should return false when no error response is cached', (done) => {
676+
spyOn(service,'hasCachedResponse').and.returnValue(observableOf(true));
677+
spyOn(rdbService,'buildSingle').and.returnValue(createSuccessfulRemoteDataObject$({}));
678+
679+
const result = service.hasCachedErrorResponse('test-href');
680+
681+
result.subscribe((hasCachedErrorResponse) => {
682+
expect(hasCachedErrorResponse).toBeFalse();
683+
done();
684+
});
685+
});
686+
687+
it('should return true when an error response is cached', (done) => {
688+
spyOn(service,'hasCachedResponse').and.returnValue(observableOf(true));
689+
spyOn(rdbService,'buildSingle').and.returnValue(createFailedRemoteDataObject$());
690+
691+
const result = service.hasCachedErrorResponse('test-href');
692+
693+
result.subscribe((hasCachedErrorResponse) => {
694+
expect(hasCachedErrorResponse).toBeTrue();
695+
done();
696+
});
697+
});
698+
});
699+
644700
describe('addDependency', () => {
645701
let addDependencySpy;
646702

src/app/core/data/base/base-data.service.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,48 @@ export class BaseDataService<T extends CacheableObject> implements HALDataServic
341341
}
342342
}
343343

344+
/**
345+
* Checks for the provided href whether a response is already cached
346+
* @param href$ The url for which to check whether there is a cached response.
347+
* Can be a string or an Observable<string>
348+
*/
349+
hasCachedResponse(href$: string | Observable<string>): Observable<boolean> {
350+
if (isNotEmpty(href$)) {
351+
if (typeof href$ === 'string') {
352+
href$ = observableOf(href$);
353+
}
354+
return href$.pipe(
355+
isNotEmptyOperator(),
356+
take(1),
357+
map((href: string) => {
358+
const requestId = this.requestService.generateRequestId();
359+
const request = new GetRequest(requestId, href);
360+
return !this.requestService.shouldDispatchRequest(request, true);
361+
}),
362+
);
363+
}
364+
throw new Error(`Can't check whether there is a cached response for an empty href$`);
365+
}
366+
367+
/**
368+
* Checks for the provided href whether an ERROR response is currently cached
369+
* @param href$ The url for which to check whether there is a cached ERROR response.
370+
* Can be a string or an Observable<string>
371+
*/
372+
hasCachedErrorResponse(href$: string | Observable<string>): Observable<boolean> {
373+
return this.hasCachedResponse(href$).pipe(
374+
switchMap((hasCachedResponse) => {
375+
if (hasCachedResponse) {
376+
return this.rdbService.buildSingle(href$).pipe(
377+
getFirstCompletedRemoteData(),
378+
map((rd => rd.hasFailed))
379+
);
380+
}
381+
return observableOf(false);
382+
})
383+
);
384+
}
385+
344386
/**
345387
* Return the links to traverse from the root of the api to the
346388
* endpoint this DataService represents

src/app/core/data/external-source-data.service.spec.ts

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { ExternalSourceEntry } from '../shared/external-source-entry.model';
55
import { of as observableOf } from 'rxjs';
66
import { GetRequest } from './request.models';
77
import { testSearchDataImplementation } from './base/search-data.spec';
8+
import { take } from 'rxjs/operators';
89

910
describe('ExternalSourceService', () => {
1011
let service: ExternalSourceDataService;
@@ -64,19 +65,42 @@ describe('ExternalSourceService', () => {
6465
});
6566

6667
describe('getExternalSourceEntries', () => {
67-
let result;
6868

69-
beforeEach(() => {
70-
result = service.getExternalSourceEntries('test');
71-
});
69+
describe('when no error response is cached', () => {
70+
let result;
71+
beforeEach(() => {
72+
spyOn(service, 'hasCachedErrorResponse').and.returnValue(observableOf(false));
73+
result = service.getExternalSourceEntries('test');
74+
});
7275

73-
it('should send a GetRequest', () => {
74-
expect(requestService.send).toHaveBeenCalledWith(jasmine.any(GetRequest), true);
76+
it('should send a GetRequest', () => {
77+
result.pipe(take(1)).subscribe();
78+
expect(requestService.send).toHaveBeenCalledWith(jasmine.any(GetRequest), true);
79+
});
80+
81+
it('should return the entries', () => {
82+
result.subscribe((resultRD) => {
83+
expect(resultRD.payload.page).toBe(entries);
84+
});
85+
});
7586
});
7687

77-
it('should return the entries', () => {
78-
result.subscribe((resultRD) => {
79-
expect(resultRD.payload.page).toBe(entries);
88+
describe('when an error response is cached', () => {
89+
let result;
90+
beforeEach(() => {
91+
spyOn(service, 'hasCachedErrorResponse').and.returnValue(observableOf(true));
92+
result = service.getExternalSourceEntries('test');
93+
});
94+
95+
it('should send a GetRequest', () => {
96+
result.pipe(take(1)).subscribe();
97+
expect(requestService.send).toHaveBeenCalledWith(jasmine.any(GetRequest), false);
98+
});
99+
100+
it('should return the entries', () => {
101+
result.subscribe((resultRD) => {
102+
expect(resultRD.payload.page).toBe(entries);
103+
});
80104
});
81105
});
82106
});

src/app/core/data/external-source-data.service.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,12 @@ export class ExternalSourceDataService extends IdentifiableDataService<ExternalS
7474
);
7575

7676
// TODO create a dedicated ExternalSourceEntryDataService and move this entire method to it. Then the "as any"s won't be necessary
77-
return this.findListByHref(href$, undefined, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow as any) as any;
77+
78+
return this.hasCachedErrorResponse(href$).pipe(
79+
switchMap((hasCachedErrorResponse) => {
80+
return this.findListByHref(href$, undefined, !hasCachedErrorResponse, reRequestOnStale, ...linksToFollow as any);
81+
})
82+
) as any;
7883
}
7984

8085
/**

src/app/shared/mocks/request.service.mock.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export function getMockRequestService(requestEntry$: Observable<RequestEntry> =
1414
removeByHrefSubstring: observableOf(true),
1515
setStaleByHrefSubstring: observableOf(true),
1616
setStaleByUUID: observableOf(true),
17-
hasByHref$: observableOf(false)
17+
hasByHref$: observableOf(false),
18+
shouldDispatchRequest: true
1819
});
1920
}

src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
<ds-themed-collection-dropdown [ngClass]="{'d-none': isLoading()}"
1010
(selectionChange)="selectObject($event)"
1111
(searchComplete)="searchComplete()"
12-
(theOnlySelectable)="theOnlySelectable($event)"
1312
[entityType]="entityType">
1413
</ds-themed-collection-dropdown>
1514
</div>

src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ describe('SubmissionImportExternalCollectionComponent test suite', () => {
6464
compAsAny = null;
6565
});
6666

67-
it('should emit from selectedEvent on selectObject', () => {
67+
it('should emit from selectedEvent on selectObject and set loading to true', () => {
6868
spyOn(comp.selectedEvent, 'emit').and.callThrough();
6969

7070
const entry = {
@@ -79,6 +79,7 @@ describe('SubmissionImportExternalCollectionComponent test suite', () => {
7979
comp.selectObject(entry);
8080

8181
expect(comp.selectedEvent.emit).toHaveBeenCalledWith(entry);
82+
expect(comp.loading).toBeTrue();
8283
});
8384

8485
it('should dismiss modal on closeCollectionModal', () => {

src/app/submission/import-external/import-external-collection/submission-import-external-collection.component.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export class SubmissionImportExternalCollectionComponent {
3838
* This method emits the selected Collection from the 'selectedEvent' variable.
3939
*/
4040
public selectObject(object: CollectionListEntry): void {
41+
this.loading = true;
4142
this.selectedEvent.emit(object);
4243
}
4344

src/app/submission/import-external/submission-import-external.component.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ import { Context } from '../../core/shared/context.model';
1515
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
1616
import { RouteService } from '../../core/services/route.service';
1717
import { createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils';
18-
import { SubmissionImportExternalPreviewComponent } from './import-external-preview/submission-import-external-preview.component';
18+
import {
19+
SubmissionImportExternalPreviewComponent
20+
} from './import-external-preview/submission-import-external-preview.component';
1921
import { fadeIn } from '../../shared/animations/fade';
2022
import { PageInfo } from '../../core/shared/page-info.model';
2123
import { hasValue, isNotEmpty } from '../../shared/empty.util';

0 commit comments

Comments
 (0)