diff --git a/README.md b/README.md index 12c454e..394acd9 100644 --- a/README.md +++ b/README.md @@ -35,3 +35,6 @@ And if you use `npm` ```shell npm install react-router-scroll-top --save ``` + +## Props + - `delay` _(number) : A delay before scroll to top function is run. Default `0` diff --git a/package-lock.json b/package-lock.json index 9d2bc96..ec8c8fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-router-scroll-top", - "version": "0.2.0", + "version": "0.2.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/src/ScrollToTop.js b/src/ScrollToTop.js index e6c9193..1ba0859 100644 --- a/src/ScrollToTop.js +++ b/src/ScrollToTop.js @@ -4,6 +4,10 @@ import React, { Fragment } from "react" import { type Props } from "." class ScrollToTop extends React.PureComponent { + static defaultProps: { + delay: 0 + } + componentDidUpdate: (prevProps: Props) => void props: Props diff --git a/src/index.js b/src/index.js index f15a2ab..c354c36 100644 --- a/src/index.js +++ b/src/index.js @@ -18,16 +18,17 @@ type Location = { export type Props = { children?: React$Node, - location: Location + location: Location, + delay: number } export const componentDidUpdate = function componentDidUpdate( prevProps: Props ) { - const { location }: Props = this.props + const { location, delay }: Props = this.props if (location !== prevProps.location) { - window.scrollTo(LEFT, TOP) + setTimeout(() => window.scrollTo(LEFT, TOP), delay) } } diff --git a/src/index.test.js b/src/index.test.js index 2b86122..73ae9b3 100644 --- a/src/index.test.js +++ b/src/index.test.js @@ -4,21 +4,32 @@ import { spy } from "sinon" const TOP = 0 const LEFT = 0 +const TIMEOUTS = 1 +const NO_DELAY = 0 +const DELAY = 1000 + +jest.useFakeTimers() + describe("ScrollToTop", () => { describe("componentDidUpdate", () => { it("scrolls window to top on location update", () => { global.scrollTo = spy() const prevProps = { - location: "/" + location: "/", } const props = { - location: "/about" + location: "/about", } componentDidUpdate.bind({ props })(prevProps) - expect(global.scrollTo.calledOnce).toBe(true) - expect(global.scrollTo.calledWith(TOP, LEFT)).toBe(true) + setTimeout(() => { + expect(setTimeout).toHaveBeenCalledTimes(TIMEOUTS) + expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), NO_DELAY) + + expect(global.scrollTo.calledOnce).toBe(true) + expect(global.scrollTo.calledWith(TOP, LEFT)).toBe(true) + }, NO_DELAY) }) it("does not scroll window to top on same location", () => { @@ -35,5 +46,45 @@ describe("ScrollToTop", () => { expect(global.scrollTo.calledOnce).toBe(false) }) + + it("scrolls window after given delay", () => { + global.scrollTo = spy() + + const prevProps = { + location: "/" + } + const props = { + delay: DELAY, + location: "/about" + } + + componentDidUpdate.bind({ props })(prevProps) + + setTimeout(() => { + expect(setTimeout).toHaveBeenCalledTimes(TIMEOUTS) + expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), DELAY) + + expect(global.scrollTo.calledOnce).toBe(true) + expect(global.scrollTo.calledWith(TOP, LEFT)).toBe(true) + }, DELAY) + }) + + it("does not scroll window immediately if given delay", () => { + global.scrollTo = spy() + + const prevProps = { + location: "/" + } + const props = { + delay: DELAY, + location: "/about" + } + + componentDidUpdate.bind({ props })(prevProps) + + setTimeout(() => { + expect(global.scrollTo.calledOnce).toBe(false) + }, NO_DELAY) + }) }) })