UNPKG

react-virtualized

Version:

React components for efficiently rendering large, scrollable lists and tabular data

340 lines (336 loc) 10.8 kB
import * as React from 'react'; import { findDOMNode } from 'react-dom'; import { render } from '../TestUtils'; import CellMeasurer from './CellMeasurer'; import CellMeasurerCache, { DEFAULT_HEIGHT, DEFAULT_WIDTH } from './CellMeasurerCache'; // Accounts for the fact that JSDom doesn't support measurements. function mockClientWidthAndHeight(_ref) { var height = _ref.height, width = _ref.width; var object = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : HTMLElement.prototype; var heightFn = jest.fn().mockReturnValue(height); var widthFn = jest.fn().mockReturnValue(width); Object.defineProperty(object, 'offsetHeight', { configurable: true, get: heightFn }); Object.defineProperty(object, 'offsetWidth', { configurable: true, get: widthFn }); return { heightFn: heightFn, widthFn: widthFn }; } function createParent() { var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, cache = _ref2.cache, _ref2$invalidateCellS = _ref2.invalidateCellSizeAfterRender, invalidateCellSizeAfterRender = _ref2$invalidateCellS === void 0 ? jest.fn() : _ref2$invalidateCellS; return { invalidateCellSizeAfterRender: invalidateCellSizeAfterRender, props: { deferredMeasurementCache: cache } }; } function renderHelper() { var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref3$cache = _ref3.cache, cache = _ref3$cache === void 0 ? new CellMeasurerCache({ fixedWidth: true }) : _ref3$cache, _ref3$children = _ref3.children, children = _ref3$children === void 0 ? /*#__PURE__*/React.createElement("div", null) : _ref3$children, parent = _ref3.parent; render(/*#__PURE__*/React.createElement(CellMeasurer, { cache: cache, columnIndex: 0, parent: parent, rowIndex: 0, style: {} }, children)); } describe('CellMeasurer', function () { it('componentDidMount() should measure content that is not already in the cache', function () { var cache = new CellMeasurerCache({ fixedWidth: true }); var parent = createParent({ cache: cache }); var _mockClientWidthAndHe = mockClientWidthAndHeight({ height: 20, width: 100 }), heightFn = _mockClientWidthAndHe.heightFn, widthFn = _mockClientWidthAndHe.widthFn; expect(heightFn).toHaveBeenCalledTimes(0); expect(widthFn).toHaveBeenCalledTimes(0); expect(cache.has(0, 0)).toBe(false); renderHelper({ cache: cache, parent: parent }); expect(parent.invalidateCellSizeAfterRender).toHaveBeenCalled(); expect(heightFn).toHaveBeenCalledTimes(1); expect(widthFn).toHaveBeenCalledTimes(1); expect(cache.has(0, 0)).toBe(true); expect(cache.getWidth(0, 0)).toBe(100); expect(cache.getHeight(0, 0)).toBe(20); }); it('componentDidMount() should not measure content that is already in the cache', function () { var cache = new CellMeasurerCache({ fixedWidth: true }); cache.set(0, 0, 100, 20); var parent = createParent({ cache: cache }); var _mockClientWidthAndHe2 = mockClientWidthAndHeight({ height: 20, width: 100 }), heightFn = _mockClientWidthAndHe2.heightFn, widthFn = _mockClientWidthAndHe2.widthFn; expect(cache.has(0, 0)).toBe(true); renderHelper({ cache: cache, parent: parent }); expect(parent.invalidateCellSizeAfterRender).not.toHaveBeenCalled(); expect(heightFn).toHaveBeenCalledTimes(0); expect(widthFn).toHaveBeenCalledTimes(0); }); it('componentDidUpdate() should measure content that is not already in the cache', function () { var cache = new CellMeasurerCache({ fixedWidth: true }); var parent = createParent({ cache: cache }); renderHelper({ cache: cache, parent: parent }); cache.clear(0, 0); parent.invalidateCellSizeAfterRender.mockReset(); expect(cache.has(0, 0)).toBe(false); expect(cache.getWidth(0, 0)).toBe(DEFAULT_WIDTH); expect(cache.getHeight(0, 0)).toBe(DEFAULT_HEIGHT); var _mockClientWidthAndHe3 = mockClientWidthAndHeight({ height: 20, width: 100 }), heightFn = _mockClientWidthAndHe3.heightFn, widthFn = _mockClientWidthAndHe3.widthFn; renderHelper({ cache: cache, parent: parent }); expect(cache.has(0, 0)).toBe(true); expect(parent.invalidateCellSizeAfterRender).toHaveBeenCalled(); expect(heightFn).toHaveBeenCalledTimes(1); expect(widthFn).toHaveBeenCalledTimes(1); expect(cache.getWidth(0, 0)).toBe(100); expect(cache.getHeight(0, 0)).toBe(20); }); it('componentDidUpdate() should not measure content that is already in the cache', function () { var cache = new CellMeasurerCache({ fixedWidth: true }); cache.set(0, 0, 100, 20); var parent = createParent({ cache: cache }); expect(cache.has(0, 0)).toBe(true); var _mockClientWidthAndHe4 = mockClientWidthAndHeight({ height: 20, width: 100 }), heightFn = _mockClientWidthAndHe4.heightFn, widthFn = _mockClientWidthAndHe4.widthFn; renderHelper({ cache: cache, parent: parent }); renderHelper({ cache: cache, parent: parent }); expect(parent.invalidateCellSizeAfterRender).not.toHaveBeenCalled(); expect(heightFn).toHaveBeenCalledTimes(0); expect(widthFn).toHaveBeenCalledTimes(0); }); it('registerChild() should measure content that is not already in the cache', function () { var cache = new CellMeasurerCache({ fixedWidth: true }); var parent = createParent({ cache: cache }); var element = document.createElement('div'); var _mockClientWidthAndHe5 = mockClientWidthAndHeight({ height: 20, width: 100 }, element), heightFn = _mockClientWidthAndHe5.heightFn, widthFn = _mockClientWidthAndHe5.widthFn; expect(heightFn).toHaveBeenCalledTimes(0); expect(widthFn).toHaveBeenCalledTimes(0); expect(cache.has(0, 0)).toBe(false); renderHelper({ cache: cache, parent: parent, children: function children(_ref4) { var registerChild = _ref4.registerChild; registerChild(element); return null; } }); expect(parent.invalidateCellSizeAfterRender).toHaveBeenCalled(); expect(heightFn).toHaveBeenCalledTimes(1); expect(widthFn).toHaveBeenCalledTimes(1); expect(cache.has(0, 0)).toBe(true); expect(cache.getWidth(0, 0)).toBe(100); expect(cache.getHeight(0, 0)).toBe(20); }); it('registerChild() should not measure content that is already in the cache', function () { var cache = new CellMeasurerCache({ fixedWidth: true }); cache.set(0, 0, 100, 20); var parent = createParent({ cache: cache }); var element = document.createElement('div'); var _mockClientWidthAndHe6 = mockClientWidthAndHeight({ height: 20, width: 100 }, element), heightFn = _mockClientWidthAndHe6.heightFn, widthFn = _mockClientWidthAndHe6.widthFn; expect(cache.has(0, 0)).toBe(true); renderHelper({ cache: cache, parent: parent, children: function children(_ref5) { var registerChild = _ref5.registerChild; registerChild(element); return null; } }); expect(parent.invalidateCellSizeAfterRender).not.toHaveBeenCalled(); expect(heightFn).toHaveBeenCalledTimes(0); expect(widthFn).toHaveBeenCalledTimes(0); }); it('should pass a :measure param to a function child', function () { var cache = new CellMeasurerCache({ fixedWidth: true }); var children = jest.fn().mockReturnValue(/*#__PURE__*/React.createElement("div", null)); renderHelper({ cache: cache, children: children }); expect(children).toHaveBeenCalled(); var params = children.mock.calls[0][0]; expect(typeof params.measure === 'function').toBe(true); }); it('should still update cache without a parent Grid', function () { jest.spyOn(console, 'warn'); mockClientWidthAndHeight({ height: 20, width: 100 }); var cache = new CellMeasurerCache({ fixedWidth: true }); renderHelper({ cache: cache }); // No parent Grid expect(cache.has(0, 0)).toBe(true); expect(console.warn).not.toHaveBeenCalled(); }); // See issue #593 it('should explicitly set width/height style to "auto" before re-measuring', function () { var cache = new CellMeasurerCache({ fixedWidth: true }); var parent = createParent({ cache: cache }); var child = jest.fn().mockReturnValue(/*#__PURE__*/React.createElement("div", { style: { width: 100, height: 30 } })); var measurer; var node = findDOMNode(render(/*#__PURE__*/React.createElement(CellMeasurer, { ref: function ref(_ref6) { measurer = _ref6; }, cache: cache, columnIndex: 0, parent: parent, rowIndex: 0, style: {} }, child))); var styleHeights = [30]; var styleWidths = [100]; Object.defineProperties(node.style, { height: { get: function get() { return styleHeights[styleHeights.length - 1]; }, set: function set(value) { return styleHeights.push(value); } }, width: { get: function get() { return styleWidths[styleWidths.length - 1]; }, set: function set(value) { return styleWidths.push(value); } } }); var _measurer$_getCellMea = measurer._getCellMeasurements(node), height = _measurer$_getCellMea.height, width = _measurer$_getCellMea.width; expect(height).toBeGreaterThan(0); expect(width).toBeGreaterThan(0); expect(styleHeights).toEqual([30, 'auto', 30]); expect(styleWidths).toEqual([100, 100]); }); // See issue #660 it('should reset width/height style values after measuring with style "auto"', function () { var cache = new CellMeasurerCache({ fixedHeight: true }); var parent = createParent({ cache: cache }); var child = jest.fn().mockReturnValue(/*#__PURE__*/React.createElement("div", { style: { width: 100, height: 30 } })); var node = findDOMNode(render(/*#__PURE__*/React.createElement(CellMeasurer, { cache: cache, columnIndex: 0, parent: parent, rowIndex: 0, style: {} }, child))); node.style.width = 200; node.style.height = 60; child.mock.calls[0][0].measure(); expect(node.style.height).toBe('30px'); expect(node.style.width).toBe('100px'); }); });