diff --git a/CHANGELOG.md b/CHANGELOG.md index e063b18fd..8669fcbc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ * Accessibility | Repeatable Field Component. Refs STCOM-766. * Apply highest z-index to focused `` within `AccordionSet`. Refs STCOM-1257. * Upgrade storybook to v7. Refs STCOM-1176. +* Fix bug with MCL not re-enabling paging buttons after more data was loaded. Refs STCOM-1262. ## [12.0.0](https://github.com/folio-org/stripes-components/tree/v12.0.0) (2023-10-11) [Full Changelog](https://github.com/folio-org/stripes-components/compare/v11.0.0...v12.0.0) diff --git a/lib/MultiColumnList/MCLRenderer.js b/lib/MultiColumnList/MCLRenderer.js index 7f0424a30..a32b97d4f 100644 --- a/lib/MultiColumnList/MCLRenderer.js +++ b/lib/MultiColumnList/MCLRenderer.js @@ -433,10 +433,12 @@ class MCLRenderer extends React.Component { const checkValue = parseInt(Object.keys(contentData).length, 10); - if (newState.isSparse && receivedRows !== checkValue) { + if (receivedRows !== checkValue) { newState.receivedRows = checkValue; newState.loading = false; + } + if (newState.isSparse && receivedRows !== checkValue) { // for paging via slice-at-a-time sparse arrays (and prev/next pagination); if (!virtualize) { const contentDataIndices = Object.keys(contentData); diff --git a/lib/MultiColumnList/stories/service.js b/lib/MultiColumnList/stories/service.js index eabf7d8ad..ca23e5ff7 100644 --- a/lib/MultiColumnList/stories/service.js +++ b/lib/MultiColumnList/stories/service.js @@ -14,6 +14,8 @@ export function syncGenerate(n, start = 0, generator) { date: faker.date.past().toString(), email: faker.internet.email(), status: faker.random.boolean(), + phone: faker.phone.phoneNumber(), + name: faker.name.findName(), }); } i++; diff --git a/lib/MultiColumnList/tests/MCLHarness.js b/lib/MultiColumnList/tests/MCLHarness.js index ecc301d66..dfffb5b05 100644 --- a/lib/MultiColumnList/tests/MCLHarness.js +++ b/lib/MultiColumnList/tests/MCLHarness.js @@ -4,6 +4,7 @@ import cloneDeep from 'lodash/cloneDeep'; import MultiColumnList from '../MultiColumnList'; import Button from '../../Button'; import { generate } from './generate'; +import { asyncGenerate, syncGenerate } from '../stories/service'; class MCLHarness extends React.Component { @@ -15,7 +16,7 @@ class MCLHarness extends React.Component { super(props); this.state = { - data: props.initialData || generate(30), + data: props.initialData || syncGenerate(30), height: 400, selected: {}, displayGrid: props.displayGrid, @@ -36,9 +37,18 @@ class MCLHarness extends React.Component { this.onNeedMore(); } - onNeedMore() { + async onNeedMore() { + const { onNeedMoreSpy, asyncPaging } = this.props; + if (onNeedMoreSpy) onNeedMoreSpy(); + let newData; + if (asyncPaging) { + newData = await asyncGenerate(30, null, 500); + } else { + newData = await Promise.resolve(syncGenerate(30)); + } + this.setState(curState => ({ - data: [...curState.data, ...generate(30)] + data: [...curState.data, ...newData] })); } @@ -102,7 +112,7 @@ class MCLHarness extends React.Component { render() { const { displayGrid, placeMarker } = this.state; - const { initialData, ...rest } = this.props; // eslint-disable-line no-unused-vars + const { initialData, onNeedMoreSpy, asyncPaging, ...rest } = this.props; // eslint-disable-line no-unused-vars return (
diff --git a/lib/MultiColumnList/tests/MultiColumnList-test.js b/lib/MultiColumnList/tests/MultiColumnList-test.js index 1d27fdbae..e6954a898 100644 --- a/lib/MultiColumnList/tests/MultiColumnList-test.js +++ b/lib/MultiColumnList/tests/MultiColumnList-test.js @@ -454,7 +454,7 @@ describe('MultiColumnList', () => { describe('adjusting to width change', () => { beforeEach(async () => { - await mcl.scrollBy({ direction: 'top', value: 500 }); + await mcl.scrollBy({ direction: 'top', value: 600 }); }); describe('selecting another', () => { @@ -688,17 +688,18 @@ describe('MultiColumnList', () => { describe('using the pagingType prop', () => { const loadMore = ButtonInteractor('Load more'); + let pagingNeedMore; beforeEach(async () => { pagingNeedMore = sinon.fake(); await mountWithContext( - + ); }); it('click paging type has no axe errors', runAxeTest); - it('renders the paging button', () => loadMore.is({ visible: true })); + it('renders the paging button', () => loadMore.exists()); describe('clicking the paging button', () => { beforeEach(async () => { @@ -708,10 +709,21 @@ describe('MultiColumnList', () => { it('calls the onNeedMoreData handler', () => { expect(pagingNeedMore.calledOnce).to.be.true; }); + + it('disables the Load more button', () => loadMore.is({ disabled: true })); + + describe('after loading data...', () => { + beforeEach(async () => { + await mcl.has({ rowCount: 28 }); + await mcl.scrollBy({ direction: 'top', value: 815 }); + }); + + it('re-enables Load more button when loading is finished', () => loadMore.is({ disabled: false })); + }) }); }); - describe.skip('prev-next paging', () => { + describe('prev-next paging', () => { let needMoreHandler; beforeEach(async () => { needMoreHandler = sinon.fake(); @@ -771,7 +783,7 @@ describe('MultiColumnList', () => { it('disables the Previous button', () => ButtonInteractor('Previous').is({ disabled: true })); }); - describe.skip('pagingOffset prop', () => { + describe('pagingOffset prop', () => { let needMoreHandler; let handleScroll; beforeEach(async () => { @@ -788,37 +800,37 @@ describe('MultiColumnList', () => { it('displays the proper ending index within pagination', () => HTMLInteractor('100').exists()); it('scrolls down 500 px', () => mcl.has({ scrollTop: 500 })); - describe('clicking the next pagination button', () => { - beforeEach( async () => { - await mcl.clickNextPagingButton(); - }); - - it('displays advanced starting index within pagination', async () => await HTMLInteractor('101').exists()); - it('displays the proper advanced ending index within pagination', async () => await HTMLInteractor('200').exists()); - it('scrolls back to top when new data received', async () => await mcl.has({ scrollTop: 0 })); + describe('clicking the next pagination button', () => { + beforeEach(async () => { + await mcl.clickNextPagingButton(); + }); - describe('Reaching the totalCount disables the next button...', () => { - beforeEach( async () => { - await mcl.clickNextPagingButton(); - }); + it('displays advanced starting index within pagination', () => HTMLInteractor('101').exists()); + it('displays the proper advanced ending index within pagination', () => HTMLInteractor('200').exists()); + it('scrolls back to top when new data received', () => mcl.has({ scrollTop: 0 })); - it('displays advanced starting index within pagination', async () => await HTMLInteractor('201').exists()); - it('displays the proper advanced ending index within pagination', async () => await HTMLInteractor('250').exists()); - it('disables the next button', async () => await mcl.find(ButtonInteractor('Next')).is({ disabled: true })); + describe('Reaching the totalCount disables the next button...', () => { + beforeEach(async () => { + await mcl.clickNextPagingButton(); }); - describe('clicking the previous pagination button', () => { - beforeEach( async () => { - await mcl.scrollBy({ direction: 'top', value: 500 }); - await mcl.clickPreviousPagingButton(); - }); + it('displays advanced starting index within pagination', () => HTMLInteractor('201').exists()); + it('displays the proper advanced ending index within pagination', () => HTMLInteractor('250').exists()); + it('disables the next button', () => mcl.find(ButtonInteractor('Next')).is({ disabled: true })); + }); - it('displays advanced starting index within pagination', () => HTMLInteractor('1')); - it('displays the proper advanced ending index within pagination', () => HTMLInteractor('100')); - it('scrolls back to top when new data received', () => mcl.has({ scrollTop: 0 })); + describe('clicking the previous pagination button', () => { + beforeEach(async () => { + await mcl.scrollBy({ direction: 'top', value: 500 }); + await mcl.clickPreviousPagingButton(); }); + + it('displays advanced starting index within pagination', () => HTMLInteractor('1')); + it('displays the proper advanced ending index within pagination', () => HTMLInteractor('100')); + it('scrolls back to top when new data received', () => mcl.has({ scrollTop: 0 })); }); }); + }); describe('mark position functionality', () => { let markPositionInspector; @@ -918,6 +930,7 @@ describe('MultiColumnList', () => { describe('adding data roles to overflow the grid', () => { beforeEach(async () => { await Button('loadData').click(); + await mcl.has({ rowCount: 33 }) }); it('detects vertical scrollbar', () => {