@@ -23,6 +23,7 @@ import {
2323import { CommunityDataService } from '@dspace/core/data/community-data.service' ;
2424import { RemoteData } from '@dspace/core/data/remote-data' ;
2525import { APP_DATA_SERVICES_MAP } from '@dspace/core/data-services-map-type' ;
26+ import { PaginationService } from '@dspace/core/pagination/pagination.service' ;
2627import { PaginationComponentOptions } from '@dspace/core/pagination/pagination-component-options.model' ;
2728import {
2829 getCollectionPageRoute ,
@@ -31,6 +32,7 @@ import {
3132import { RouteService } from '@dspace/core/services/route.service' ;
3233import { DSpaceObject } from '@dspace/core/shared/dspace-object.model' ;
3334import { Item } from '@dspace/core/shared/item.model' ;
35+ import { PageInfo } from '@dspace/core/shared/page-info.model' ;
3436import { FilterType } from '@dspace/core/shared/search/models/filter-type.model' ;
3537import { PaginatedSearchOptions } from '@dspace/core/shared/search/models/paginated-search-options.model' ;
3638import { SearchFilterConfig } from '@dspace/core/shared/search/models/search-filter-config.model' ;
@@ -39,6 +41,7 @@ import {
3941 SearchConfig ,
4042 SortConfig ,
4143} from '@dspace/core/shared/search/search-filters/search-config.model' ;
44+ import { PaginationServiceStub } from '@dspace/core/testing/pagination-service.stub' ;
4245import { SidebarServiceStub } from '@dspace/core/testing/sidebar-service.stub' ;
4346import {
4447 createSuccessfulRemoteDataObject ,
@@ -253,6 +256,7 @@ export function configureSearchComponentTestingModule(compType, additionalDeclar
253256 { provide : APP_DATA_SERVICES_MAP , useValue : { } } ,
254257 { provide : APP_CONFIG , useValue : environment } ,
255258 { provide : PLATFORM_ID , useValue : 'browser' } ,
259+ { provide : PaginationService , useClass : PaginationServiceStub } ,
256260 ] ,
257261 schemas : [ NO_ERRORS_SCHEMA ] ,
258262 } ) . overrideComponent ( compType , {
@@ -452,4 +456,71 @@ describe('SearchComponent', () => {
452456 } ) ) ;
453457 } ) ;
454458 } ) ;
459+
460+ describe ( 'Fallback pagination logic' , ( ) => {
461+ let paginationServiceStub : PaginationServiceStub ;
462+
463+ beforeEach ( ( ) => {
464+ paginationServiceStub = TestBed . inject ( PaginationService ) as any ;
465+ } ) ;
466+
467+ afterEach ( ( ) => {
468+ searchManagerStub . search . and . returnValue ( mockResultsRD$ ) ;
469+ paginationServiceStub . updateRoute . calls . reset ( ) ;
470+ } ) ;
471+
472+ it ( 'should navigate to last available page when requested page exceeds total pages' , fakeAsync ( ( ) => {
473+ // Mock search to return empty results with totalPages = 3
474+ const emptySearchResults : SearchObjects < DSpaceObject > = Object . assign ( new SearchObjects ( ) , {
475+ page : [ ] ,
476+ pageInfo : Object . assign ( new PageInfo ( ) , { totalPages : 3 , totalElements : 25 , elementsPerPage : 10 , currentPage : 5 } ) ,
477+ } ) ;
478+ const emptyResultsRD = createSuccessfulRemoteDataObject ( emptySearchResults ) ;
479+ searchManagerStub . search . and . returnValue ( of ( emptyResultsRD ) ) ;
480+
481+ fixture . detectChanges ( ) ;
482+ tick ( 100 ) ;
483+
484+ // Reset updateRoute spy to only track calls after the page change
485+ paginationServiceStub . updateRoute . calls . reset ( ) ;
486+
487+ // Emit new search options with currentPage = 5 (exceeding totalPages = 3)
488+ const paginationOptions = Object . assign ( new PaginationComponentOptions ( ) , {
489+ id : paginationId ,
490+ currentPage : 5 ,
491+ pageSize : 10 ,
492+ } ) ;
493+ paginatedSearchOptions$ . next ( new PaginatedSearchOptions ( { pagination : paginationOptions } ) ) ;
494+ tick ( 100 ) ;
495+
496+ expect ( paginationServiceStub . updateRoute ) . toHaveBeenCalledWith ( paginationId , { page : 3 } ) ;
497+ } ) ) ;
498+
499+ it ( 'should NOT navigate when requested page is within total pages' , fakeAsync ( ( ) => {
500+ // Mock search to return results on page 2
501+ const searchResultsPage2 : SearchObjects < DSpaceObject > = Object . assign ( new SearchObjects ( ) , {
502+ page : [ mockDso ] ,
503+ pageInfo : Object . assign ( new PageInfo ( ) , { totalPages : 3 , totalElements : 25 , elementsPerPage : 10 , currentPage : 2 } ) ,
504+ } ) ;
505+ const resultsRD = createSuccessfulRemoteDataObject ( searchResultsPage2 ) ;
506+ searchManagerStub . search . and . returnValue ( of ( resultsRD ) ) ;
507+
508+ fixture . detectChanges ( ) ;
509+ tick ( 100 ) ;
510+
511+ // Reset updateRoute spy
512+ paginationServiceStub . updateRoute . calls . reset ( ) ;
513+
514+ // Emit new search options with currentPage = 2 (within totalPages = 3)
515+ const paginationOptions = Object . assign ( new PaginationComponentOptions ( ) , {
516+ id : paginationId ,
517+ currentPage : 2 ,
518+ pageSize : 10 ,
519+ } ) ;
520+ paginatedSearchOptions$ . next ( new PaginatedSearchOptions ( { pagination : paginationOptions } ) ) ;
521+ tick ( 100 ) ;
522+
523+ expect ( paginationServiceStub . updateRoute ) . not . toHaveBeenCalled ( ) ;
524+ } ) ) ;
525+ } ) ;
455526} ) ;
0 commit comments