diff --git a/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts b/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts index 62f8b0abe3..6da37b436b 100644 --- a/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.spec.ts @@ -1,25 +1,14 @@ import { ItemEditBitstreamBundleComponent } from './item-edit-bitstream-bundle.component'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { of as observableOf } from 'rxjs/internal/observable/of'; import { TranslateModule } from '@ngx-translate/core'; -import { VarDirective } from '../../../../shared/utils/var.directive'; -import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; -import { NO_ERRORS_SCHEMA } from '@angular/core'; -import { Bitstream } from '../../../../core/shared/bitstream.model'; -import { createMockRDObs } from '../item-bitstreams.component.spec'; -import { BitstreamFormat } from '../../../../core/shared/bitstream-format.model'; -import { BundleDataService } from '../../../../core/data/bundle-data.service'; -import { createPaginatedList, createSuccessfulRemoteDataObject$ } from '../../../../shared/testing/utils'; -import { ObjectValuesPipe } from '../../../../shared/utils/object-values-pipe'; +import { NO_ERRORS_SCHEMA, ViewContainerRef } from '@angular/core'; import { Item } from '../../../../core/shared/item.model'; import { Bundle } from '../../../../core/shared/bundle.model'; describe('ItemEditBitstreamBundleComponent', () => { let comp: ItemEditBitstreamBundleComponent; let fixture: ComponentFixture; - - let objectUpdatesService: ObjectUpdatesService; - let bundleService: BundleDataService; + let viewContainerRef: ViewContainerRef; const item = Object.assign(new Item(), { id: 'item-1', @@ -30,75 +19,12 @@ describe('ItemEditBitstreamBundleComponent', () => { uuid: 'bundle-1', self: 'bundle-1-selflink' }); - const date = new Date(); - const format = Object.assign(new BitstreamFormat(), { - shortDescription: 'PDF' - }); - const bitstream1 = Object.assign(new Bitstream(), { - uuid: 'bitstreamUUID1', - name: 'Fake Bitstream 1', - bundleName: 'ORIGINAL', - description: 'Description', - format: createMockRDObs(format) - }); - const fieldUpdate1 = { - field: bitstream1, - changeType: undefined - }; - const bitstream2 = Object.assign(new Bitstream(), { - uuid: 'bitstreamUUID2', - name: 'Fake Bitstream 2', - bundleName: 'ORIGINAL', - description: 'Description', - format: createMockRDObs(format) - }); - const fieldUpdate2 = { - field: bitstream2, - changeType: undefined - }; - const batchSize = 10; beforeEach(async(() => { - objectUpdatesService = jasmine.createSpyObj('objectUpdatesService', - { - getFieldUpdates: observableOf({ - [bitstream1.uuid]: fieldUpdate1, - [bitstream2.uuid]: fieldUpdate2, - }), - getFieldUpdatesExclusive: observableOf({ - [bitstream1.uuid]: fieldUpdate1, - [bitstream2.uuid]: fieldUpdate2, - }), - getFieldUpdatesByCustomOrder: observableOf({ - [bitstream1.uuid]: fieldUpdate1, - [bitstream2.uuid]: fieldUpdate2, - }), - saveMoveFieldUpdate: {}, - saveRemoveFieldUpdate: {}, - removeSingleFieldUpdate: {}, - saveAddFieldUpdate: {}, - discardFieldUpdates: {}, - reinstateFieldUpdates: observableOf(true), - initialize: {}, - getUpdatedFields: observableOf([bitstream1, bitstream2]), - getLastModified: observableOf(date), - hasUpdates: observableOf(true), - isReinstatable: observableOf(false), - isValidPage: observableOf(true) - } - ); - - bundleService = jasmine.createSpyObj('bundleService', { - getBitstreams: createSuccessfulRemoteDataObject$(createPaginatedList([bitstream1, bitstream2])) - }); - TestBed.configureTestingModule({ imports: [TranslateModule.forRoot()], - declarations: [ItemEditBitstreamBundleComponent, VarDirective, ObjectValuesPipe], - providers: [ - { provide: ObjectUpdatesService, useValue: objectUpdatesService }, - { provide: BundleDataService, useValue: bundleService } - ], schemas: [ + declarations: [ItemEditBitstreamBundleComponent], + schemas: [ NO_ERRORS_SCHEMA ] }).compileComponents(); @@ -109,35 +35,12 @@ describe('ItemEditBitstreamBundleComponent', () => { comp = fixture.componentInstance; comp.item = item; comp.bundle = bundle; - comp.batchSize = batchSize; + viewContainerRef = (comp as any).viewContainerRef; + spyOn(viewContainerRef, 'createEmbeddedView'); fixture.detectChanges(); }); - describe('A drag-and-drop event', () => { - it('should send a move update to the objectUpdatesService', () => { - const event = { - previousIndex: 0, - currentIndex: 1 - }; - comp.drop(event as any); - expect(objectUpdatesService.saveMoveFieldUpdate).toHaveBeenCalledWith(bundle.self, event.previousIndex, event.currentIndex); - }); - }); - - describe('loadMore', () => { - it('should increase the current size by ' + batchSize, () => { - const initialSize = comp.currentSize$.value; - comp.loadMore(); - const newSize = comp.currentSize$.value; - expect(initialSize + batchSize).toEqual(newSize); - }); - }); - - describe('loadAll', () => { - it('should increase the current size by a lot', () => { - comp.loadAll(); - const newSize = comp.currentSize$.value; - expect(newSize).toBeGreaterThanOrEqual(999); - }); + it('should create an embedded view of the component', () => { + expect(viewContainerRef.createEmbeddedView).toHaveBeenCalled(); }); }); diff --git a/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.spec.ts b/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.spec.ts new file mode 100644 index 0000000000..edb0087b31 --- /dev/null +++ b/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/paginated-drag-and-drop-bitstream-list/paginated-drag-and-drop-bitstream-list.component.spec.ts @@ -0,0 +1,120 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { Bundle } from '../../../../../core/shared/bundle.model'; +import { TranslateModule } from '@ngx-translate/core'; +import { PaginatedDragAndDropBitstreamListComponent } from './paginated-drag-and-drop-bitstream-list.component'; +import { VarDirective } from '../../../../../shared/utils/var.directive'; +import { ObjectValuesPipe } from '../../../../../shared/utils/object-values-pipe'; +import { ObjectUpdatesService } from '../../../../../core/data/object-updates/object-updates.service'; +import { BundleDataService } from '../../../../../core/data/bundle-data.service'; +import { createMockRDObs } from '../../item-bitstreams.component.spec'; +import { Bitstream } from '../../../../../core/shared/bitstream.model'; +import { BitstreamFormat } from '../../../../../core/shared/bitstream-format.model'; +import { createPaginatedList, createSuccessfulRemoteDataObject$ } from '../../../../../shared/testing/utils'; +import { of as observableOf } from 'rxjs/internal/observable/of'; +import { take } from 'rxjs/operators'; + +describe('PaginatedDragAndDropBitstreamListComponent', () => { + let comp: PaginatedDragAndDropBitstreamListComponent; + let fixture: ComponentFixture; + let objectUpdatesService: ObjectUpdatesService; + let bundleService: BundleDataService; + + const bundle = Object.assign(new Bundle(), { + id: 'bundle-1', + uuid: 'bundle-1', + self: 'bundle-1-selflink' + }); + const date = new Date(); + const format = Object.assign(new BitstreamFormat(), { + shortDescription: 'PDF' + }); + const bitstream1 = Object.assign(new Bitstream(), { + uuid: 'bitstreamUUID1', + name: 'Fake Bitstream 1', + bundleName: 'ORIGINAL', + description: 'Description', + format: createMockRDObs(format) + }); + const fieldUpdate1 = { + field: bitstream1, + changeType: undefined + }; + const bitstream2 = Object.assign(new Bitstream(), { + uuid: 'bitstreamUUID2', + name: 'Fake Bitstream 2', + bundleName: 'ORIGINAL', + description: 'Description', + format: createMockRDObs(format) + }); + const fieldUpdate2 = { + field: bitstream2, + changeType: undefined + }; + + beforeEach(async(() => { + objectUpdatesService = jasmine.createSpyObj('objectUpdatesService', + { + getFieldUpdates: observableOf({ + [bitstream1.uuid]: fieldUpdate1, + [bitstream2.uuid]: fieldUpdate2, + }), + getFieldUpdatesExclusive: observableOf({ + [bitstream1.uuid]: fieldUpdate1, + [bitstream2.uuid]: fieldUpdate2, + }), + getFieldUpdatesByCustomOrder: observableOf({ + [bitstream1.uuid]: fieldUpdate1, + [bitstream2.uuid]: fieldUpdate2, + }), + saveMoveFieldUpdate: {}, + saveRemoveFieldUpdate: {}, + removeSingleFieldUpdate: {}, + saveAddFieldUpdate: {}, + discardFieldUpdates: {}, + reinstateFieldUpdates: observableOf(true), + initialize: {}, + getUpdatedFields: observableOf([bitstream1, bitstream2]), + getLastModified: observableOf(date), + hasUpdates: observableOf(true), + isReinstatable: observableOf(false), + isValidPage: observableOf(true), + initializeWithCustomOrder: {}, + addPageToCustomOrder: {} + } + ); + + bundleService = jasmine.createSpyObj('bundleService', { + getBitstreams: createSuccessfulRemoteDataObject$(createPaginatedList([bitstream1, bitstream2])) + }); + + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot()], + declarations: [PaginatedDragAndDropBitstreamListComponent, VarDirective, ObjectValuesPipe], + providers: [ + { provide: ObjectUpdatesService, useValue: objectUpdatesService }, + { provide: BundleDataService, useValue: bundleService } + ], schemas: [ + NO_ERRORS_SCHEMA + ] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(PaginatedDragAndDropBitstreamListComponent); + comp = fixture.componentInstance; + comp.bundle = bundle; + fixture.detectChanges(); + }); + + it('should initialize the objectsRD$', (done) => { + comp.objectsRD$.pipe(take(1)).subscribe((objects) => { + expect(objects.payload.page).toEqual([bitstream1, bitstream2]); + done(); + }); + }); + + it('should initialize the URL', () => { + expect(comp.url).toEqual(bundle.self); + }); +}); diff --git a/src/app/core/data/object-updates/object-updates.reducer.spec.ts b/src/app/core/data/object-updates/object-updates.reducer.spec.ts index 1fe3b97070..dc2d3cb508 100644 --- a/src/app/core/data/object-updates/object-updates.reducer.spec.ts +++ b/src/app/core/data/object-updates/object-updates.reducer.spec.ts @@ -1,6 +1,6 @@ import * as deepFreeze from 'deep-freeze'; import { - AddFieldUpdateAction, + AddFieldUpdateAction, AddPageToCustomOrderAction, DiscardObjectUpdatesAction, FieldChangeType, InitializeFieldsAction, MoveFieldUpdateAction, @@ -81,8 +81,13 @@ describe('objectUpdatesReducer', () => { }, lastModified: modDate, customOrder: { - initialOrder: [identifiable1.uuid, identifiable2.uuid, identifiable3.uuid], - newOrder: [identifiable1.uuid, identifiable2.uuid, identifiable3.uuid], + initialOrderPages: [ + { order: [identifiable1.uuid, identifiable2.uuid, identifiable3.uuid] } + ], + newOrderPages: [ + { order: [identifiable1.uuid, identifiable2.uuid, identifiable3.uuid] } + ], + pageSize: 10, changed: false } } @@ -109,8 +114,13 @@ describe('objectUpdatesReducer', () => { }, lastModified: modDate, customOrder: { - initialOrder: [identifiable1.uuid, identifiable2.uuid, identifiable3.uuid], - newOrder: [identifiable1.uuid, identifiable2.uuid, identifiable3.uuid], + initialOrderPages: [ + { order: [identifiable1.uuid, identifiable2.uuid, identifiable3.uuid] } + ], + newOrderPages: [ + { order: [identifiable1.uuid, identifiable2.uuid, identifiable3.uuid] } + ], + pageSize: 10, changed: false } }, @@ -145,8 +155,13 @@ describe('objectUpdatesReducer', () => { }, lastModified: modDate, customOrder: { - initialOrder: [identifiable1.uuid, identifiable2.uuid, identifiable3.uuid], - newOrder: [identifiable1.uuid, identifiable2.uuid, identifiable3.uuid], + initialOrderPages: [ + { order: [identifiable1.uuid, identifiable2.uuid, identifiable3.uuid] } + ], + newOrderPages: [ + { order: [identifiable1.uuid, identifiable2.uuid, identifiable3.uuid] } + ], + pageSize: 10, changed: false } } @@ -211,7 +226,7 @@ describe('objectUpdatesReducer', () => { }); it('should initialize all fields when the INITIALIZE action is dispatched, based on the payload', () => { - const action = new InitializeFieldsAction(url, [identifiable1, identifiable3], modDate); + const action = new InitializeFieldsAction(url, [identifiable1, identifiable3], modDate, [identifiable1.uuid, identifiable3.uuid], 10, 0); const expectedState = { [url]: { @@ -230,8 +245,13 @@ describe('objectUpdatesReducer', () => { fieldUpdates: {}, lastModified: modDate, customOrder: { - initialOrder: [], - newOrder: [], + initialOrderPages: [ + { order: [identifiable1.uuid, identifiable3.uuid] } + ], + newOrderPages: [ + { order: [identifiable1.uuid, identifiable3.uuid] } + ], + pageSize: 10, changed: false } } @@ -301,11 +321,28 @@ describe('objectUpdatesReducer', () => { }); it('should move the custom order from the state when the MOVE action is dispatched', () => { - const action = new MoveFieldUpdateAction(url, 0, 1); + const action = new MoveFieldUpdateAction(url, 0, 1, 0, 0); const newState = objectUpdatesReducer(testState, action); - expect(newState[url].customOrder.newOrder[0]).toEqual(testState[url].customOrder.newOrder[1]); - expect(newState[url].customOrder.newOrder[1]).toEqual(testState[url].customOrder.newOrder[0]); + expect(newState[url].customOrder.newOrderPages[0].order[0]).toEqual(testState[url].customOrder.newOrderPages[0].order[1]); + expect(newState[url].customOrder.newOrderPages[0].order[1]).toEqual(testState[url].customOrder.newOrderPages[0].order[0]); expect(newState[url].customOrder.changed).toEqual(true); }); + + it('should add a new page to the custom order and add empty pages in between when the ADD_PAGE_TO_CUSTOM_ORDER action is dispatched', () => { + const identifiable4 = { + uuid: 'a23eae5a-7857-4ef9-8e52-989436ad2955', + key: 'dc.description.abstract', + language: null, + value: 'Extra value' + }; + const action = new AddPageToCustomOrderAction(url, [identifiable4], [identifiable4.uuid], 2); + + const newState = objectUpdatesReducer(testState, action); + // Confirm the page in between the two pages (index 1) has been filled with 10 (page size) undefined values + expect(newState[url].customOrder.newOrderPages[1].order.length).toEqual(10); + expect(newState[url].customOrder.newOrderPages[1].order[0]).toBeUndefined(); + // Verify the new page is correct + expect(newState[url].customOrder.newOrderPages[2].order[0]).toEqual(identifiable4.uuid); + }); }); diff --git a/src/app/core/data/object-updates/object-updates.service.spec.ts b/src/app/core/data/object-updates/object-updates.service.spec.ts index 9038832a0c..924b7dd996 100644 --- a/src/app/core/data/object-updates/object-updates.service.spec.ts +++ b/src/app/core/data/object-updates/object-updates.service.spec.ts @@ -2,6 +2,7 @@ import { Store } from '@ngrx/store'; import { CoreState } from '../../core.reducers'; import { ObjectUpdatesService } from './object-updates.service'; import { + AddPageToCustomOrderAction, DiscardObjectUpdatesAction, FieldChangeType, InitializeFieldsAction, ReinstateObjectUpdatesAction, RemoveFieldUpdateAction, @@ -58,6 +59,25 @@ describe('ObjectUpdatesService', () => { }); }); + describe('initializeWithCustomOrder', () => { + const pageSize = 20; + const page = 0; + + it('should dispatch an INITIALIZE action with the correct URL, initial identifiables, last modified , custom order, page size and page', () => { + service.initializeWithCustomOrder(url, identifiables, modDate, pageSize, page); + expect(store.dispatch).toHaveBeenCalledWith(new InitializeFieldsAction(url, identifiables, modDate, identifiables.map((identifiable) => identifiable.uuid), pageSize, page)); + }); + }); + + describe('addPageToCustomOrder', () => { + const page = 2; + + it('should dispatch an ADD_PAGE_TO_CUSTOM_ORDER action with the correct URL, identifiables, custom order and page number to add', () => { + service.addPageToCustomOrder(url, identifiables, page); + expect(store.dispatch).toHaveBeenCalledWith(new AddPageToCustomOrderAction(url, identifiables, identifiables.map((identifiable) => identifiable.uuid), page)); + }); + }); + describe('getFieldUpdates', () => { it('should return the list of all fields, including their update if there is one', () => { const result$ = service.getFieldUpdates(url, identifiables); diff --git a/src/app/core/data/object-updates/object-updates.service.ts b/src/app/core/data/object-updates/object-updates.service.ts index 0980f182c1..4ae5810fe3 100644 --- a/src/app/core/data/object-updates/object-updates.service.ts +++ b/src/app/core/data/object-updates/object-updates.service.ts @@ -73,6 +73,12 @@ export class ObjectUpdatesService { this.store.dispatch(new InitializeFieldsAction(url, fields, lastModified, fields.map((field) => field.uuid), pageSize, page)); } + /** + * Method to dispatch an AddPageToCustomOrderAction, adding a new page to an already existing custom order tracking + * @param url The URL for which the changes are being mapped + * @param fields The fields to add a new page for + * @param page The page number (starting from index 0) + */ addPageToCustomOrder(url, fields: Identifiable[], page: number): void { this.store.dispatch(new AddPageToCustomOrderAction(url, fields, fields.map((field) => field.uuid), page)); } diff --git a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts new file mode 100644 index 0000000000..84f3381880 --- /dev/null +++ b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.spec.ts @@ -0,0 +1,178 @@ +import { AbstractPaginatedDragAndDropListComponent } from './abstract-paginated-drag-and-drop-list.component'; +import { DSpaceObject } from '../../core/shared/dspace-object.model'; +import { ObjectUpdatesService } from '../../core/data/object-updates/object-updates.service'; +import { ElementRef } from '@angular/core'; +import { Observable } from 'rxjs/internal/Observable'; +import { PaginatedList } from '../../core/data/paginated-list'; +import { RemoteData } from '../../core/data/remote-data'; +import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; +import { createPaginatedList, createSuccessfulRemoteDataObject } from '../testing/utils'; +import { FieldUpdates } from '../../core/data/object-updates/object-updates.reducer'; +import { of as observableOf } from 'rxjs'; +import { take } from 'rxjs/operators'; +import { PaginationComponent } from '../pagination/pagination.component'; + +class MockAbstractPaginatedDragAndDropListComponent extends AbstractPaginatedDragAndDropListComponent { + + constructor(protected objectUpdatesService: ObjectUpdatesService, + protected elRef: ElementRef, + protected mockUrl: string, + protected mockObjectsRD$: Observable>>) { + super(objectUpdatesService, elRef); + } + + initializeObjectsRD(): void { + this.objectsRD$ = this.mockObjectsRD$; + } + + initializeURL(): void { + this.url = this.mockUrl; + } +} + +describe('AbstractPaginatedDragAndDropListComponent', () => { + let component: MockAbstractPaginatedDragAndDropListComponent; + let objectUpdatesService: ObjectUpdatesService; + let elRef: ElementRef; + + const url = 'mock-abstract-paginated-drag-and-drop-list-component'; + + const object1 = Object.assign(new DSpaceObject(), { uuid: 'object-1' }); + const object2 = Object.assign(new DSpaceObject(), { uuid: 'object-2' }); + const objectsRD = createSuccessfulRemoteDataObject(createPaginatedList([object1, object2])); + let objectsRD$: BehaviorSubject>>; + + const updates = { + [object1.uuid]: { field: object1, changeType: undefined }, + [object2.uuid]: { field: object2, changeType: undefined } + } as FieldUpdates; + + let paginationComponent: PaginationComponent; + + beforeEach(() => { + objectUpdatesService = jasmine.createSpyObj('objectUpdatesService', { + initializeWithCustomOrder: {}, + addPageToCustomOrder: {}, + getFieldUpdatesByCustomOrder: observableOf(updates), + saveMoveFieldUpdate: {} + }); + elRef = { + nativeElement: jasmine.createSpyObj('nativeElement', { + querySelector: {} + }) + }; + paginationComponent = jasmine.createSpyObj('paginationComponent', { + doPageChange: {} + }); + objectsRD$ = new BehaviorSubject(objectsRD); + component = new MockAbstractPaginatedDragAndDropListComponent(objectUpdatesService, elRef, url, objectsRD$); + component.paginationComponent = paginationComponent; + component.ngOnInit(); + }); + + it('should call initializeWithCustomOrder to initialize the first page and add it to initializedPages', (done) => { + expect(component.initializedPages.indexOf(0)).toBeLessThan(0); + component.updates$.pipe(take(1)).subscribe(() => { + expect(objectUpdatesService.initializeWithCustomOrder).toHaveBeenCalled(); + expect(component.initializedPages.indexOf(0)).toBeGreaterThanOrEqual(0); + done(); + }); + }); + + it('should initialize the updates correctly', (done) => { + component.updates$.pipe(take(1)).subscribe((fieldUpdates) => { + expect(fieldUpdates).toEqual(updates); + done(); + }); + }); + + describe('when a new page is loaded', () => { + const page = 5; + + beforeEach((done) => { + component.updates$.pipe(take(1)).subscribe(() => { + component.currentPage$.next(page); + objectsRD$.next(objectsRD); + done(); + }); + }); + + it('should call addPageToCustomOrder to initialize the new page and add it to initializedPages', (done) => { + component.updates$.pipe(take(1)).subscribe(() => { + expect(objectUpdatesService.addPageToCustomOrder).toHaveBeenCalled(); + expect(component.initializedPages.indexOf(page - 1)).toBeGreaterThanOrEqual(0); + done(); + }); + }); + + describe('twice', () => { + beforeEach((done) => { + component.updates$.pipe(take(1)).subscribe(() => { + component.currentPage$.next(page); + objectsRD$.next(objectsRD); + done(); + }); + }); + + it('shouldn\'t call addPageToCustomOrder again, as the page has already been initialized', (done) => { + component.updates$.pipe(take(1)).subscribe(() => { + expect(objectUpdatesService.addPageToCustomOrder).toHaveBeenCalledTimes(1); + done(); + }); + }); + }); + }); + + describe('switchPage', () => { + const page = 3; + + beforeEach(() => { + component.switchPage(page); + }); + + it('should set currentPage$ to the new page', () => { + expect(component.currentPage$.value).toEqual(page); + }); + }); + + describe('drop', () => { + const event = { + previousIndex: 0, + currentIndex: 1, + item: { element: { nativeElement: { id: object1.uuid } } } + } as any; + + describe('when the user is hovering over a new page', () => { + const hoverPage = 3; + const hoverElement = { textContent: '' + hoverPage }; + + beforeEach(() => { + elRef.nativeElement.querySelector.and.returnValue(hoverElement); + component.initializedPages.push(hoverPage - 1); + component.drop(event); + }); + + it('should detect the page and set currentPage$ to its value', () => { + expect(component.currentPage$.value).toEqual(hoverPage); + }); + + it('should detect the page and update the pagination component with its value', () => { + expect(paginationComponent.doPageChange).toHaveBeenCalledWith(hoverPage); + }); + + it('should send out a saveMoveFieldUpdate with the correct values', () => { + expect(objectUpdatesService.saveMoveFieldUpdate).toHaveBeenCalledWith(url, event.previousIndex, 0, 0, hoverPage - 1, object1); + }); + }); + + describe('when the user is not hovering over a new page', () => { + beforeEach(() => { + component.drop(event); + }); + + it('should send out a saveMoveFieldUpdate with the correct values', () => { + expect(objectUpdatesService.saveMoveFieldUpdate).toHaveBeenCalledWith(url, event.previousIndex, event.currentIndex, 0, 0); + }); + }); + }); +}); diff --git a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts index 14aedcaf82..7f616aa772 100644 --- a/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts +++ b/src/app/shared/pagination-drag-and-drop/abstract-paginated-drag-and-drop-list.component.ts @@ -6,7 +6,7 @@ import { PaginationComponentOptions } from '../pagination/pagination-component-o import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; import { ObjectUpdatesService } from '../../core/data/object-updates/object-updates.service'; import { switchMap, take, tap } from 'rxjs/operators'; -import { hasValue, isEmpty } from '../empty.util'; +import { hasValue, isEmpty, isNotEmpty } from '../empty.util'; import { paginatedListToArray } from '../../core/shared/operators'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { CdkDragDrop } from '@angular/cdk/drag-drop'; @@ -152,7 +152,7 @@ export abstract class AbstractPaginatedDragAndDropListComponent) { // Check if the user is hovering over any of the pagination's pages at the time of dropping the object const droppedOnElement = this.elRef.nativeElement.querySelector('.page-item:hover'); - if (hasValue(droppedOnElement)) { + if (isNotEmpty(droppedOnElement)) { // The user is hovering over a page, fetch the page's number from the element const page = Number(droppedOnElement.textContent); if (hasValue(page) && !Number.isNaN(page)) {