Skip to content

Commit

Permalink
Fix inferno router #1608 (#1615)
Browse files Browse the repository at this point in the history
* Fix regression issue due to update of history package

* Prettier

* Fix linting error

* Added test with actual state object
  • Loading branch information
jhsware committed Nov 8, 2022
1 parent 4140367 commit e3c3deb
Show file tree
Hide file tree
Showing 4 changed files with 228 additions and 7 deletions.
88 changes: 86 additions & 2 deletions packages/inferno-router/__tests__/Link.spec.jsx
@@ -1,6 +1,6 @@
import { render } from 'inferno';
import { render, Component } from 'inferno';
import { HashRouter, Link, MemoryRouter } from 'inferno-router';
import { parsePath } from 'history';
import { parsePath, createMemoryHistory } from 'history';

describe('Link (jsx)', () => {
let node;
Expand Down Expand Up @@ -85,4 +85,88 @@ describe('A <Link> underneath a <HashRouter>', () => {
const linkNode = createLinkNode('foo');
expect(linkNode.getAttribute('href')).toEqual('#foo');
});

it('accepts a string `to` prop', () => {
const to = '/the/path?the=query#the-hash';

render(
<MemoryRouter>
<Link to={to}>link</Link>
</MemoryRouter>,
node
);

const a = node.querySelector('a');

expect(a.getAttribute('href')).toEqual('/the/path?the=query#the-hash');
});

it('accepts an object `to` prop', () => {
const to = {
pathname: '/the/path',
search: 'the=query',
hash: '#the-hash'
};

render(
<MemoryRouter>
<Link to={to}>link</Link>
</MemoryRouter>,
node
);

const a = node.querySelector('a');

expect(a.getAttribute('href')).toEqual('/the/path?the=query#the-hash');
});

it('accepts an object `to` prop with state', () => {
const memoryHistoryFoo = createMemoryHistory({
initialEntries: ['/foo']
});
memoryHistoryFoo.push = jest.fn();

const clickHandler = jest.fn();

const to = {
pathname: '/the/path',
search: 'the=query',
hash: '#the-hash',
state: { test: 'ok' }
};

class ContextChecker extends Component {
getChildContext() {
const { context } = this;
context.router.history = memoryHistoryFoo;

return {
router: context.router
};
}

render({ children }) {
return children;
}
}

render(
<MemoryRouter>
<ContextChecker>
<Link to={to} onClick={clickHandler}>
link
</Link>
</ContextChecker>
</MemoryRouter>,
node
);

const a = node.querySelector('a');
a.click();

expect(clickHandler).toBeCalledTimes(1);
expect(memoryHistoryFoo.push).toBeCalledTimes(1);
const { hash, pathname, search, state } = to;
expect(memoryHistoryFoo.push).toBeCalledWith({ hash, pathname, search }, state);
});
});
126 changes: 124 additions & 2 deletions packages/inferno-router/__tests__/NavLink.spec.tsx
@@ -1,5 +1,6 @@
import { render } from 'inferno';
import { MemoryRouter, NavLink } from 'inferno-router';
import { createMemoryHistory } from 'history';
import { Component, render } from 'inferno';
import { HashRouter, MemoryRouter, NavLink } from 'inferno-router';

describe('NavLink', () => {
let node;
Expand Down Expand Up @@ -404,4 +405,125 @@ describe('NavLink', () => {
expect(a.title).toEqual('pasta');
});
});

describe('A <NavLink> underneath a <HashRouter>', () => {
let tmpNode;
beforeEach(function () {
tmpNode = document.createElement('div');
document.body.appendChild(tmpNode);
});

afterEach(function () {
render(null, tmpNode);
document.body.removeChild(tmpNode);
});

const createLinkNode = (to) => {
render(
<HashRouter>
<NavLink to={to} />
</HashRouter>,
tmpNode
);

return tmpNode.querySelector('a');
};

it('has the correct href', () => {
const linkNode = createLinkNode('/foo');
expect(linkNode.getAttribute('href')).toEqual('#/foo');
});

it('has the correct href #2', () => {
const linkNode = createLinkNode('foo');
expect(linkNode.getAttribute('href')).toEqual('#foo');
});

it('accepts a string `to` prop', () => {
const to = '/the/path?the=query#the-hash';

render(
<MemoryRouter>
<NavLink to={to}>link</NavLink>
</MemoryRouter>,
tmpNode
);

const a = tmpNode.querySelector('a');

expect(a.getAttribute('href')).toEqual('/the/path?the=query#the-hash');
});

it('accepts an object `to` prop', () => {
const to = {
hash: '#the-hash',
key: '1',
pathname: '/the/path',
search: 'the=query',
state: null,
};

render(
<MemoryRouter>
<NavLink to={to}>link</NavLink>
</MemoryRouter>,
tmpNode
);

const a = tmpNode.querySelector('a');

expect(a.getAttribute('href')).toEqual('/the/path?the=query#the-hash');
});

it('accepts an object `to` prop with state', async () => {
const memoryHistoryFoo = createMemoryHistory({
initialEntries: ["/foo"]
});
memoryHistoryFoo.push = jest.fn();

const clickHandler = jest.fn();

const to = {
hash: '#the-hash',
key: '1',
pathname: '/the/path',
search: 'the=query',
state: { test: 'ok' }
};

class ContextChecker extends Component {
public getChildContext() {
const { context } = this;
context.router.history = memoryHistoryFoo;

return {
router: context.router
};
}

public render({ children }) {
return children;
}
}

render(
<MemoryRouter>
<ContextChecker>
<NavLink to={to} onClick={clickHandler}>
link
</NavLink>
</ContextChecker>
</MemoryRouter>,
tmpNode
);

const a = tmpNode.querySelector("a");
a.click();

expect(clickHandler).toBeCalledTimes(1);
expect(memoryHistoryFoo.push).toBeCalledTimes(1);
const { hash, pathname, search, state } = to;
expect(memoryHistoryFoo.push).toBeCalledWith({ hash, pathname, search }, state);
});
});
});
10 changes: 7 additions & 3 deletions packages/inferno-router/src/Link.ts
Expand Up @@ -4,6 +4,8 @@ import { invariant } from './utils';
import { combineFrom, isString } from 'inferno-shared';
import type { Location } from 'history';
import { parsePath } from 'history';
import { splitLocation, normalizeToLocation } from "./locationUtils";


const isModifiedEvent = (event: InfernoMouseEvent<any>): boolean => Boolean(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);

Expand Down Expand Up @@ -31,12 +33,14 @@ function handleClick({ props, context }, event: InfernoMouseEvent<any>) {
event.preventDefault();

const { history } = context.router;
const { replace = false, to } = props;
const { replace = false, to: toPropIn } = props;
const { to, state } = splitLocation(normalizeToLocation(toPropIn));


if (replace) {
history.replace(to);
history.replace(to, state);
} else {
history.push(to);
history.push(to, state);
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions packages/inferno-router/src/locationUtils.ts
@@ -0,0 +1,11 @@
import { To, Location, parsePath } from "history";
import { isString } from 'inferno-shared';

export const normalizeToLocation = (to) => {
return isString(to) ? parsePath(to) : to;
};

export const splitLocation = (location: Location): { to: To, state: any} => {
const { key = '', state, ...to } = location;
return { to, state };
}

0 comments on commit e3c3deb

Please sign in to comment.