@@ -21,28 +21,44 @@ const setupDOM = (cardCount: number = 10) => {
2121 <button id="next-button">Next</button>
2222 </div>
2323 <div id="cardContainer">
24- ${ Array . from ( { length : cardCount } , ( _ , i ) =>
24+ ${ Array . from ( { length : cardCount } , ( _ , i ) =>
2525 `<div class="card" data-title="Card ${ i + 1 } ">Card ${ i + 1 } </div>`
2626 ) . join ( '' ) }
2727 </div>
2828 </body>
2929 </html>
30- ` )
30+ ` , {
31+ url : "http://localhost" , // Provide a URL to avoid localStorage issues
32+ } )
3133
3234 global . document = dom . window . document
3335 global . window = dom . window as any
3436 global . Event = dom . window . Event
35- }
36-
37- // Simple PaginationManager class for testing (extracted from paginate.ts)
37+ global . CustomEvent = dom . window . CustomEvent
38+
39+ // Mock localStorage
40+ const localStorageMock = {
41+ getItem : vi . fn ( ) ,
42+ setItem : vi . fn ( ) ,
43+ removeItem : vi . fn ( ) ,
44+ clear : vi . fn ( ) ,
45+ length : 0 ,
46+ key : vi . fn ( )
47+ }
48+ Object . defineProperty ( dom . window , 'localStorage' , {
49+ value : localStorageMock ,
50+ writable : true
51+ } )
52+ global . localStorage = localStorageMock
53+ } // Simple PaginationManager class for testing (extracted from paginate.ts)
3854class PaginationManager {
39- private cards : HTMLElement [ ]
55+ private allCards : HTMLElement [ ]
4056 private currentPage : number = 1
4157 private itemsPerPage : number = 6
4258 private totalPages : number = 1
4359
4460 constructor ( ) {
45- this . cards = Array . from ( document . querySelectorAll ( ".card" ) )
61+ this . allCards = Array . from ( document . querySelectorAll ( ".card" ) )
4662 this . init ( )
4763 }
4864
@@ -58,6 +74,11 @@ class PaginationManager {
5874 const prevButton = document . getElementById ( "prev-button" )
5975 const nextButton = document . getElementById ( "next-button" )
6076
77+ // Listen for filter changes
78+ window . addEventListener ( 'cardsFiltered' , ( ) => {
79+ setTimeout ( ( ) => this . refreshPagination ( ) , 10 )
80+ } )
81+
6182 paginateSelect ?. addEventListener ( "change" , ( e ) => {
6283 const target = e . target as HTMLSelectElement
6384 this . itemsPerPage = parseInt ( target . value )
@@ -84,19 +105,33 @@ class PaginationManager {
84105 } )
85106 }
86107
108+ private refreshPagination ( ) {
109+ this . currentPage = 1
110+ this . calculateTotalPages ( )
111+ this . showCurrentPage ( )
112+ this . updateButtonStates ( )
113+ }
114+
87115 private calculateTotalPages ( ) {
88- this . totalPages = Math . ceil ( this . cards . length / this . itemsPerPage )
116+ const filteredCards = this . getFilteredCards ( )
117+ this . totalPages = Math . ceil ( filteredCards . length / this . itemsPerPage )
118+ if ( this . totalPages === 0 ) this . totalPages = 1
89119 }
90120
91121 private showCurrentPage ( ) {
122+ const filteredCards = this . getFilteredCards ( )
92123 const startIndex = ( this . currentPage - 1 ) * this . itemsPerPage
93124 const endIndex = startIndex + this . itemsPerPage
94125
95- this . cards . forEach ( ( card ) => {
96- card . style . display = "none"
126+ this . allCards . forEach ( ( card ) => {
127+ if ( card . getAttribute ( 'data-hidden-by-filter' ) === 'true' ) {
128+ card . style . display = "none"
129+ } else {
130+ card . style . display = "none"
131+ }
97132 } )
98133
99- this . cards . slice ( startIndex , endIndex ) . forEach ( ( card ) => {
134+ filteredCards . slice ( startIndex , endIndex ) . forEach ( ( card ) => {
100135 card . style . display = "block"
101136 } )
102137 }
@@ -130,7 +165,13 @@ class PaginationManager {
130165 }
131166
132167 public getVisibleCards ( ) : HTMLElement [ ] {
133- return this . cards . filter ( card => card . style . display !== "none" )
168+ return this . allCards . filter ( card => card . style . display !== "none" )
169+ }
170+
171+ public getFilteredCards ( ) : HTMLElement [ ] {
172+ return this . allCards . filter ( card => {
173+ return card . getAttribute ( 'data-hidden-by-filter' ) !== 'true'
174+ } )
134175 }
135176}
136177
@@ -268,4 +309,46 @@ describe("PaginationManager", () => {
268309 nextButton . click ( )
269310 expect ( paginationManager . getCurrentPage ( ) ) . toBe ( 1 )
270311 } )
312+
313+ test ( "works with filtered cards" , ( ) => {
314+ setupDOM ( 10 )
315+ paginationManager = new PaginationManager ( )
316+
317+ // Simulate filtering by marking some cards as hidden by filter
318+ const cards = Array . from ( document . querySelectorAll ( '.card' ) )
319+ if ( cards . length >= 3 ) {
320+ cards [ 0 ] ! . setAttribute ( 'data-hidden-by-filter' , 'true' )
321+ cards [ 1 ] ! . setAttribute ( 'data-hidden-by-filter' , 'true' )
322+ cards [ 2 ] ! . setAttribute ( 'data-hidden-by-filter' , 'true' )
323+ }
324+
325+ // Trigger pagination refresh with custom event
326+ window . dispatchEvent ( new CustomEvent ( 'cardsFiltered' ) )
327+
328+ // Should now work with 7 visible cards instead of 10
329+ expect ( paginationManager . getTotalPages ( ) ) . toBe ( 2 ) // 7 cards / 6 per page = 2 pages
330+
331+ // First page should show 6 cards
332+ const visibleCards = paginationManager . getVisibleCards ( )
333+ expect ( visibleCards ) . toHaveLength ( 6 )
334+ } )
335+
336+ test ( "resets to page 1 when filters change" , async ( ) => {
337+ setupDOM ( 15 )
338+ paginationManager = new PaginationManager ( )
339+
340+ // Go to page 2
341+ const nextButton = document . getElementById ( "next-button" ) as HTMLButtonElement
342+ nextButton . click ( )
343+ expect ( paginationManager . getCurrentPage ( ) ) . toBe ( 2 )
344+
345+ // Simulate filter change
346+ window . dispatchEvent ( new CustomEvent ( 'cardsFiltered' ) )
347+
348+ // Wait for the setTimeout in the event handler
349+ await new Promise ( resolve => setTimeout ( resolve , 20 ) )
350+
351+ // Should reset to page 1
352+ expect ( paginationManager . getCurrentPage ( ) ) . toBe ( 1 )
353+ } )
271354} )
0 commit comments