From f5d4ad72f8c57126903b252e15e20874a90755dd Mon Sep 17 00:00:00 2001 From: Niko Simonson Date: Fri, 29 Dec 2017 11:48:52 -0800 Subject: [PATCH 1/4] Add tests for location path --- packages/gatsby-link/src/__tests__/index.js | 72 +++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/packages/gatsby-link/src/__tests__/index.js b/packages/gatsby-link/src/__tests__/index.js index f79aa0645fcd8..1febd7ca08e19 100644 --- a/packages/gatsby-link/src/__tests__/index.js +++ b/packages/gatsby-link/src/__tests__/index.js @@ -1,3 +1,7 @@ +import React from "react" +import ReactDOM from "react-dom" +import { MemoryRouter } from "react-router-dom" + const getInstance = (props, pathPrefix = ``) => { Object.assign(global.window, { __PREFIX_PATHS__: pathPrefix ? true : false, @@ -60,6 +64,74 @@ describe(``, () => { }) }) + describe(`the location to link to`, () => { + global.___loader = { + enqueue: jest.fn(), + } + + it(`accepts to as a string`, () => { + const location = `/courses?sort=name` + + const node = document.createElement(`div`) + const Link = require(`../`).default + + ReactDOM.render( + + link + , + node + ) + + const href = node.querySelector(`a`).getAttribute(`href`) + + expect(href).toEqual(location) + }) + + it(`accepts a location "to" prop`, () => { + const location = { + pathname: `/courses`, + search: `?sort=name`, + hash: `#the-hash`, + state: { fromDashboard: true }, + } + + const node = document.createElement(`div`) + const Link = require(`../`).default + + ReactDOM.render( + + link + , + node + ) + + const href = node.querySelector(`a`).getAttribute(`href`) + + expect(href).toEqual(`/courses?sort=name#the-hash`) + }) + + it(`resolves to with no pathname using current location`, () => { + const location = { + search: `?sort=name`, + hash: `#the-hash`, + } + + const node = document.createElement(`div`) + const Link = require(`../`).default + + ReactDOM.render( + + link + , + node + ) + + const href = node.querySelector(`a`).getAttribute(`href`) + + expect(href).toEqual(`/somewhere?sort=name#the-hash`) + }) + }) + it(`navigateTo is called with correct args`, () => { getNavigateTo()(`/some-path`) From ccf30cab94551b1913c049f8c241251f3d2460c1 Mon Sep 17 00:00:00 2001 From: Niko Simonson Date: Wed, 3 Jan 2018 21:20:14 -0800 Subject: [PATCH 2/4] Add location object as valid to prop --- packages/gatsby-link/src/index.js | 35 +++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/packages/gatsby-link/src/index.js b/packages/gatsby-link/src/index.js index 0065f651d54a8..853298429fc49 100644 --- a/packages/gatsby-link/src/index.js +++ b/packages/gatsby-link/src/index.js @@ -2,6 +2,7 @@ import React from "react" import { Link, NavLink } from "react-router-dom" import PropTypes from "prop-types" +import { createLocation as cL, createPath } from "history" let pathPrefix = `/` if (typeof __PREFIX_PATHS__ !== `undefined` && __PREFIX_PATHS__) { @@ -16,6 +17,12 @@ function normalizePath(path) { return path.replace(/^\/\//g, `/`) } +function createLocation(path, history) { + const location = cL(path, null, null, history.location) + location.pathname = withPrefix(location.pathname) + return location +} + const NavLinkPropTypes = { activeClassName: PropTypes.string, activeStyle: PropTypes.object, @@ -45,7 +52,7 @@ const handleIntersection = (el, cb) => { } class GatsbyLink extends React.Component { - constructor(props) { + constructor(props, context) { super() // Default to no support for IntersectionObserver let IOSupported = false @@ -53,8 +60,12 @@ class GatsbyLink extends React.Component { IOSupported = true } + const { history } = context.router + const to = createLocation(props.to, history) + this.state = { - to: withPrefix(props.to), + path: createPath(to), + to, IOSupported, } this.handleRef = this.handleRef.bind(this) @@ -62,12 +73,14 @@ class GatsbyLink extends React.Component { componentWillReceiveProps(nextProps) { if (this.props.to !== nextProps.to) { + const to = createLocation(nextProps.to, history) this.setState({ - to: withPrefix(nextProps.to), + path: createPath(to), + to, }) // Preserve non IO functionality if no support if (!this.state.IOSupported) { - ___loader.enqueue(this.state.to) + ___loader.enqueue(this.state.path) } } } @@ -75,7 +88,7 @@ class GatsbyLink extends React.Component { componentDidMount() { // Preserve non IO functionality if no support if (!this.state.IOSupported) { - ___loader.enqueue(this.state.to) + ___loader.enqueue(this.state.path) } } @@ -85,7 +98,7 @@ class GatsbyLink extends React.Component { if (this.state.IOSupported && ref) { // If IO supported and element reference found, setup Observer functionality handleIntersection(ref, () => { - ___loader.enqueue(this.state.to) + ___loader.enqueue(this.state.path) }) } } @@ -116,7 +129,7 @@ class GatsbyLink extends React.Component { ) { // Is this link pointing to a hash on the same page? If so, // just scroll there. - let pathname = this.state.to + let pathname = this.state.path if (pathname.split(`#`).length > 1) { pathname = pathname .split(`#`) @@ -124,7 +137,7 @@ class GatsbyLink extends React.Component { .join(``) } if (pathname === window.location.pathname) { - const hashFragment = this.state.to + const hashFragment = this.state.path .split(`#`) .slice(1) .join(`#`) @@ -139,7 +152,7 @@ class GatsbyLink extends React.Component { // loaded before continuing. if (process.env.NODE_ENV === `production`) { e.preventDefault() - window.___navigateTo(this.state.to) + window.___navigateTo(this.state.path) } } @@ -157,7 +170,7 @@ GatsbyLink.propTypes = { ...NavLinkPropTypes, innerRef: PropTypes.func, onClick: PropTypes.func, - to: PropTypes.string.isRequired, + to: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired, } GatsbyLink.contextTypes = { @@ -167,5 +180,5 @@ GatsbyLink.contextTypes = { export default GatsbyLink export const navigateTo = pathname => { - window.___navigateTo(withPrefix(pathname)) + window.___navigateTo(pathname) } From 971c6dd3e9f1dfe1a33cccd34b54addf19270ea8 Mon Sep 17 00:00:00 2001 From: Niko Simonson Date: Wed, 3 Jan 2018 21:20:40 -0800 Subject: [PATCH 3/4] Update tests --- packages/gatsby-link/src/__tests__/index.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/gatsby-link/src/__tests__/index.js b/packages/gatsby-link/src/__tests__/index.js index 1febd7ca08e19..0c926a4e20322 100644 --- a/packages/gatsby-link/src/__tests__/index.js +++ b/packages/gatsby-link/src/__tests__/index.js @@ -8,8 +8,10 @@ const getInstance = (props, pathPrefix = ``) => { __PATH_PREFIX__: pathPrefix, }) + const context = { router: { history: {} } } + const Link = require(`../`).default - return new Link(props) + return new Link(props, context) } const getNavigateTo = () => { @@ -31,8 +33,9 @@ const getWithPrefix = (pathPrefix = ``) => { describe(``, () => { it(`does not fail to initialize when __PREFIX_PATHS__ is not defined`, () => { expect(() => { + const context = { router: { history: {} } } const Link = require(`../`).default - const link = new Link({}) //eslint-disable-line no-unused-vars + const link = new Link({}, context) //eslint-disable-line no-unused-vars }).not.toThrow() }) @@ -43,7 +46,7 @@ describe(``, () => { to, }) - expect(instance.state.to).toEqual(to) + expect(instance.state.to.pathname).toEqual(to) }) /* From eb5f8660cf5441e061c8eec8a6c4e6bfb7ad1386 Mon Sep 17 00:00:00 2001 From: Niko Simonson Date: Wed, 3 Jan 2018 22:04:44 -0800 Subject: [PATCH 4/4] Update typescript type --- packages/gatsby-link/index.d.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/gatsby-link/index.d.ts b/packages/gatsby-link/index.d.ts index 039dc625bd465..c2a76e17bb95a 100644 --- a/packages/gatsby-link/index.d.ts +++ b/packages/gatsby-link/index.d.ts @@ -2,7 +2,6 @@ import * as React from "react"; import { NavLinkProps } from "react-router-dom"; export interface GatsbyLinkProps extends NavLinkProps { - to: string; onClick?: (event: any) => void className?: string }