From 7129ece920cbe3e25c9b9acf6e28ba5f4a6869c3 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 4 Feb 2021 15:14:59 +0800 Subject: [PATCH] Fix it will fire `onEnter` callback anyway when parent isn't display Fix #328 --- src/waypoint.jsx | 53 ++- test/browser/waypoint_test.jsx | 845 +++++++++++++++++---------------- 2 files changed, 462 insertions(+), 436 deletions(-) diff --git a/src/waypoint.jsx b/src/waypoint.jsx index ef78f2d..f4da764 100644 --- a/src/waypoint.jsx +++ b/src/waypoint.jsx @@ -134,10 +134,7 @@ export class Waypoint extends React.PureComponent { * as a fallback. */ _findScrollableAncestor() { - const { - horizontal, - scrollableAncestor, - } = this.props; + const { horizontal, scrollableAncestor } = this.props; if (scrollableAncestor) { return resolveScrollableAncestorProp(scrollableAncestor); @@ -159,7 +156,11 @@ export class Waypoint extends React.PureComponent { : style.getPropertyValue('overflow-y'); const overflow = overflowDirec || style.getPropertyValue('overflow'); - if (overflow === 'auto' || overflow === 'scroll' || overflow === 'overlay') { + if ( + overflow === 'auto' + || overflow === 'scroll' + || overflow === 'overlay' + ) { return node; } } @@ -169,6 +170,25 @@ export class Waypoint extends React.PureComponent { return window; } + /** + * Traverses up the DOM to check element is display. + * + * @return {Boolean} + */ + _checkDisplay() { + let node = this._ref; + + while (node && node instanceof Element) { + const style = window.getComputedStyle(node); + if (style.getPropertyValue('display') === 'none') { + return false; + } + node = node.parentNode; + } + + return true; + } + /** * @param {Object} event the native scroll event coming from the scrollable * ancestor, or resize event coming from the window. Will be undefined if @@ -181,7 +201,9 @@ export class Waypoint extends React.PureComponent { } const bounds = this._getBounds(); - const currentPosition = getCurrentPosition(bounds); + // If waypoint or its parent is not display + const currentPosition = this._checkDisplay() ? getCurrentPosition(bounds) : INVISIBLE; + const previousPosition = this._previousPosition; const { debug, @@ -221,10 +243,8 @@ export class Waypoint extends React.PureComponent { onLeave.call(this, callbackArg); } - const isRapidScrollDown = previousPosition === BELOW - && currentPosition === ABOVE; - const isRapidScrollUp = previousPosition === ABOVE - && currentPosition === BELOW; + const isRapidScrollDown = previousPosition === BELOW && currentPosition === ABOVE; + const isRapidScrollUp = previousPosition === ABOVE && currentPosition === BELOW; if (fireOnRapidScroll && (isRapidScrollDown || isRapidScrollUp)) { // If the scroll event isn't fired often enough to occur while the @@ -264,7 +284,8 @@ export class Waypoint extends React.PureComponent { contextHeight = horizontal ? window.innerWidth : window.innerHeight; contextScrollTop = 0; } else { - contextHeight = horizontal ? this.scrollableAncestor.offsetWidth + contextHeight = horizontal + ? this.scrollableAncestor.offsetWidth : this.scrollableAncestor.offsetHeight; contextScrollTop = horizontal ? this.scrollableAncestor.getBoundingClientRect().left @@ -341,16 +362,10 @@ if (process.env.NODE_ENV !== 'production') { // For instance, if you pass "-20%", and the containing element is 100px tall, // then the waypoint will be triggered when it has been scrolled 20px beyond // the top of the containing element. - topOffset: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), + topOffset: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), // `bottomOffset` is like `topOffset`, but for the bottom of the container. - bottomOffset: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), + bottomOffset: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), }; } diff --git a/test/browser/waypoint_test.jsx b/test/browser/waypoint_test.jsx index 3170b2a..20d051c 100644 --- a/test/browser/waypoint_test.jsx +++ b/test/browser/waypoint_test.jsx @@ -104,16 +104,15 @@ describe('', () => { }); it('calls the onPositionChange handler', () => { - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: undefined, - event: null, - waypointTop: this.margin + this.topSpacerHeight, - waypointBottom: this.margin + this.topSpacerHeight, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: undefined, + event: null, + waypointTop: this.margin + this.topSpacerHeight, + waypointBottom: this.margin + this.topSpacerHeight, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); it('does not call the onLeave handler', () => { @@ -138,22 +137,21 @@ describe('', () => { event: null, waypointTop: this.margin + this.topSpacerHeight, waypointBottom: this.margin + this.topSpacerHeight, - viewportTop: this.margin - (this.parentHeight * 2), + viewportTop: this.margin - this.parentHeight * 2, viewportBottom: this.margin + this.parentHeight, }); }); it('calls the onPositionChange handler', () => { - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: undefined, - event: null, - waypointTop: this.margin + this.topSpacerHeight, - waypointBottom: this.margin + this.topSpacerHeight, - viewportTop: this.margin - (this.parentHeight * 2), - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: undefined, + event: null, + waypointTop: this.margin + this.topSpacerHeight, + waypointBottom: this.margin + this.topSpacerHeight, + viewportTop: this.margin - this.parentHeight * 2, + viewportBottom: this.margin + this.parentHeight, + }); }); it('does not call the onLeave handler', () => { @@ -179,21 +177,20 @@ describe('', () => { waypointTop: this.margin + this.topSpacerHeight, waypointBottom: this.margin + this.topSpacerHeight, viewportTop: this.margin, - viewportBottom: this.margin + (this.parentHeight * 3), + viewportBottom: this.margin + this.parentHeight * 3, }); }); it('calls the onPositionChange handler', () => { - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: undefined, - event: null, - waypointTop: this.margin + this.topSpacerHeight, - waypointBottom: this.margin + this.topSpacerHeight, - viewportTop: this.margin, - viewportBottom: this.margin + (this.parentHeight * 3), - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: undefined, + event: null, + waypointTop: this.margin + this.topSpacerHeight, + waypointBottom: this.margin + this.topSpacerHeight, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight * 3, + }); }); it('does not call the onLeave handler', () => { @@ -219,22 +216,21 @@ describe('', () => { event: null, waypointTop: this.margin + this.topSpacerHeight, waypointBottom: this.margin + this.topSpacerHeight, - viewportTop: this.margin - (this.parentHeight * 2), - viewportBottom: this.margin + (this.parentHeight * 3), + viewportTop: this.margin - this.parentHeight * 2, + viewportBottom: this.margin + this.parentHeight * 3, }); }); it('calls the onPositionChange handler', () => { - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: undefined, - event: null, - waypointTop: this.margin + this.topSpacerHeight, - waypointBottom: this.margin + this.topSpacerHeight, - viewportTop: this.margin - (this.parentHeight * 2), - viewportBottom: this.margin + (this.parentHeight * 3), - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: undefined, + event: null, + waypointTop: this.margin + this.topSpacerHeight, + waypointBottom: this.margin + this.topSpacerHeight, + viewportTop: this.margin - this.parentHeight * 2, + viewportBottom: this.margin + this.parentHeight * 3, + }); }); it('does not call the onLeave handler', () => { @@ -274,16 +270,15 @@ describe('', () => { }); it('the onLeave handler is called', () => { - expect(this.props.onLeave) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.above, - previousPosition: Waypoint.inside, - event: jasmine.any(Event), - waypointTop: this.margin - 10, - waypointBottom: this.margin - 10, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onLeave).toHaveBeenCalledWith({ + currentPosition: Waypoint.above, + previousPosition: Waypoint.inside, + event: jasmine.any(Event), + waypointTop: this.margin - 10, + waypointBottom: this.margin - 10, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); it('does not call the onEnter handler', () => { @@ -291,16 +286,15 @@ describe('', () => { }); it('the onPositionChange is called', () => { - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.above, - previousPosition: Waypoint.inside, - event: jasmine.any(Event), - waypointTop: this.margin - 10, - waypointBottom: this.margin - 10, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.above, + previousPosition: Waypoint.inside, + event: jasmine.any(Event), + waypointTop: this.margin - 10, + waypointBottom: this.margin - 10, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); }); @@ -325,16 +319,15 @@ describe('', () => { it('calls the onPositionChange handler', () => { this.subject(); - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.below, - previousPosition: undefined, - event: null, - waypointTop: this.margin + this.topSpacerHeight, - waypointBottom: this.margin + this.topSpacerHeight, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.below, + previousPosition: undefined, + event: null, + waypointTop: this.margin + this.topSpacerHeight, + waypointBottom: this.margin + this.topSpacerHeight, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); describe('with children', () => { @@ -353,16 +346,16 @@ describe('', () => { this.props.onPositionChange.calls.reset(); scrollNodeTo(this.component, 100); - expect(this.props.onEnter) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.below, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight - 100, - waypointBottom: this.margin + this.topSpacerHeight - 100 + this.childrenHeight, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onEnter).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.below, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight - 100, + waypointBottom: + this.margin + this.topSpacerHeight - 100 + this.childrenHeight, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); }); @@ -389,31 +382,29 @@ describe('', () => { it('calls the onEnter handler when scrolling down past the threshold', () => { scrollNodeTo(this.subject(), 100); - expect(this.props.onEnter) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.below, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight - 100, - waypointBottom: this.margin + this.topSpacerHeight - 100, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onEnter).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.below, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight - 100, + waypointBottom: this.margin + this.topSpacerHeight - 100, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); it('calls the onPositionChange handler when scrolling down past the threshold', () => { scrollNodeTo(this.subject(), 100); - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.below, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight - 100, - waypointBottom: this.margin + this.topSpacerHeight - 100, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.below, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight - 100, + waypointBottom: this.margin + this.topSpacerHeight - 100, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); it('does not call the onLeave handler when scrolling down past the threshold', () => { @@ -429,31 +420,29 @@ describe('', () => { it('calls the onEnter handler when scrolling down past the threshold', () => { scrollNodeTo(this.subject(), 100); - expect(this.props.onEnter) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.below, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight - 100, - waypointBottom: this.margin + this.topSpacerHeight - 100, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onEnter).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.below, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight - 100, + waypointBottom: this.margin + this.topSpacerHeight - 100, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); it('calls the onPositionChange handler when scrolling down past the threshold', () => { scrollNodeTo(this.subject(), 100); - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.below, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight - 100, - waypointBottom: this.margin + this.topSpacerHeight - 100, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.below, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight - 100, + waypointBottom: this.margin + this.topSpacerHeight - 100, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); it('does not call the onLeave handler when scrolling down past the threshold', () => { @@ -472,50 +461,56 @@ describe('', () => { this.scrollQuicklyPast = () => { this.component = this.subject(); this.props.onPositionChange.calls.reset(); - scrollNodeTo(this.component, this.topSpacerHeight + this.bottomSpacerHeight); + scrollNodeTo( + this.component, + this.topSpacerHeight + this.bottomSpacerHeight, + ); }; }); it('calls the onEnter handler', () => { this.scrollQuicklyPast(); - expect(this.props.onEnter) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.below, - event: jasmine.any(Event), - waypointTop: this.margin - this.bottomSpacerHeight + this.parentHeight, - waypointBottom: this.margin - this.bottomSpacerHeight + this.parentHeight, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onEnter).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.below, + event: jasmine.any(Event), + waypointTop: + this.margin - this.bottomSpacerHeight + this.parentHeight, + waypointBottom: + this.margin - this.bottomSpacerHeight + this.parentHeight, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); it('calls the onLeave handler', () => { this.scrollQuicklyPast(); - expect(this.props.onLeave) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.above, - previousPosition: Waypoint.inside, - event: jasmine.any(Event), - waypointTop: this.margin - this.bottomSpacerHeight + this.parentHeight, - waypointBottom: this.margin - this.bottomSpacerHeight + this.parentHeight, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onLeave).toHaveBeenCalledWith({ + currentPosition: Waypoint.above, + previousPosition: Waypoint.inside, + event: jasmine.any(Event), + waypointTop: + this.margin - this.bottomSpacerHeight + this.parentHeight, + waypointBottom: + this.margin - this.bottomSpacerHeight + this.parentHeight, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); it('calls the onPositionChange handler', () => { this.scrollQuicklyPast(); - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.above, - previousPosition: Waypoint.below, - event: jasmine.any(Event), - waypointTop: this.margin - this.bottomSpacerHeight + this.parentHeight, - waypointBottom: this.margin - this.bottomSpacerHeight + this.parentHeight, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.above, + previousPosition: Waypoint.below, + event: jasmine.any(Event), + waypointTop: + this.margin - this.bottomSpacerHeight + this.parentHeight, + waypointBottom: + this.margin - this.bottomSpacerHeight + this.parentHeight, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); describe('when `fireOnRapidScroll` is disabled', () => { @@ -535,16 +530,17 @@ describe('', () => { it('calls the onPositionChange handler', () => { this.scrollQuicklyPast(); - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.above, - previousPosition: Waypoint.below, - event: jasmine.any(Event), - waypointTop: this.margin - this.bottomSpacerHeight + this.parentHeight, - waypointBottom: this.margin - this.bottomSpacerHeight + this.parentHeight, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.above, + previousPosition: Waypoint.below, + event: jasmine.any(Event), + waypointTop: + this.margin - this.bottomSpacerHeight + this.parentHeight, + waypointBottom: + this.margin - this.bottomSpacerHeight + this.parentHeight, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); }); }); @@ -560,16 +556,15 @@ describe('', () => { this.props.onPositionChange.calls.reset(); scrollNodeTo(this.component, 211); - expect(this.props.onLeave) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.above, - previousPosition: Waypoint.inside, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight - 211, - waypointBottom: this.margin + this.topSpacerHeight - 211, - viewportTop: this.margin + this.parentHeight * -0.1, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onLeave).toHaveBeenCalledWith({ + currentPosition: Waypoint.above, + previousPosition: Waypoint.inside, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight - 211, + waypointBottom: this.margin + this.topSpacerHeight - 211, + viewportTop: this.margin + this.parentHeight * -0.1, + viewportBottom: this.margin + this.parentHeight, + }); }); }); }); @@ -609,16 +604,15 @@ describe('', () => { this.props.onPositionChange.calls.reset(); scrollNodeTo(this.component, 90); - expect(this.props.onEnter) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.below, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight - 90, - waypointBottom: this.margin + this.topSpacerHeight - 90, - viewportTop: this.margin, - viewportBottom: this.margin + Math.floor(this.parentHeight * 1.1), - }); + expect(this.props.onEnter).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.below, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight - 90, + waypointBottom: this.margin + this.topSpacerHeight - 90, + viewportTop: this.margin, + viewportBottom: this.margin + Math.floor(this.parentHeight * 1.1), + }); }); it('does not call the onLeave handler when scrolling down past the bottom offset', () => { @@ -634,16 +628,15 @@ describe('', () => { this.props.onPositionChange.calls.reset(); scrollNodeTo(this.component, 90); - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.below, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight - 90, - waypointBottom: this.margin + this.topSpacerHeight - 90, - viewportTop: this.margin, - viewportBottom: this.margin + Math.floor(this.parentHeight * 1.1), - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.below, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight - 90, + waypointBottom: this.margin + this.topSpacerHeight - 90, + viewportTop: this.margin, + viewportBottom: this.margin + Math.floor(this.parentHeight * 1.1), + }); }); }); @@ -681,16 +674,15 @@ describe('', () => { this.props.onPositionChange.calls.reset(); scrollNodeTo(this.component, 90); - expect(this.props.onEnter) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.below, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight - 90, - waypointBottom: this.margin + this.topSpacerHeight - 90, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight + 10, - }); + expect(this.props.onEnter).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.below, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight - 90, + waypointBottom: this.margin + this.topSpacerHeight - 90, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight + 10, + }); }); it('does not call the onLeave handler when scrolling down past the bottom offset', () => { @@ -706,16 +698,15 @@ describe('', () => { this.props.onPositionChange.calls.reset(); scrollNodeTo(this.component, 90); - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.below, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight - 90, - waypointBottom: this.margin + this.topSpacerHeight - 90, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight + 10, - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.below, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight - 90, + waypointBottom: this.margin + this.topSpacerHeight - 90, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight + 10, + }); }); }); @@ -753,16 +744,15 @@ describe('', () => { this.props.onPositionChange.calls.reset(); scrollNodeTo(this.component, 90); - expect(this.props.onEnter) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.below, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight - 90, - waypointBottom: this.margin + this.topSpacerHeight - 90, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight + 10, - }); + expect(this.props.onEnter).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.below, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight - 90, + waypointBottom: this.margin + this.topSpacerHeight - 90, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight + 10, + }); }); it('does not call the onLeave handler when scrolling down past the bottom offset', () => { @@ -778,16 +768,15 @@ describe('', () => { this.props.onPositionChange.calls.reset(); scrollNodeTo(this.component, 90); - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.below, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight - 90, - waypointBottom: this.margin + this.topSpacerHeight - 90, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight + 10, - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.below, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight - 90, + waypointBottom: this.margin + this.topSpacerHeight - 90, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight + 10, + }); }); }); @@ -825,16 +814,15 @@ describe('', () => { this.props.onPositionChange.calls.reset(); scrollNodeTo(this.component, 90); - expect(this.props.onEnter) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.below, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight - 90, - waypointBottom: this.margin + this.topSpacerHeight - 90, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight + 10, - }); + expect(this.props.onEnter).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.below, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight - 90, + waypointBottom: this.margin + this.topSpacerHeight - 90, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight + 10, + }); }); it('does not call the onLeave handler when scrolling down past the bottom offset', () => { @@ -850,16 +838,15 @@ describe('', () => { this.props.onPositionChange.calls.reset(); scrollNodeTo(this.component, 90); - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.below, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight - 90, - waypointBottom: this.margin + this.topSpacerHeight - 90, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight + 10, - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.below, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight - 90, + waypointBottom: this.margin + this.topSpacerHeight - 90, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight + 10, + }); }); }); }); @@ -938,16 +925,15 @@ describe('', () => { it('calls the onEnter handler when scrolled back up just past the bottom', () => { scrollNodeTo(this.scrollable, this.topSpacerHeight + 50); - expect(this.props.onEnter) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.above, - event: jasmine.any(Event), - waypointTop: -40, - waypointBottom: -40 + this.childrenHeight, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onEnter).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.above, + event: jasmine.any(Event), + waypointTop: -40, + waypointBottom: -40 + this.childrenHeight, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); it('does not call the onLeave handler when scrolled back up just past the bottom', () => { @@ -1009,16 +995,15 @@ describe('', () => { }); it('calls the onEnter handler', () => { - expect(this.props.onEnter) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.above, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight - 200, - waypointBottom: this.margin + this.topSpacerHeight - 200, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onEnter).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.above, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight - 200, + waypointBottom: this.margin + this.topSpacerHeight - 200, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); it('does not call the onLeave handler', () => { @@ -1026,31 +1011,29 @@ describe('', () => { }); it('calls the onPositionChange handler', () => { - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.above, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight - 200, - waypointBottom: this.margin + this.topSpacerHeight - 200, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.above, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight - 200, + waypointBottom: this.margin + this.topSpacerHeight - 200, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); it('calls the onLeave handler when scrolling up past the waypoint', () => { scrollNodeTo(this.scrollable, 99); - expect(this.props.onLeave) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.below, - previousPosition: Waypoint.inside, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight - 99, - waypointBottom: this.margin + this.topSpacerHeight - 99, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onLeave).toHaveBeenCalledWith({ + currentPosition: Waypoint.below, + previousPosition: Waypoint.inside, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight - 99, + waypointBottom: this.margin + this.topSpacerHeight - 99, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); it('does not call the onEnter handler again when scrolling up past the waypoint', () => { @@ -1062,16 +1045,15 @@ describe('', () => { it('calls the onPositionChange handler when scrolling up past the waypoint', () => { scrollNodeTo(this.scrollable, 99); - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.below, - previousPosition: Waypoint.inside, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight - 99, - waypointBottom: this.margin + this.topSpacerHeight - 99, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.below, + previousPosition: Waypoint.inside, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight - 99, + waypointBottom: this.margin + this.topSpacerHeight - 99, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); }); @@ -1085,42 +1067,39 @@ describe('', () => { }); it('calls the onEnter handler', () => { - expect(this.props.onEnter) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.above, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight, - waypointBottom: this.margin + this.topSpacerHeight, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onEnter).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.above, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight, + waypointBottom: this.margin + this.topSpacerHeight, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); it('calls the onLeave handler', () => { - expect(this.props.onLeave) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.below, - previousPosition: Waypoint.inside, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight, - waypointBottom: this.margin + this.topSpacerHeight, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onLeave).toHaveBeenCalledWith({ + currentPosition: Waypoint.below, + previousPosition: Waypoint.inside, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight, + waypointBottom: this.margin + this.topSpacerHeight, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); it('calls the onPositionChange handler', () => { - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.below, - previousPosition: Waypoint.above, - event: jasmine.any(Event), - waypointTop: this.margin + this.topSpacerHeight, - waypointBottom: this.margin + this.topSpacerHeight, - viewportTop: this.margin, - viewportBottom: this.margin + this.parentHeight, - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.below, + previousPosition: Waypoint.above, + event: jasmine.any(Event), + waypointTop: this.margin + this.topSpacerHeight, + waypointBottom: this.margin + this.topSpacerHeight, + viewportTop: this.margin, + viewportBottom: this.margin + this.parentHeight, + }); }); }); }); @@ -1131,16 +1110,15 @@ describe('', () => { const node = ReactDOM.findDOMNode(this.component); node.style.display = 'none'; scrollNodeTo(this.component, 0); - expect(this.props.onLeave) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.invisible, - previousPosition: Waypoint.inside, - event: jasmine.any(Event), - waypointTop: 0, - waypointBottom: 0, - viewportTop: 0, - viewportBottom: 0, - }); + expect(this.props.onLeave).toHaveBeenCalledWith({ + currentPosition: Waypoint.invisible, + previousPosition: Waypoint.inside, + event: jasmine.any(Event), + waypointTop: 0, + waypointBottom: 0, + viewportTop: 0, + viewportBottom: 0, + }); }); }); @@ -1170,48 +1148,45 @@ describe('', () => { it('fires the onPositionChange handler on mount', () => { this.subject(); - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.below, - previousPosition: undefined, - event: null, - waypointTop: this.margin + this.topSpacerHeight, - waypointBottom: this.margin + this.topSpacerHeight, - viewportTop: 0, - viewportBottom: window.innerHeight, - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.below, + previousPosition: undefined, + event: null, + waypointTop: this.margin + this.topSpacerHeight, + waypointBottom: this.margin + this.topSpacerHeight, + viewportTop: 0, + viewportBottom: window.innerHeight, + }); }); it('fires the onEnter handler when the Waypoint is in view', () => { this.subject(); scrollNodeTo(window, this.topSpacerHeight - window.innerHeight / 2); - expect(this.props.onEnter) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.below, - event: jasmine.any(Event), - waypointTop: this.margin + Math.ceil(window.innerHeight / 2), - waypointBottom: this.margin + Math.ceil(window.innerHeight / 2), - viewportTop: 0, - viewportBottom: window.innerHeight, - }); + expect(this.props.onEnter).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.below, + event: jasmine.any(Event), + waypointTop: this.margin + Math.ceil(window.innerHeight / 2), + waypointBottom: this.margin + Math.ceil(window.innerHeight / 2), + viewportTop: 0, + viewportBottom: window.innerHeight, + }); }); it('fires the onPositionChange handler when the Waypoint is in view', () => { this.subject(); scrollNodeTo(window, this.topSpacerHeight - window.innerHeight / 2); - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: Waypoint.below, - event: jasmine.any(Event), - waypointTop: this.margin + Math.ceil(window.innerHeight / 2), - waypointBottom: this.margin + Math.ceil(window.innerHeight / 2), - viewportTop: 0, - viewportBottom: window.innerHeight, - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: Waypoint.below, + event: jasmine.any(Event), + waypointTop: this.margin + Math.ceil(window.innerHeight / 2), + waypointBottom: this.margin + Math.ceil(window.innerHeight / 2), + viewportTop: 0, + viewportBottom: window.innerHeight, + }); }); }); @@ -1284,16 +1259,15 @@ describe('', () => { }); it('calls the onEnter handler', () => { - expect(this.props.onEnter) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: undefined, - event: null, - waypointTop: 20 + this.topSpacerHeight, - waypointBottom: 20 + this.topSpacerHeight, - viewportTop: 0, - viewportBottom: window.innerHeight, - }); + expect(this.props.onEnter).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: undefined, + event: null, + waypointTop: 20 + this.topSpacerHeight, + waypointBottom: 20 + this.topSpacerHeight, + viewportTop: 0, + viewportBottom: window.innerHeight, + }); }); it('does not call the onLeave handler', () => { @@ -1301,16 +1275,15 @@ describe('', () => { }); it('calls the onPositionChange handler', () => { - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.inside, - previousPosition: undefined, - event: null, - waypointTop: 20 + this.topSpacerHeight, - waypointBottom: 20 + this.topSpacerHeight, - viewportTop: 0, - viewportBottom: window.innerHeight, - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.inside, + previousPosition: undefined, + event: null, + waypointTop: 20 + this.topSpacerHeight, + waypointBottom: 20 + this.topSpacerHeight, + viewportTop: 0, + viewportBottom: window.innerHeight, + }); }); describe('when scrolling while the waypoint is visible', () => { @@ -1334,16 +1307,15 @@ describe('', () => { it('the onLeave handler is called when scrolling past the waypoint', () => { scrollNodeTo(window, 25); - expect(this.props.onLeave) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.above, - previousPosition: Waypoint.inside, - event: jasmine.any(Event), - waypointTop: 20 + this.topSpacerHeight - 25, - waypointBottom: 20 + this.topSpacerHeight - 25, - viewportTop: 0, - viewportBottom: window.innerHeight, - }); + expect(this.props.onLeave).toHaveBeenCalledWith({ + currentPosition: Waypoint.above, + previousPosition: Waypoint.inside, + event: jasmine.any(Event), + waypointTop: 20 + this.topSpacerHeight - 25, + waypointBottom: 20 + this.topSpacerHeight - 25, + viewportTop: 0, + viewportBottom: window.innerHeight, + }); }); it('does not call the onEnter handler when scrolling past the waypoint', () => { @@ -1355,19 +1327,54 @@ describe('', () => { it('the onPositionChange handler is called when scrolling past the waypoint', () => { scrollNodeTo(window, 25); - expect(this.props.onPositionChange) - .toHaveBeenCalledWith({ - currentPosition: Waypoint.above, - previousPosition: Waypoint.inside, - event: jasmine.any(Event), - waypointTop: 20 + this.topSpacerHeight - 25, - waypointBottom: 20 + this.topSpacerHeight - 25, - viewportTop: 0, - viewportBottom: window.innerHeight, - }); + expect(this.props.onPositionChange).toHaveBeenCalledWith({ + currentPosition: Waypoint.above, + previousPosition: Waypoint.inside, + event: jasmine.any(Event), + waypointTop: 20 + this.topSpacerHeight - 25, + waypointBottom: 20 + this.topSpacerHeight - 25, + viewportTop: 0, + viewportBottom: window.innerHeight, + }); }); }); }); + + describe('when parent element not display', () => { + beforeEach(() => { + this.subject = () => { + const parentStyle = { + height: 100, + overflow: 'auto', + display: 'none', + }; + const el = renderAttached( +
+
+ +
+
, + ); + + jasmine.clock().tick(1); + return el; + }; + }); + + afterEach(() => { }); + + it('does not call the onEnter handler', () => { + expect(this.props.onEnter).not.toHaveBeenCalled(); + }); + + it('does not call the onLeave handler', () => { + expect(this.props.onLeave).not.toHaveBeenCalled(); + }); + + it('does not call the onPositionChange handler', () => { + expect(this.props.onPositionChange).not.toHaveBeenCalled(); + }); + }); }); // smoke tests for horizontal scrolling @@ -1411,9 +1418,13 @@ describe(' Horizontal', () => { this.subject = () => { const el = renderAttached(
-
+
-
+
, );