1- import { DebugElement } from '@angular/core' ;
1+ import {
2+ Component ,
3+ DebugElement ,
4+ Input ,
5+ } from '@angular/core' ;
26import {
37 ComponentFixture ,
48 TestBed ,
59 waitForAsync ,
610} from '@angular/core/testing' ;
711import { By } from '@angular/platform-browser' ;
812import { TranslateModule } from '@ngx-translate/core' ;
13+ import { BehaviorSubject } from 'rxjs' ;
914
1015import { DSONameService } from '../../core/breadcrumbs/dso-name.service' ;
1116import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service' ;
17+ import { PaginationService } from '../../core/pagination/pagination.service' ;
1218import { UsageReport } from '../../core/statistics/models/usage-report.model' ;
19+ import { PaginationComponent } from '../../shared/pagination/pagination.component' ;
20+ import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model' ;
1321import { StatisticsTableComponent } from './statistics-table.component' ;
1422
23+ /**
24+ * Lightweight stand-in for ds-pagination so the table can be tested in isolation; the current page is
25+ * driven through the (mocked) PaginationService, exactly as the real component does via the URL.
26+ */
27+ @Component ( {
28+ selector : 'ds-pagination' ,
29+ standalone : true ,
30+ template : '<ng-content></ng-content>' ,
31+ } )
32+ class MockPaginationComponent {
33+ @Input ( ) paginationOptions : PaginationComponentOptions ;
34+ @Input ( ) collectionSize : number ;
35+ @Input ( ) hideGear : boolean ;
36+ @Input ( ) hidePaginationDetail : boolean ;
37+ @Input ( ) hideSortOptions : boolean ;
38+ @Input ( ) retainScrollPosition : boolean ;
39+ }
40+
1541describe ( 'StatisticsTableComponent' , ( ) => {
1642
1743 let component : StatisticsTableComponent ;
1844 let de : DebugElement ;
1945 let fixture : ComponentFixture < StatisticsTableComponent > ;
46+ let currentPagination$ : BehaviorSubject < PaginationComponentOptions > ;
47+
48+ const paginationService = {
49+ getCurrentPagination : ( _id : string , _options : PaginationComponentOptions ) => currentPagination$ . asObservable ( ) ,
50+ } ;
51+
52+ const setPage = ( currentPage : number , pageSize = 10 ) => {
53+ currentPagination$ . next ( Object . assign ( new PaginationComponentOptions ( ) , { currentPage, pageSize } ) ) ;
54+ } ;
2055
2156 beforeEach ( waitForAsync ( ( ) => {
57+ currentPagination$ = new BehaviorSubject ( Object . assign ( new PaginationComponentOptions ( ) , { currentPage : 1 , pageSize : 10 } ) ) ;
58+
2259 TestBed . configureTestingModule ( {
2360 imports : [
2461 TranslateModule . forRoot ( ) ,
@@ -27,8 +64,13 @@ describe('StatisticsTableComponent', () => {
2764 providers : [
2865 { provide : DSpaceObjectDataService , useValue : { } } ,
2966 { provide : DSONameService , useValue : { } } ,
67+ { provide : PaginationService , useValue : paginationService } ,
3068 ] ,
3169 } )
70+ . overrideComponent ( StatisticsTableComponent , {
71+ remove : { imports : [ PaginationComponent ] } ,
72+ add : { imports : [ MockPaginationComponent ] } ,
73+ } )
3274 . compileComponents ( ) ;
3375 } ) ) ;
3476
@@ -51,6 +93,10 @@ describe('StatisticsTableComponent', () => {
5193 it ( 'should not display a table' , ( ) => {
5294 expect ( de . query ( By . css ( 'table' ) ) ) . toBeNull ( ) ;
5395 } ) ;
96+
97+ it ( 'should not display a pagination control' , ( ) => {
98+ expect ( de . query ( By . directive ( MockPaginationComponent ) ) ) . toBeNull ( ) ;
99+ } ) ;
54100 } ) ;
55101
56102 describe ( 'when the storage report has data' , ( ) => {
@@ -96,5 +142,83 @@ describe('StatisticsTableComponent', () => {
96142 expect ( de . query ( By . css ( 'td.item_2-downloads-data' ) ) . nativeElement . innerText )
97143 . toEqual ( '8' ) ;
98144 } ) ;
145+
146+ it ( 'should wrap the table in a ds-pagination control with the report size' , ( ) => {
147+ const pagination = de . query ( By . directive ( MockPaginationComponent ) ) ;
148+ expect ( pagination ) . toBeTruthy ( ) ;
149+ expect ( pagination . componentInstance . collectionSize ) . toEqual ( 2 ) ;
150+ } ) ;
151+
152+ it ( 'should hide the page-size selector when everything fits on a single page' , ( ) => {
153+ expect ( de . query ( By . directive ( MockPaginationComponent ) ) . componentInstance . hideGear ) . toBeTrue ( ) ;
154+ } ) ;
155+ } ) ;
156+
157+ describe ( 'when the report has more points than the page size' , ( ) => {
158+
159+ const numberOfPoints = 25 ;
160+
161+ beforeEach ( ( ) => {
162+ const points = [ ] ;
163+ for ( let i = 0 ; i < numberOfPoints ; i ++ ) {
164+ points . push ( {
165+ id : `item_${ i } ` ,
166+ label : `item_${ i } ` ,
167+ values : {
168+ views : i ,
169+ } ,
170+ } ) ;
171+ }
172+ component . report = Object . assign ( new UsageReport ( ) , { points } ) ;
173+ component . ngOnInit ( ) ;
174+ fixture . detectChanges ( ) ;
175+ } ) ;
176+
177+ it ( 'should pass the full report size to the pagination control' , ( ) => {
178+ expect ( de . query ( By . directive ( MockPaginationComponent ) ) . componentInstance . collectionSize )
179+ . toEqual ( numberOfPoints ) ;
180+ } ) ;
181+
182+ it ( 'should offer the page-size selector with its options when there is more than one page' , ( ) => {
183+ const pagination = de . query ( By . directive ( MockPaginationComponent ) ) . componentInstance ;
184+ expect ( pagination . hideGear ) . toBeFalse ( ) ;
185+ expect ( pagination . paginationOptions . pageSizeOptions ) . toEqual ( [ 10 , 20 , 40 , 60 , 80 , 100 ] ) ;
186+ } ) ;
187+
188+ it ( 'should render more rows when a larger page size is selected' , ( ) => {
189+ setPage ( 1 , 20 ) ;
190+ fixture . detectChanges ( ) ;
191+
192+ expect ( de . queryAll ( By . css ( '[data-test="statistics-label"]' ) ) . length ) . toEqual ( 20 ) ;
193+ expect ( de . query ( By . css ( 'td.item_19-views-data' ) ) ) . toBeTruthy ( ) ;
194+ } ) ;
195+
196+ it ( 'should only render the first page of points' , ( ) => {
197+ expect ( de . queryAll ( By . css ( '[data-test="statistics-label"]' ) ) . length )
198+ . toEqual ( component . pageSize ) ;
199+ expect ( de . query ( By . css ( 'td.item_0-views-data' ) ) ) . toBeTruthy ( ) ;
200+ expect ( de . query ( By . css ( 'td.item_10-views-data' ) ) ) . toBeNull ( ) ;
201+ } ) ;
202+
203+ it ( 'should render the next page of points when the current page changes' , ( ) => {
204+ setPage ( 2 ) ;
205+ fixture . detectChanges ( ) ;
206+
207+ expect ( de . query ( By . css ( 'td.item_0-views-data' ) ) ) . toBeNull ( ) ;
208+ expect ( de . query ( By . css ( 'td.item_10-views-data' ) ) ) . toBeTruthy ( ) ;
209+ expect ( de . queryAll ( By . css ( '[data-test="statistics-label"]' ) ) . length )
210+ . toEqual ( component . pageSize ) ;
211+ } ) ;
212+
213+ it ( 'should render the remaining points on the last page' , ( ) => {
214+ const lastPage = Math . ceil ( numberOfPoints / component . pageSize ) ;
215+ setPage ( lastPage ) ;
216+ fixture . detectChanges ( ) ;
217+
218+ const remaining = numberOfPoints - ( lastPage - 1 ) * component . pageSize ;
219+ expect ( de . queryAll ( By . css ( '[data-test="statistics-label"]' ) ) . length )
220+ . toEqual ( remaining ) ;
221+ expect ( de . query ( By . css ( `td.item_${ numberOfPoints - 1 } -views-data` ) ) ) . toBeTruthy ( ) ;
222+ } ) ;
99223 } ) ;
100224} ) ;
0 commit comments