Skip to content

Instantly share code, notes, and snippets.

@willmanduffy
Created May 24, 2019 16:06
Show Gist options
  • Select an option

  • Save willmanduffy/3979b307c7863ccbeec275b3fcdc1112 to your computer and use it in GitHub Desktop.

Select an option

Save willmanduffy/3979b307c7863ccbeec275b3fcdc1112 to your computer and use it in GitHub Desktop.
import { withEvents } from 'react-compose-events';
import { compose, withHandlers, withState } from 'recompose';
import { debounce } from './utils';
const LOAD_DISTANCE_FROM_PAGE_BOTTOM = 500;
const LOAD_MORE_DEBOUNCE_TIME = 100;
const withInfiniteScrolling = (loadMoreFunctionName, startsInfiniteEnabled = false) => compose(
withState('infiniteEnabled', 'setInfiniteEnabled', startsInfiniteEnabled),
withHandlers({
enableInfinite: ({ setInfiniteEnabled }) => event => setInfiniteEnabled(true)
}),
withEvents(window, ({ infiniteEnabled, [loadMoreFunctionName]: loadMoreFunction }) => ({
scroll: debounce(() => {
loadMoreAtPageBottom({ infiniteEnabled, loadMoreFunction });
}, LOAD_MORE_DEBOUNCE_TIME)
})
));
export const loadMoreAtPageBottom = ({ infiniteEnabled, loadMoreFunction }) => {
if(infiniteEnabled && nearBottomOfPage()) {
return loadMoreFunction();
};
};
const nearBottomOfPage = () => {
return (window.innerHeight + window.pageYOffset) >= document.body.scrollHeight - LOAD_DISTANCE_FROM_PAGE_BOTTOM;
}
export default withInfiniteScrolling;
import { mount } from 'enzyme';
import React from 'react';
import { compose, toClass, withProps } from 'recompose';
import simulant from 'simulant';
import withInfiniteScrolling, {
loadMoreAtPageBottom
} from './with-infinite-scrolling';
describe('a wrapped component', () => {
jest.useFakeTimers();
const WrappedComponent = () => (
<div>That's a wrap!</div>
);
const WrappedComponentClass = toClass(WrappedComponent);
const EnhancedComponent = compose(
withProps({ testFunction: jest.fn() }),
withInfiniteScrolling('testFunction')
)(WrappedComponentClass);
const wrapper = mount(
<EnhancedComponent />
);
it('has infinite scrolling disabled by default', () => {
const subject = wrapper.find(WrappedComponentClass).props();
expect(subject.infiniteEnabled).toEqual(false);
})
it('calling enableInfinite will enable infinite scrolling', () => {
const subject = wrapper.find(WrappedComponentClass).props();
subject.enableInfinite();
wrapper.update();
expect(wrapper.find(WrappedComponentClass).props().infiniteEnabled).toEqual(true);
});
it('does not call the loadMoreFunction on a scroll event near the page bottom when infinite is disabled', () => {
simulant.fire(window, 'scroll');
jest.runAllTimers();
expect(wrapper.find(WrappedComponentClass).props().testFunction).toHaveBeenCalled();
});
it('calls the loadMoreFunction on a scroll event near the page bottom when infinite is enabled', () => {
wrapper.find(WrappedComponentClass).props().enableInfinite();
wrapper.update();
simulant.fire(window, 'scroll');
jest.runAllTimers();
expect(wrapper.find(WrappedComponentClass).props().testFunction).toHaveBeenCalled();
});
});
describe('loadMoreAtPageBottom', () => {
const loadMoreFunction = jest.fn();
describe('when infinite scrolling is enabled', () => {
beforeEach(() => loadMoreFunction.mockClear());
describe('when near the bottom of the page', () => {
beforeEach(() => {
Object.defineProperty(document.body, 'scrollHeight', { value: 1500, writable: true });
global.pageYOffset = 250;
});
afterEach(() => global.pageYOffset = 0);
it('calls the load more function', () => {
loadMoreAtPageBottom({ infiniteEnabled: true, loadMoreFunction });
expect(loadMoreFunction).toHaveBeenCalled();
});
});
describe('when near the top of the page', () => {
beforeEach(() => {
Object.defineProperty(document.body, 'scrollHeight', { value: 2000, writable: true });
});
it('does not call the load more function', () => {
loadMoreAtPageBottom({ infiniteEnabled: true, loadMoreFunction });
expect(loadMoreFunction).not.toHaveBeenCalled();
});
});
});
describe('when infinite scrolling is not enabled', () => {
describe('when near the bottom of the page', () => {
it('does not call the load more function', () => {
loadMoreAtPageBottom({ infiniteEnabled: false, loadMoreFunction });
expect(loadMoreFunction).not.toHaveBeenCalled();
});
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment