From e12b63c438975dafba5f1ecdaad873d342beba6e Mon Sep 17 00:00:00 2001 From: Unknown Date: Sat, 13 Oct 2018 16:48:02 +0100 Subject: [PATCH 1/4] Jest Coverage Flow and Prettier Updates --- .gitignore | 1 + package.json | 6 +++--- yarn.lock | 12 ++++++++---- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index bae3866..90a9b72 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules lib/ yarn-error.log +coverage/ diff --git a/package.json b/package.json index 31af5ce..b205947 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "build": "webpack", "clean": "rm -fr lib/", "prepublish": "yarn test && yarn run clean && yarn run build", - "test": "eslint src/ && flow && jest --silent" + "test": "eslint src/ && flow && jest --silent --coverage" }, "devDependencies": { "babel-core": "^6.26.0", @@ -31,9 +31,9 @@ "eslint-plugin-html": "^4.0.2", "eslint-plugin-prettier": "^2.6.0", "eslint-plugin-react": "^7.6.1", - "flow-bin": "^0.59.0", + "flow-bin": "^0.83.0", "jest-cli": "^21.2.1", - "prettier": "^1.10.2", + "prettier": "^1.14.3", "prettier-eslint": "^8.2.2", "react": "^16.2.0", "react-dom": "^16.2.0", diff --git a/yarn.lock b/yarn.lock index 307fb45..e88f0d7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1918,9 +1918,9 @@ flat-cache@^1.2.1: graceful-fs "^4.1.2" write "^0.2.1" -flow-bin@^0.59.0: - version "0.59.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.59.0.tgz#8c151ee7f09f1deed9bf0b9d1f2e8ab9d470f1bb" +flow-bin@^0.83.0: + version "0.83.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.83.0.tgz#fd26f5f95758d7701264b3f9a1e1a3d4cbcab1a9" for-in@^1.0.1: version "1.0.2" @@ -3587,7 +3587,11 @@ prettier-eslint@^8.2.2: typescript "^2.5.1" typescript-eslint-parser "^11.0.0" -prettier@^1.10.2, prettier@^1.7.0: +prettier@^1.14.3: + version "1.14.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.3.tgz#90238dd4c0684b7edce5f83b0fb7328e48bd0895" + +prettier@^1.7.0: version "1.10.2" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.10.2.tgz#1af8356d1842276a99a5b5529c82dd9e9ad3cc93" From fccb6e4c51691d9b39e75c440428b5e6744907fd Mon Sep 17 00:00:00 2001 From: Unknown Date: Sat, 13 Oct 2018 16:48:52 +0100 Subject: [PATCH 2/4] PureComponent And Flow Updates --- src/ScrollToTop.jsx | 4 ++-- src/ScrollToTop.test.jsx | 2 +- src/index.js | 20 ++++++++++++++++---- src/index.test.js | 2 +- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/ScrollToTop.jsx b/src/ScrollToTop.jsx index d8be82b..e6c9193 100644 --- a/src/ScrollToTop.jsx +++ b/src/ScrollToTop.jsx @@ -1,9 +1,9 @@ // @flow import React, { Fragment } from "react" -import { type Props } from "./" +import { type Props } from "." -class ScrollToTop extends React.Component { +class ScrollToTop extends React.PureComponent { componentDidUpdate: (prevProps: Props) => void props: Props diff --git a/src/ScrollToTop.test.jsx b/src/ScrollToTop.test.jsx index c125455..31cecbb 100644 --- a/src/ScrollToTop.test.jsx +++ b/src/ScrollToTop.test.jsx @@ -5,7 +5,7 @@ import ScrollToTop from "./ScrollToTop" Enzyme.configure({ adapter: new Adapter() }) -jest.mock("./", () => {}) +jest.mock(".", () => ({})) describe("ScrollToTop", () => { it("renders", () => { diff --git a/src/index.js b/src/index.js index 0aec721..f15a2ab 100644 --- a/src/index.js +++ b/src/index.js @@ -1,18 +1,30 @@ // @flow -import { type Element } from "react" import ScrollToTop from "./ScrollToTop" import { withRouter } from "react-router-dom" const TOP = 0 const LEFT = 0 +type Location = { + +key: string, + +pathname: string, + +search: string, + +hash: string, + +state: { + +[string]: boolean + } +} + export type Props = { - children?: Element<*> + children?: React$Node, + location: Location } -export const componentDidUpdate = function componentDidUpdate(prevProps: Props) { - const { location } = this.props +export const componentDidUpdate = function componentDidUpdate( + prevProps: Props +) { + const { location }: Props = this.props if (location !== prevProps.location) { window.scrollTo(LEFT, TOP) diff --git a/src/index.test.js b/src/index.test.js index 567086d..2b86122 100644 --- a/src/index.test.js +++ b/src/index.test.js @@ -1,4 +1,4 @@ -import { componentDidUpdate } from "./" +import { componentDidUpdate } from "." import { spy } from "sinon" const TOP = 0 From 3b485bd658b9791e453b0e52a2a0ac6ba3ee1674 Mon Sep 17 00:00:00 2001 From: Thomas English Date: Thu, 11 Apr 2019 14:26:21 +0100 Subject: [PATCH 3/4] Adding optional `delay` prop The delay prop allows the user to specify an optional delay before the scroll to top function is run. This is helpful for use cases where page transition animations are in place. - Added `delay` prop code - Updated tests - Updated documentation --- README.md | 3 +++ src/ScrollToTop.jsx | 4 +++ src/index.js | 7 +++--- src/index.test.js | 59 ++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 66 insertions(+), 7 deletions(-) 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/src/ScrollToTop.jsx b/src/ScrollToTop.jsx index e6c9193..1ba0859 100644 --- a/src/ScrollToTop.jsx +++ b/src/ScrollToTop.jsx @@ -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) + }) }) }) From fe6801afff072ab02764da5061880eb0f6e5e94b Mon Sep 17 00:00:00 2001 From: Thomas English Date: Thu, 20 Jun 2019 15:00:14 +0100 Subject: [PATCH 4/4] Updated jest snapshot with yarn --- src/__snapshots__/ScrollToTop.test.js.snap | 24 ++-------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/src/__snapshots__/ScrollToTop.test.js.snap b/src/__snapshots__/ScrollToTop.test.js.snap index 273ebc9..8a2beb6 100644 --- a/src/__snapshots__/ScrollToTop.test.js.snap +++ b/src/__snapshots__/ScrollToTop.test.js.snap @@ -2,13 +2,13 @@ exports[`ScrollToTop renders 1`] = ` ShallowWrapper { + "length": 1, Symbol(enzyme.__root__): [Circular], Symbol(enzyme.__unrendered__): , Symbol(enzyme.__renderer__): Object { "batchedUpdates": [Function], "getNode": [Function], "render": [Function], - "simulateError": [Function], "simulateEvent": [Function], "unmount": [Function], }, @@ -40,16 +40,6 @@ ShallowWrapper { "adapter": ReactSixteenAdapter { "options": Object { "enableComponentDidUpdateOnSetState": true, - "lifecycles": Object { - "componentDidUpdate": Object { - "onSetState": true, - }, - "getDerivedStateFromProps": true, - "getSnapshotBeforeUpdate": true, - "setState": Object { - "skipsComponentDidUpdateOnNullish": true, - }, - }, }, }, }, @@ -58,6 +48,7 @@ ShallowWrapper { exports[`ScrollToTop renders children 1`] = ` ShallowWrapper { + "length": 1, Symbol(enzyme.__root__): [Circular], Symbol(enzyme.__unrendered__): @@ -66,7 +57,6 @@ ShallowWrapper { "batchedUpdates": [Function], "getNode": [Function], "render": [Function], - "simulateError": [Function], "simulateEvent": [Function], "unmount": [Function], }, @@ -114,16 +104,6 @@ ShallowWrapper { "adapter": ReactSixteenAdapter { "options": Object { "enableComponentDidUpdateOnSetState": true, - "lifecycles": Object { - "componentDidUpdate": Object { - "onSetState": true, - }, - "getDerivedStateFromProps": true, - "getSnapshotBeforeUpdate": true, - "setState": Object { - "skipsComponentDidUpdateOnNullish": true, - }, - }, }, }, },