Commit 737c7402 by Wee

test: import `Route` test from react-router

parent 1242da81
import React from 'react'
import ReactDOM from 'react-dom'
import { createMemoryHistory as createHistory } from 'history'
import { MemoryRouter, Router, Route } from 'react-router'
import renderStrict from './utils/renderStrict'
describe('A <Route>', () => {
const node = document.createElement('div')
afterEach(() => {
ReactDOM.unmountComponentAtNode(node)
})
describe('without a <Router>', () => {
it('throws an error', () => {
jest.spyOn(console, 'error').mockImplementation(() => {})
expect(() => {
renderStrict(<Route />, node)
}).toThrow(/You should not use <Route> outside a <Router>/)
})
})
it('renders when it matches', () => {
const text = 'cupcakes'
renderStrict(
<MemoryRouter initialEntries={['/cupcakes']}>
<Route path="/cupcakes" render={() => <h1>{text}</h1>} />
</MemoryRouter>,
node
)
expect(node.innerHTML).toContain(text)
})
it('renders when it matches at the root URL', () => {
const text = 'cupcakes'
renderStrict(
<MemoryRouter initialEntries={['/']}>
<Route path="/" render={() => <h1>{text}</h1>} />
</MemoryRouter>,
node
)
expect(node.innerHTML).toContain(text)
})
it('does not render when it does not match', () => {
const text = 'bubblegum'
renderStrict(
<MemoryRouter initialEntries={['/bunnies']}>
<Route path="/flowers" render={() => <h1>{text}</h1>} />
</MemoryRouter>,
node
)
expect(node.innerHTML).not.toContain(text)
})
it('matches using nextContext when updating', () => {
const history = createHistory({
initialEntries: ['/sushi/california']
})
renderStrict(
<Router history={history}>
<Route path="/sushi/:roll" render={({ match }) => <h1>{match.url}</h1>} />
</Router>,
node
)
history.push('/sushi/spicy-tuna')
expect(node.innerHTML).toContain('/sushi/spicy-tuna')
})
describe('with dynamic segments in the path', () => {
it('decodes them', () => {
renderStrict(
<MemoryRouter initialEntries={['/a%20dynamic%20segment']}>
<Route path="/:id" render={({ match }) => <h1>{match.params.id}</h1>} />
</MemoryRouter>,
node
)
expect(node.innerHTML).toContain('a dynamic segment')
})
})
describe('with an array of paths', () => {
it('matches the first provided path', () => {
const node = document.createElement('div')
ReactDOM.render(
<MemoryRouter initialEntries={['/hello']}>
<Route path={['/hello', '/world']} render={() => <div>Hello World</div>} />
</MemoryRouter>,
node
)
expect(node.innerHTML).toContain('Hello World')
})
it('matches other provided paths', () => {
const node = document.createElement('div')
ReactDOM.render(
<MemoryRouter initialEntries={['/other', '/world']} initialIndex={1}>
<Route path={['/hello', '/world']} render={() => <div>Hello World</div>} />
</MemoryRouter>,
node
)
expect(node.innerHTML).toContain('Hello World')
})
it('provides the matched path as a string', () => {
const node = document.createElement('div')
ReactDOM.render(
<MemoryRouter initialEntries={['/other', '/world']} initialIndex={1}>
<Route path={['/hello', '/world']} render={({ match }) => <div>{match.path}</div>} />
</MemoryRouter>,
node
)
expect(node.innerHTML).toContain('/world')
})
it("doesn't remount when moving from one matching path to another", () => {
const node = document.createElement('div')
const history = createHistory()
const mount = jest.fn()
class MatchedRoute extends React.Component {
componentWillMount() {
mount()
}
render() {
return <div>Hello World</div>
}
}
history.push('/hello')
ReactDOM.render(
<Router history={history}>
<Route path={['/hello', '/world']} component={MatchedRoute} />
</Router>,
node
)
expect(mount).toHaveBeenCalledTimes(1)
expect(node.innerHTML).toContain('Hello World')
history.push('/world/somewhere/else')
expect(mount).toHaveBeenCalledTimes(1)
expect(node.innerHTML).toContain('Hello World')
})
})
describe('with a unicode path', () => {
it('is able to match', () => {
renderStrict(
<MemoryRouter initialEntries={['/パス名']}>
<Route path="/パス名" render={({ match }) => <h1>{match.url}</h1>} />
</MemoryRouter>,
node
)
expect(node.innerHTML).toContain('/パス名')
})
})
describe('with escaped special characters in the path', () => {
it('is able to match', () => {
renderStrict(
<MemoryRouter initialEntries={['/pizza (1)']}>
<Route path="/pizza \(1\)" render={({ match }) => <h1>{match.url}</h1>} />
</MemoryRouter>,
node
)
expect(node.innerHTML).toContain('/pizza (1)')
})
})
describe('with `exact=true`', () => {
it('renders when the URL does not have a trailing slash', () => {
const text = 'bubblegum'
renderStrict(
<MemoryRouter initialEntries={['/somepath/']}>
<Route exact path="/somepath" render={() => <h1>{text}</h1>} />
</MemoryRouter>,
node
)
expect(node.innerHTML).toContain(text)
})
it('renders when the URL has trailing slash', () => {
const text = 'bubblegum'
renderStrict(
<MemoryRouter initialEntries={['/somepath']}>
<Route exact path="/somepath/" render={() => <h1>{text}</h1>} />
</MemoryRouter>,
node
)
expect(node.innerHTML).toContain(text)
})
describe('and `strict=true`', () => {
it('does not render when the URL has a trailing slash', () => {
const text = 'bubblegum'
renderStrict(
<MemoryRouter initialEntries={['/somepath/']}>
<Route exact strict path="/somepath" render={() => <h1>{text}</h1>} />
</MemoryRouter>,
node
)
expect(node.innerHTML).not.toContain(text)
})
it('does not render when the URL does not have a trailing slash', () => {
const text = 'bubblegum'
renderStrict(
<MemoryRouter initialEntries={['/somepath']}>
<Route exact strict path="/somepath/" render={() => <h1>{text}</h1>} />
</MemoryRouter>,
node
)
expect(node.innerHTML).not.toContain(text)
})
})
})
describe('the `location` prop', () => {
it('overrides `context.location`', () => {
const text = 'bubblegum'
renderStrict(
<MemoryRouter initialEntries={['/cupcakes']}>
<Route location={{ pathname: '/bubblegum' }} path="/bubblegum" render={() => <h1>{text}</h1>} />
</MemoryRouter>,
node
)
expect(node.innerHTML).toContain(text)
})
})
describe('the `children` prop', () => {
describe('that is an element', () => {
it('renders', () => {
const text = 'bubblegum'
renderStrict(
<MemoryRouter initialEntries={['/']}>
<Route path="/">
<h1>{text}</h1>
</Route>
</MemoryRouter>,
node
)
expect(node.innerHTML).toContain(text)
})
})
describe('that is a function', () => {
it('receives { history, location, match } props', () => {
const history = createHistory()
let props = null
renderStrict(
<Router history={history}>
<Route
path="/"
children={p => {
props = p
return null
}}
/>
</Router>,
node
)
expect(props).not.toBe(null)
expect(props.history).toBe(history)
expect(typeof props.location).toBe('object')
expect(typeof props.match).toBe('object')
})
it('renders', () => {
const text = 'bubblegum'
renderStrict(
<MemoryRouter initialEntries={['/']}>
<Route path="/" children={() => <h1>{text}</h1>} />
</MemoryRouter>,
node
)
expect(node.innerHTML).toContain(text)
})
describe('that returns `undefined`', () => {
it('logs a warning to the console and renders nothing', () => {
jest.spyOn(console, 'warn').mockImplementation(() => {})
renderStrict(
<MemoryRouter initialEntries={['/']}>
<Route path="/" children={() => undefined} />
</MemoryRouter>,
node
)
expect(node.innerHTML).toEqual('')
expect(console.warn).toHaveBeenCalledWith(
expect.stringContaining('You returned `undefined` from the `children` function')
)
})
})
})
describe('that is an empty array (as in Preact)', () => {
it('ignores the children', () => {
const text = 'bubblegum'
renderStrict(
<MemoryRouter>
<Route render={() => <h1>{text}</h1>}>{[]}</Route>
</MemoryRouter>,
node
)
expect(node.innerHTML).toContain(text)
})
})
})
describe('the `component` prop', () => {
it('renders the component', () => {
const text = 'bubblegum'
const Home = () => <h1>{text}</h1>
renderStrict(
<MemoryRouter initialEntries={['/']}>
<Route path="/" component={Home} />
</MemoryRouter>,
node
)
expect(node.innerHTML).toContain(text)
})
it('receives { history, location, match } props', () => {
const history = createHistory()
let props = null
const Component = p => {
props = p
return null
}
renderStrict(
<Router history={history}>
<Route path="/" component={Component} />
</Router>,
node
)
expect(props).not.toBe(null)
expect(props.history).toBe(history)
expect(typeof props.location).toBe('object')
expect(typeof props.match).toBe('object')
})
it("won't throw a prop-type warning when passed valid React components that aren't functions", () => {
function forwardRef(Component) {
class ForwardComponent extends React.Component {
render() {
const { forwardedRef, ...rest } = this.props
return <Component ref={forwardedRef} {...rest} />
}
}
return React.forwardRef((props, ref) => {
return <ForwardComponent {...props} forwardedRef={ref} />
})
}
const history = createHistory()
const Component = () => null
const WrappedComponent = forwardRef(Component)
jest.spyOn(console, 'error').mockImplementation(() => {})
ReactDOM.render(
<Router history={history}>
<Route path="/" component={WrappedComponent} />
</Router>,
node
)
expect(console.error).not.toHaveBeenCalled()
})
})
describe('the `render` prop', () => {
it('renders its return value', () => {
const text = 'Mrs. Kato'
renderStrict(
<MemoryRouter initialEntries={['/']}>
<Route path="/" render={() => <h1>{text}</h1>} />
</MemoryRouter>,
node
)
expect(node.innerHTML).toContain(text)
})
it('receives { history, location, match } props', () => {
const history = createHistory()
let props = null
renderStrict(
<Router history={history}>
<Route
path="/"
render={p => {
props = p
return null
}}
/>
</Router>,
node
)
expect(props).not.toBe(null)
expect(props.history).toBe(history)
expect(typeof props.location).toBe('object')
expect(typeof props.match).toBe('object')
})
})
})
import React from "react";
let StrictMode = function(props) {
return props.children || null;
};
if (React.StrictMode) {
StrictMode = React.StrictMode;
}
export default StrictMode;
import React from "react";
import ReactDOM from "react-dom";
import StrictMode from "./StrictMode";
function renderStrict(element, node) {
ReactDOM.render(<StrictMode>{element}</StrictMode>, node);
}
export default renderStrict;
...@@ -5,7 +5,7 @@ var __extends = (this && this.__extends) || (function () { ...@@ -5,7 +5,7 @@ var __extends = (this && this.__extends) || (function () {
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b); return extendStatics(d, b);
}; }
return function (d, b) { return function (d, b) {
extendStatics(d, b); extendStatics(d, b);
function __() { this.constructor = d; } function __() { this.constructor = d; }
......
...@@ -29,10 +29,12 @@ ...@@ -29,10 +29,12 @@
"warning": "^4.0.1" "warning": "^4.0.1"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^24.0.9",
"@types/react": "^16.7.18", "@types/react": "^16.7.18",
"@types/react-dom": "^16.0.11", "@types/react-dom": "^16.0.11",
"jest": "^23.1.0", "jest": "^23.1.0",
"react-addons-test-utils": "^15.6.2", "react-addons-test-utils": "^15.6.2",
"ts-jest": "^24.0.0",
"tslint-config-prettier": "^1.17.0" "tslint-config-prettier": "^1.17.0"
}, },
"jest": { "jest": {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment