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
JSX
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);
});
});