-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Revise selection of pagination items
Revise the calculation of the set of page numbers so that the number of pagination items (page numbers and elided-page markers) is consistent regardless of the current page. If each item is rendered at a consistent width, this keeps the controls in the same place as the user navigates through the page list, avoiding mis-clicks due to pages jumping around.
- Loading branch information
1 parent
5c82a76
commit 6829c62
Showing
4 changed files
with
239 additions
and
71 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,115 @@ | ||
import { pageNumberOptions } from '../pagination'; | ||
|
||
describe('sidebar/util/pagination', () => { | ||
describe('pageNumberOptions', () => { | ||
[ | ||
{ args: [1, 10, 5], expected: [1, 2, 3, 4, null, 10] }, | ||
{ args: [3, 10, 5], expected: [1, 2, 3, 4, null, 10] }, | ||
{ args: [6, 10, 5], expected: [1, null, 5, 6, 7, null, 10] }, | ||
{ args: [9, 10, 5], expected: [1, null, 7, 8, 9, 10] }, | ||
{ args: [2, 3, 5], expected: [1, 2, 3] }, | ||
{ args: [3, 10, 7], expected: [1, 2, 3, 4, 5, 6, null, 10] }, | ||
{ args: [1, 1, 5], expected: [] }, | ||
].forEach(testCase => { | ||
it('should produce expected available page numbers', () => { | ||
assert.deepEqual( | ||
pageNumberOptions(...testCase.args), | ||
testCase.expected, | ||
); | ||
import { paginationItems } from '../pagination'; | ||
|
||
describe('paginationItems', () => { | ||
[ | ||
// Only one page | ||
{ | ||
current: 1, | ||
total: 1, | ||
expected: [], | ||
}, | ||
|
||
// No pages elided. | ||
{ | ||
current: 1, | ||
total: 3, | ||
expected: [1, 2, 3], | ||
}, | ||
|
||
// Pages elided after current. | ||
{ | ||
current: 1, | ||
total: 4, | ||
expected: [1, 2, null, 4], | ||
}, | ||
|
||
// Pages elided before current. | ||
{ | ||
current: 4, | ||
total: 6, | ||
expected: [1, null, 3, 4, 5, 6], | ||
}, | ||
|
||
// Pages elided before and after current. | ||
{ | ||
current: 4, | ||
total: 7, | ||
expected: [1, null, 3, 4, 5, null, 7], | ||
}, | ||
|
||
// Custom boundary count | ||
{ | ||
current: 6, | ||
total: 10, | ||
boundaryCount: 2, | ||
expected: [1, 2, null, 5, 6, 7, null, 9, 10], | ||
}, | ||
|
||
// Custom sibling count | ||
{ | ||
current: 6, | ||
total: 10, | ||
siblingCount: 2, | ||
expected: [1, null, 4, 5, 6, 7, 8, null, 10], | ||
}, | ||
].forEach(({ current, total, boundaryCount, siblingCount, expected }) => { | ||
it('should produce expected items', () => { | ||
const items = paginationItems(current, total, { | ||
boundaryCount, | ||
siblingCount, | ||
}); | ||
assert.deepEqual(items, expected); | ||
}); | ||
}); | ||
|
||
function* configurations() { | ||
for (let boundaryCount = 1; boundaryCount <= 3; boundaryCount++) { | ||
for (let siblingCount = 0; siblingCount <= 2; siblingCount++) { | ||
for (let total = 1; total <= 10; total++) { | ||
yield { total, boundaryCount, siblingCount }; | ||
} | ||
} | ||
} | ||
} | ||
|
||
function isSorted(list) { | ||
return list.every((item, idx) => idx === 0 || item >= list[idx - 1]); | ||
} | ||
|
||
it('should produce expected items for generated configurations', () => { | ||
for (const { total, boundaryCount, siblingCount } of configurations()) { | ||
let expectedItems = null; | ||
for (let current = 1; current <= total; current++) { | ||
const items = paginationItems(current, total, { | ||
boundaryCount, | ||
siblingCount, | ||
}); | ||
|
||
if (total === 1) { | ||
assert.deepEqual(items, []); | ||
continue; | ||
} | ||
|
||
// Total number of items should always be the same for a given total | ||
// page count and configuration. | ||
if (expectedItems === null) { | ||
expectedItems = items.length; | ||
} else { | ||
assert.equal(items.length, expectedItems); | ||
} | ||
|
||
// Check that first, current and last pages are present. | ||
assert.include(items, 1); | ||
assert.include(items, current); | ||
assert.include(items, total); | ||
|
||
// There should be at most two elided page indicators | ||
assert.isAtMost(items.filter(it => it === null).length, 2); | ||
|
||
// Page numbers should always be in sorted order. | ||
const numbers = items.filter(it => typeof it === 'number'); | ||
assert.isTrue(isSorted(numbers), `${numbers.join(', ')} is not sorted`); | ||
} | ||
} | ||
}); | ||
}); |