UNPKG

react-lazily-render

Version:
322 lines (296 loc) 12.2 kB
"use strict"; var _react = _interopRequireDefault(require("react")); var _enzyme = require("enzyme"); var _ = _interopRequireDefault(require(".")); var _getViewportBounds = require("./utils/getViewportBounds"); var _getElementBounds = require("./utils/getElementBounds"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } var mockScrollParent = window; jest.mock('scrollparent', function () { return function (element) { return mockScrollParent; }; }); jest.mock('./utils/eventListenerOptions', function () { return { passive: true }; }); jest.mock('./utils/getViewportBounds', function () { var bounds = undefined; var getViewportBounds = function getViewportBounds() { return bounds; }; getViewportBounds.__setViewportBounds = function (val) { return bounds = val; }; return getViewportBounds; }); jest.mock('./utils/getElementBounds', function () { var bounds = undefined; var getElementBounds = function getElementBounds() { return bounds; }; getElementBounds.__setElementBounds = function (val) { return bounds = val; }; return getElementBounds; }); function setupElementInView() { (0, _getViewportBounds.__setViewportBounds)({ top: 0, right: 1000, bottom: 1000, left: 0 }); (0, _getElementBounds.__setElementBounds)({ top: 100, right: 200, bottom: 200, left: 100 }); } function setupElementOutOfView() { (0, _getViewportBounds.__setViewportBounds)({ top: 0, right: 1000, bottom: 1000, left: 0 }); (0, _getElementBounds.__setElementBounds)({ top: 1100, right: 1200, bottom: 1200, left: 1100 }); } var compatMode; function mockCompatMode(mode) { compatMode = Object.getOwnPropertyDescriptor(Document.prototype, 'compatMode'); Object.defineProperty(document, 'compatMode', { value: mode, writable: false, configurable: true }); } function unmockCompatMode() { Object.defineProperty(document, 'compatMode', compatMode); } function wrapper(node) { jest.useFakeTimers(); var wrapper = (0, _enzyme.mount)(node); jest.runAllTimers(); wrapper.update(); return wrapper; } // return the div wrapper function getWrapper(element) { return element.children().first(); } describe('LazyRender', function () { var placeholder = '...'; var content = 'Hello World!'; var children = 'foo bar'; describe('.render()', function () { it('should render the class name on the wrapper', function () { var wrapper = (0, _enzyme.mount)(_react["default"].createElement(_["default"], { className: "my-cool-class" }, function () { return _react["default"].createElement("span", null, "HelloWorld!"); })); expect(wrapper.prop('className')).toEqual('my-cool-class'); }); describe("when component=\"span\"", function () { it("should render the wrapper as <span>", function () { var wrapper = (0, _enzyme.shallow)(_react["default"].createElement(_["default"], { component: "span" }, function () { return _react["default"].createElement("span", null, "HelloWorld!"); })); expect(wrapper.type()).toEqual('span'); }); }); describe("when component=\"div\"", function () { it("should render the wrapper as <div>", function () { var wrapper = (0, _enzyme.shallow)(_react["default"].createElement(_["default"], { component: "div" }, function () { return _react["default"].createElement("span", null, "HelloWorld!"); })); expect(wrapper.type()).toEqual('div'); }); }); it('should call the render fn with true when the component is visible in the viewport', function () { setupElementInView(); var render = jest.fn(); var element = wrapper(_react["default"].createElement(_["default"], null, render)); expect(render).toBeCalledWith(true); }); it('should call the render fn with false when the component is not visible in the viewport', function () { setupElementOutOfView(); var render = jest.fn(); var element = wrapper(_react["default"].createElement(_["default"], null, render)); expect(render).toBeCalledWith(false); }); describe('has not been scrolled into view:', function () { beforeEach(function () { return setupElementOutOfView(); }); it('should render the "placeholder" when there is a "placeholder"', function () { var element = wrapper(_react["default"].createElement(_["default"], { placeholder: placeholder, content: content }, function () { return children; })); expect(getWrapper(element).contains(placeholder)).toBeTruthy(); }); it('should render the "render fn" when there is no "placeholder"', function () { var element = wrapper(_react["default"].createElement(_["default"], { content: content }, function () { return children; })); expect(getWrapper(element).contains(children)).toBeTruthy(); }); it('should render "null" when there is no "placeholder" and no "render fn"', function () { var element = wrapper(_react["default"].createElement(_["default"], { content: content })); expect(getWrapper(element).children().exists()).toBeFalsy(); }); }); describe('has been scrolled into view:', function () { beforeEach(function () { return setupElementInView(); }); it('should render the "content" when there is "content"', function () { var element = wrapper(_react["default"].createElement(_["default"], { placeholder: placeholder, content: content }, function () { return children; })); expect(getWrapper(element).contains(content)).toBeTruthy(); }); it('should render the "render fn" when there is no "content"', function () { var element = wrapper(_react["default"].createElement(_["default"], { placeholder: placeholder }, function () { return children; })); expect(getWrapper(element).contains(children)).toBeTruthy(); }); it('should render "null" when there is no "content" and no "render fn"', function () { var element = wrapper(_react["default"].createElement(_["default"], { placeholder: placeholder })); expect(getWrapper(element).children().exists()).toBeFalsy(); }); }); }); describe('Event handling', function () { var windowAddEventSpy; var bodyAddEventSpy; var windowRemoveEventSpy; var bodyRemoveEventSpy; beforeEach(function () { windowAddEventSpy = jest.spyOn(window, 'addEventListener'); bodyAddEventSpy = jest.spyOn(document.body, 'addEventListener'); windowRemoveEventSpy = jest.spyOn(window, 'removeEventListener'); bodyRemoveEventSpy = jest.spyOn(document.body, 'removeEventListener'); }); it('should use passive event listeners when available', function () { var element = wrapper(_react["default"].createElement(_["default"], null, function () { return children; })); expect(windowAddEventSpy).toBeCalledWith('scroll', expect.anything(), { passive: true }); element.unmount(); expect(windowRemoveEventSpy).toBeCalledWith('scroll', expect.anything(), { passive: true }); }); it('should use passive event listeners when available, container specified', function () { var bodyAddEventSpy = jest.spyOn(document.body, 'addEventListener'); var bodyRemoveEventSpy = jest.spyOn(document.body, 'removeEventListener'); var element = wrapper(_react["default"].createElement(_["default"], { scrollContainer: document.body }, function () { return children; })); expect(bodyAddEventSpy).toBeCalledWith('scroll', expect.anything(), expect.anything()); bodyAddEventSpy.mockClear(); bodyRemoveEventSpy.mockClear(); element.unmount(); expect(bodyRemoveEventSpy).toBeCalledWith('scroll', expect.anything(), expect.anything()); }); it('should cleanup and setup containers accurately when container changes', function () { // Aim: consumer wants to switch to a nested scroll container. var innerScrollContainer = document.createElement('div', { className: 'inner-scroll-container' }); document.body.appendChild(innerScrollContainer); var bodyAddEventSpy = jest.spyOn(document.body, 'addEventListener'); var bodyRemoveEventSpy = jest.spyOn(document.body, 'removeEventListener'); var containerAddEventSpy = jest.spyOn(innerScrollContainer, 'addEventListener'); var containerRemoveEventSpy = jest.spyOn(innerScrollContainer, 'removeEventListener'); var element = wrapper(_react["default"].createElement(_["default"], { scrollContainer: document.body }, function () { return children; })); // Initial events should be attached to the first scroll container specified. expect(bodyAddEventSpy).toBeCalledWith('scroll', expect.anything(), expect.anything()); bodyAddEventSpy.mockClear(); // Switch to the next container. element.setProps({ scrollContainer: innerScrollContainer }); expect(element.prop('scrollContainer')).toBe(innerScrollContainer); // Next, a cleanup should be done of the first container, and setup of the new container. expect(bodyRemoveEventSpy).toBeCalledWith('scroll', expect.anything(), expect.anything()); expect(containerAddEventSpy).toBeCalledWith('scroll', expect.anything(), expect.anything()); containerAddEventSpy.mockClear(); bodyRemoveEventSpy.mockClear(); // Lastly, the component teardown should reference the second container. element.unmount(); expect(containerRemoveEventSpy).toBeCalledWith('scroll', expect.anything(), expect.anything()); containerRemoveEventSpy.mockClear(); }); it('should listen to the window when scrollparent returns body in CSS1Compat mode', function () { mockCompatMode('CSS1Compat'); mockScrollParent = document.body; var element = wrapper(_react["default"].createElement(_["default"], null, function () { return children; })); expect(windowAddEventSpy).toBeCalledWith('scroll', expect.anything(), expect.anything()); expect(bodyAddEventSpy).not.toBeCalledWith('scroll', expect.anything(), expect.anything()); windowAddEventSpy.mockClear(); bodyAddEventSpy.mockClear(); windowRemoveEventSpy.mockClear(); bodyRemoveEventSpy.mockClear(); element.unmount(); expect(windowRemoveEventSpy).toBeCalledWith('scroll', expect.anything(), expect.anything()); expect(bodyRemoveEventSpy).not.toBeCalledWith('scroll', expect.anything(), expect.anything()); unmockCompatMode(); }); it('should listen to the body when scrollparent returns body in BackCompat mode', function () { mockCompatMode('BackCompat'); mockScrollParent = document.body; var windowAddEventSpy = jest.spyOn(window, 'addEventListener'); var bodyAddEventSpy = jest.spyOn(document.body, 'addEventListener'); var windowRemoveEventSpy = jest.spyOn(window, 'removeEventListener'); var bodyRemoveEventSpy = jest.spyOn(document.body, 'removeEventListener'); var element = wrapper(_react["default"].createElement(_["default"], null, function () { return children; })); expect(windowAddEventSpy).not.toBeCalledWith('scroll', expect.anything(), expect.anything()); expect(bodyAddEventSpy).toBeCalledWith('scroll', expect.anything(), expect.anything()); windowAddEventSpy.mockClear(); bodyAddEventSpy.mockClear(); windowRemoveEventSpy.mockClear(); bodyRemoveEventSpy.mockClear(); element.unmount(); expect(windowRemoveEventSpy).not.toBeCalledWith('scroll', expect.anything(), expect.anything()); expect(bodyRemoveEventSpy).toBeCalledWith('scroll', expect.anything(), expect.anything()); unmockCompatMode(); }); }); });