diff --git a/src/app/core/data/item-data.service.spec.ts b/src/app/core/data/item-data.service.spec.ts index 2c20ed0fb69..58ae7a15cd8 100644 --- a/src/app/core/data/item-data.service.spec.ts +++ b/src/app/core/data/item-data.service.spec.ts @@ -10,7 +10,7 @@ import { ObjectCacheService } from '../cache/object-cache.service'; import { RestResponse } from '../cache/response.models'; import { ExternalSourceEntry } from '../shared/external-source-entry.model'; import { ItemDataService } from './item-data.service'; -import { DeleteRequest, PostRequest } from './request.models'; +import { DeleteRequest, PostRequest, GetRequest } from './request.models'; import { RequestService } from './request.service'; import { getMockRemoteDataBuildService } from '../../shared/mocks/remote-data-build.service.mock'; import { CoreState } from '../core-state.model'; @@ -192,6 +192,20 @@ describe('ItemDataService', () => { }); }); + describe('findItemsWithEdit', () => { + beforeEach(() => { + service = initTestService(); + }); + + it('should send a GET request', (done) => { + const result = service.findItemsWithEdit('', {}); + result.subscribe(() => { + expect(requestService.send).toHaveBeenCalledWith(jasmine.any(GetRequest), true); + done(); + }); + }); + }); + describe('when cache is invalidated', () => { beforeEach(() => { service = initTestService(); diff --git a/src/app/core/data/item-data.service.ts b/src/app/core/data/item-data.service.ts index aef5e90f37c..58db598a1bc 100644 --- a/src/app/core/data/item-data.service.ts +++ b/src/app/core/data/item-data.service.ts @@ -392,16 +392,6 @@ export abstract class BaseItemDataService extends IdentifiableDataService return this.createData.create(object, ...params); } - // private getSearchEndpoint(topic: string): Observable { - // return this.halService.getEndpoint(this.linkPath).pipe( - // map((endpoint: string) => { - // let result = `${endpoint}/search/${topic}`; - // console.log(result); - // return result; - // }) - // ); - // } - /** * Make a new FindListRequest with given search method * diff --git a/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts b/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts index c47931d4da1..91f15567959 100644 --- a/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts +++ b/src/app/shared/dso-selector/dso-selector/dso-selector.component.ts @@ -173,9 +173,7 @@ export class DSOSelectorComponent implements OnInit, OnDestroy { // If no query is entered, filter out the current DSO from the results, as it'll be displayed at the start of the list already const part1 = ((isEmpty(query) && page === 1) ? currentDSOResult.page : []); const part2 = rd.payload.page.filter((result) => isNotEmpty(query) || result.indexableObject.id !== this.currentDSOId); - rd.payload.page = [ - ...part1, ...part2 - ]; + rd.payload.page = [ ...part1, ...part2 ]; } else if (rd.hasFailed) { this.notifcationsService.error(this.translate.instant('dso-selector.error.title', { type: this.typesString }), rd.errorMessage); } diff --git a/src/app/shared/dso-selector/dso-selector/editable-item-selector/editable-item-selector.component.spec.ts b/src/app/shared/dso-selector/dso-selector/editable-item-selector/editable-item-selector.component.spec.ts index b5a2f39b627..518ed548e90 100644 --- a/src/app/shared/dso-selector/dso-selector/editable-item-selector/editable-item-selector.component.spec.ts +++ b/src/app/shared/dso-selector/dso-selector/editable-item-selector/editable-item-selector.component.spec.ts @@ -1,25 +1,121 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { EditableItemSelectorComponent } from './editable-item-selector.component'; +import { FindListOptions } from '../../../../core/data/find-list-options.model'; +import { Observable, of as observableOf } from 'rxjs'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { PaginatedList } from '../../../../core/data/paginated-list.model'; +import { Item } from '../../../../core/shared/item.model'; +import { RequestEntryState } from '../../../../core/data/request-entry-state.model'; +import { createSuccessfulRemoteDataObject$, createFailedRemoteDataObject$ } from '../../../remote-data.utils'; +import { createPaginatedList } from '../../../testing/utils.test'; +import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model'; +import { ItemDataService } from '../../../../core/data/item-data.service'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { NotificationsService } from '../../../notifications/notifications.service'; +import { DSpaceObjectType } from '../../../../core/shared/dspace-object-type.model'; +import { SearchService } from '../../../../core/shared/search/search.service'; +import { TranslateModule } from '@ngx-translate/core'; describe('EditableItemSelectorComponent', () => { let component: EditableItemSelectorComponent; let fixture: ComponentFixture; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ EditableItemSelectorComponent ] - }) - .compileComponents(); - }); + function createFindItemsResult(name: string): Item { + return Object.assign(new Item(), { + id: `test-result-${name}`, + metadata: { + 'dc.title': [ + { + value: `test-result - ${name}` + } + ] + } + }); + } + + const currentDSOId = 'test-uuid-ford-sose'; + const type = DSpaceObjectType.ITEM; + const currentResult = createFindItemsResult('current'); + const pages = [ + ['1','2','3'].map(createFindItemsResult), + ['4','5','6'].map(createFindItemsResult), + ]; + const itemDataService = { + findItemsWithEdit: (query: string, options: FindListOptions, + useCachedVersionIfAvailable = true, reRequestOnStale = true) => { + return createSuccessfulRemoteDataObject$(createPaginatedList( + query.startsWith('search.resourceid') ? [currentResult] : pages[options.currentPage - 1] + )); + } + }; + let notificationsService: NotificationsService; + + beforeEach(waitForAsync( () => { + notificationsService = jasmine.createSpyObj('notificationsService', ['error']); + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [EditableItemSelectorComponent], + providers: [ + { provide: ItemDataService, useValue: itemDataService }, + { provide: NotificationsService, useValue: notificationsService }, + { provide: SearchService, useValue: {} }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + })); beforeEach(() => { fixture = TestBed.createComponent(EditableItemSelectorComponent); component = fixture.componentInstance; + component.currentDSOId = currentDSOId; + component.types = [type]; fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); + + describe('populating listEntries', () => { + it('should not be empty', (done) => { + component.listEntries$.subscribe((listEntries) => { + expect(listEntries.length).toBeGreaterThan(0); + done(); + }); + }); + + it('should contain a combination of the current DSO and first page results', (done) => { + component.listEntries$.subscribe((listEntries) => { + expect(listEntries.map(entry => entry.indexableObject)) + .toEqual([currentResult, ...pages[0]]); + done(); + }); + }); + + describe('when current page increases', () => { + beforeEach(() => { + component.currentPage$.next(2); + }); + + it('should contain a combination of the current DSO, as well as first and second page results', (done) => { + component.listEntries$.subscribe((listEntries) => { + expect(listEntries.map(entry => entry.indexableObject)) + .toEqual([currentResult, ...pages[0], ...pages[1]]); + done(); + }); + }); + }); + + describe('when search returns an error', () => { + beforeEach(() => { + spyOn(itemDataService, 'findItemsWithEdit').and.returnValue(createFailedRemoteDataObject$()); + component.ngOnInit(); + }); + + it('should display an error notification', () => { + expect(notificationsService.error).toHaveBeenCalled(); + }); + }); + }); }); diff --git a/src/app/shared/dso-selector/dso-selector/editable-item-selector/editable-item-selector.component.ts b/src/app/shared/dso-selector/dso-selector/editable-item-selector/editable-item-selector.component.ts index 25ed722c9e5..c66c45e3b31 100644 --- a/src/app/shared/dso-selector/dso-selector/editable-item-selector/editable-item-selector.component.ts +++ b/src/app/shared/dso-selector/dso-selector/editable-item-selector/editable-item-selector.component.ts @@ -40,15 +40,13 @@ export class EditableItemSelectorComponent extends DSOSelectorComponent { * Find the list of items that can be edited by the current user. */ search(query: string, page: number): - Observable>>> - { + Observable>>> { const findOptions: FindListOptions = { currentPage: page, elementsPerPage: this.defaultPagination.pageSize }; return this.itemDataService.findItemsWithEdit(query, findOptions, true, true, followLink('owningCollection')).pipe( getFirstCompletedRemoteData(), - tap((rdata) => console.log('TAPPEDITAP:', rdata)), // XXX mapRemoteDataPayload((payload) => hasValue(payload) ? buildPaginatedList(payload.pageInfo, payload.page.map((item) => Object.assign(new ItemSearchResult(), { indexableObject: item }))) diff --git a/src/themes/custom/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts b/src/themes/custom/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts index 398dbc933c0..50cf8c9a20c 100644 --- a/src/themes/custom/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts +++ b/src/themes/custom/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts @@ -5,8 +5,6 @@ import { @Component({ selector: 'ds-edit-item-selector', - // styleUrls: ['./edit-item-selector.component.scss'], - // templateUrl: './edit-item-selector.component.html', templateUrl: '../../../../../../../app/shared/dso-selector/modal-wrappers/dso-selector-modal-wrapper.component.html', }) export class EditItemSelectorComponent extends BaseComponent {