UNPKG

react-visibility-sensor

Version:

Sensor component for React that notifies you when it goes in or out of the window viewport.

394 lines (346 loc) 10.4 kB
import React from "react"; import ReactDOM from "react-dom"; import assert from "assert"; import VisibilitySensor from "../visibility-sensor"; describe("VisibilitySensor", function() { var node; beforeEach(function() { node = document.createElement("div"); document.body.appendChild(node); }); afterEach(function() { ReactDOM.unmountComponentAtNode(node); document.body.removeChild(node); }); it("should notify of changes to visibility when parent moves", function( done ) { var firstTime = true; var onChange = function(isVisible) { // by default we expect the sensor to be visible if (firstTime) { firstTime = false; assert.equal(isVisible, true, "Component starts out visible"); node.setAttribute( "style", "position:absolute; width:100px; left:-101px" ); } else { // after moving the sensor it should be not visible anymore assert.equal( isVisible, false, "Component has moved out of the visible viewport" ); done(); } }; var element = ( <VisibilitySensor onChange={onChange} intervalDelay={10}> <div style={{ height: "10px", width: "10px" }} /> </VisibilitySensor> ); ReactDOM.render(element, node); }); it("should notify of changes to visibility when user scrolls", function( done ) { var firstTime = true; var onChange = function(isVisible) { // by default we expect the sensor to be visible if (firstTime) { firstTime = false; assert.equal(isVisible, true, "Component starts out visible"); window.scrollTo(0, 1000); } else { // after moving the sensor it should be not visible anymore assert.equal( isVisible, false, "Component has moved out of the visible viewport" ); done(); } }; var element = ( <div style={{ height: "5000px" }}> <VisibilitySensor scrollCheck scrollDelay={10} onChange={onChange} intervalCheck={false} > <div style={{ height: "10px", width: "10px" }} /> </VisibilitySensor> </div> ); ReactDOM.render(element, node); }); it("should notify of changes to visibility when child moves", function(done) { var firstTime = true; var initialStyle = { height: "10px", width: "10px" }; var onChange = function(isVisible) { // by default we expect the sensor to be visible if (firstTime) { firstTime = false; assert.equal(isVisible, true, "Component starts out visible"); const style = { position: "absolute", width: 100, left: -101 }; ReactDOM.render(getElement(style), node); } else { // after moving the sensor it should be not visible anymore assert.equal( isVisible, false, "Component has moved out of the visible viewport" ); done(); } }; // set interval must be one in order for this to work function getElement(style) { return ( <VisibilitySensor onChange={onChange} intervalDelay={10}> <div style={style} /> </VisibilitySensor> ); } ReactDOM.render(getElement(initialStyle), node); }); it("should notify of changes to visibility", function(done) { var onChange = function(isVisible) { assert.equal(isVisible, true, "Component starts out visible"); done(); }; var element = ( <VisibilitySensor onChange={onChange}> <div style={{ height: "10px", width: "10px" }} /> </VisibilitySensor> ); ReactDOM.render(element, node); }); it("should not notify when deactivated", function(done) { var wasCallbackCalled = false; var onChange = function(isVisible) { wasCallbackCalled = true; }; setTimeout(function() { assert(!wasCallbackCalled, "onChange callback should not be called"); done(); }, 20); var element = ( <VisibilitySensor active={false} onChange={onChange} intervalDelay={10} /> ); ReactDOM.render(element, node); }); it("should clear interval and debounceCheck when deactivated", function() { var onChange = function() {}; var element1 = ( <VisibilitySensor active={true} onChange={onChange} scrollCheck resizeCheck /> ); var element2 = ( <VisibilitySensor active={false} onChange={onChange} scrollCheck resizeCheck /> ); var component1 = ReactDOM.render(element1, node); assert(component1.interval, "interval should be set"); assert(component1.debounceCheck, "debounceCheck should be set"); assert( component1.debounceCheck.scroll, "debounceCheck.scroll should be set" ); assert( component1.debounceCheck.resize, "debounceCheck.scroll should be set" ); var component2 = ReactDOM.render(element2, node); assert(!component2.interval, "interval should not be set"); assert(!component2.debounceCheck, "debounceCheck should not be set"); }); it("should work when using offset prop and moving to outside of offset area", function( done ) { var firstTime = true; node.setAttribute("style", "position:absolute; top:51px"); var onChange = function(isVisible) { if (firstTime) { firstTime = false; assert.equal(isVisible, true, "Component starts out visible"); node.setAttribute("style", "position:absolute; top:49px"); } else { assert.equal( isVisible, false, "Component has moved out of offset area" ); done(); } }; var element = ( <VisibilitySensor onChange={onChange} offset={{ top: 50 }} intervalDelay={10} > <div style={{ height: "10px", width: "10px" }} /> </VisibilitySensor> ); ReactDOM.render(element, node); }); it("should be backwards-compatible with old offset config", function(done) { var firstTime = true; node.setAttribute("style", "position:absolute; top:51px"); var onChange = function(isVisible) { if (firstTime) { firstTime = false; assert.equal(isVisible, true, "Component starts out visible"); node.setAttribute("style", "position:absolute; top:49px"); } else { assert.equal( isVisible, false, "Component has moved out of offset area" ); done(); } }; var element = ( <VisibilitySensor onChange={onChange} offset={{ direction: "top", value: 50 }} intervalDelay={10} > <div style={{ height: "10px", width: "10px" }} /> </VisibilitySensor> ); ReactDOM.render(element, node); }); it("should work when using offset prop and moving to inside of offset area", function( done ) { var firstTime = true; node.setAttribute("style", "position:absolute; top:49px"); var onChange = function(isVisible) { if (firstTime) { firstTime = false; assert.equal(isVisible, false, "Component starts out invisible"); node.setAttribute("style", "position:absolute; top:51px"); } else { assert.equal( isVisible, true, "Component has moved inside of offset area" ); done(); } }; var element = ( <VisibilitySensor onChange={onChange} offset={{ top: 50 }} intervalDelay={10} > <div style={{ height: "10px", width: "10px" }} /> </VisibilitySensor> ); ReactDOM.render(element, node); }); it("should work when using negative offset prop and moving to outside of viewport", function( done ) { var firstTime = true; node.setAttribute("style", "position:absolute; top:-49px"); var onChange = function(isVisible) { if (firstTime) { firstTime = false; assert.equal(isVisible, true, "Component starts out visible"); node.setAttribute("style", "position:absolute; top:-51px"); } else { assert.equal( isVisible, false, "Component has moved outside of viewport and visible area" ); done(); } }; var element = ( <VisibilitySensor onChange={onChange} offset={{ top: -50 }} intervalDelay={10} > <div style={{ height: "10px", width: "10px" }} /> </VisibilitySensor> ); ReactDOM.render(element, node); }); it("should call child function with state", function(done) { var wasChildrenCalled = false; var children = function(props) { wasChildrenCalled = true; assert( "isVisible" in props, "children should be called with isVisible prop" ); assert( "visibilityRect" in props, "children should be called with visibilityRect prop" ); return <div />; }; setTimeout(function() { assert(wasChildrenCalled, "children should be called"); done(); }, 200); var element = <VisibilitySensor>{children}</VisibilitySensor>; ReactDOM.render(element, node); }); it("should not return visible if it has no size", function(done) { var firstTime = true; var onChange = function(isVisible) { if (firstTime) { assert.equal(isVisible, false, "Component is not visible"); done(); } }; var element = ( <VisibilitySensor onChange={onChange}> <div style={{ height: "0px", width: "0px" }} /> </VisibilitySensor> ); ReactDOM.render(element, node); }); it("should not return visible if the sensor is hidden", function(done) { var firstTime = true; var onChange = function(isVisible) { if (firstTime) { assert.equal(isVisible, false, "Component is not visible"); done(); } }; var element = ( <div style={{ display: "none" }}> <VisibilitySensor onChange={onChange}> <div style={{ height: "10px", width: "10px" }} /> </VisibilitySensor> </div> ); ReactDOM.render(element, node); }); });