Skip to content

Commit d7a198a

Browse files
authored
Allow router store push/replace to take a LocationShape (#171)
1 parent d6fc1f5 commit d7a198a

File tree

8 files changed

+67
-12
lines changed

8 files changed

+67
-12
lines changed

docs/api/components.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,9 @@ By using either of these you will gain access to the following actions
256256

257257
| prop | type | arguments | description |
258258
| --------------- | ---------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
259-
| `push` | `function` | `path: Href, state?: any` | Calls `history.push` with the supplied args |
259+
| `push` | `function` | `path: Href | Location, state?: any` | Calls `history.push` with the supplied args |
260260
| `pushTo` | `function` | `route: Route, attributes?: { params?: {}, query?: {} }` | Calls `history.push` generating the path from supplied route and attributes |
261-
| `replace` | `function` | `path: Href, state?: any` | Calls `history.replace` with the supplied args |
261+
| `replace` | `function` | `path: Href | Location, state?: any` | Calls `history.replace` with the supplied args |
262262
| `replaceTo` | `function` | `route: Route, attributes?: { params?: {}, query?: {} }` | Calls `history.replace` generating the path from supplied route and attributes |
263263
| `goBack` | `function` | | Goes to the previous route in history |
264264
| `goForward` | `function` | | Goes to the next route in history |

src/__tests__/unit/common/utils/history/test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,21 +117,52 @@ describe('createLegacyHistory', () => {
117117
window.location = holdWindowLocation;
118118
});
119119

120+
it('should not throw when null', () => {
121+
const history = createLegacyHistory();
122+
history.push(null as any);
123+
expect(spy).toHaveBeenCalledWith('/');
124+
})
125+
120126
it('should change location via page reload', async () => {
121127
const history = createLegacyHistory();
122128
history.push('/foo');
123129

124130
expect(spy).toHaveBeenCalledWith('/foo');
125131
});
132+
133+
it('should change location if a Location object is received', async () => {
134+
const history = createLegacyHistory();
135+
history.push({ pathname: '/other', search: '?param=1', hash: '' });
136+
137+
expect(spy).toHaveBeenCalledWith('/other?param=1');
138+
});
126139
});
127140

128141
describe('replace()', () => {
142+
it('should not throw when null', () => {
143+
window.history.replaceState = jest.fn();
144+
const history = createLegacyHistory();
145+
history.replace(null as any);
146+
expect(window.history.replaceState).toHaveBeenCalledWith({}, '', '/');
147+
})
148+
129149
it('should replace location via history', () => {
130150
window.history.replaceState = jest.fn();
131151
const history = createLegacyHistory();
132152
history.replace('/baz');
133153
expect(window.history.replaceState).toHaveBeenCalledWith({}, '', '/baz');
134154
});
155+
156+
it('should replace location if a Location object is received', async () => {
157+
window.history.replaceState = jest.fn();
158+
const history = createLegacyHistory();
159+
history.replace({ pathname: '/other', search: '?param=1', hash: '' });
160+
expect(window.history.replaceState).toHaveBeenCalledWith(
161+
{},
162+
'',
163+
'/other?param=1'
164+
);
165+
});
135166
});
136167

137168
describe('goBack()', () => {

src/__tests__/unit/controllers/router-store/test.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,23 @@ describe('SPA Router store', () => {
369369
expect(mockHistory.push).toBeCalledWith('/board/123');
370370
});
371371

372+
it('should push a relative path a Location object is pushed', () => {
373+
mount(
374+
<MemoryRouter routes={[]}>
375+
<RouterSubscriber>{children}</RouterSubscriber>
376+
</MemoryRouter>
377+
);
378+
const { actions } = getRouterStore();
379+
380+
actions.push({ pathname: '/board/123', search: '', hash: '' });
381+
382+
expect(mockHistory.push).toBeCalledWith({
383+
pathname: '/board/123',
384+
search: '',
385+
hash: '',
386+
});
387+
});
388+
372389
it('should call window.location.assign with the absolute URL if it is on a different domain', () => {
373390
jest
374391
.spyOn(window.location, 'assign')

src/common/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ export type BrowserHistory = (
2626
| Omit<History5, 'location' | 'go' | 'createHref' | 'push' | 'replace'>
2727
) & {
2828
location: Location;
29-
push: (path: string) => void;
30-
replace: (path: string) => void;
29+
push: (path: string | Location) => void;
30+
replace: (path: string | Location) => void;
3131
};
3232

3333
export type MatchParams = {

src/common/utils/history/index.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,16 @@ export const createLegacyHistory = (): BrowserHistory => {
110110
},
111111
...(hasWindow()
112112
? {
113-
push: (path: string) => window.location.assign(path),
114-
replace: (path: string) =>
115-
window.history.replaceState({}, document.title, path),
113+
push: (path: string | Location) =>
114+
window.location.assign(
115+
typeof path === 'string' ? path : createPath(path || {})
116+
),
117+
replace: (path: string | Location) =>
118+
window.history.replaceState(
119+
{},
120+
document.title,
121+
typeof path === 'string' ? path : createPath(path || {})
122+
),
116123
goBack: () => window.history.back(),
117124
goForward: () => window.history.forward(),
118125
listen: createLegacyListener(updateExposedLocation),

src/controllers/router-store/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ const actions: AllRouterActions = {
255255
if (isExternalAbsolutePath(path)) {
256256
window.location.assign(path as string);
257257
} else {
258-
history.push(getRelativePath(path, basePath) as any);
258+
history.push(getRelativePath(path, basePath));
259259
}
260260
},
261261

src/controllers/router-store/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@ type PrivateRouterActions = {
104104
};
105105

106106
type PublicRouterActions = {
107-
push: (path: Href, state?: any) => RouterAction;
107+
push: (path: Href | Location, state?: any) => RouterAction;
108108
pushTo: (route: Route, attributes?: ToAttributes) => RouterAction;
109-
replace: (path: Href) => RouterAction;
109+
replace: (path: Href | Location) => RouterAction;
110110
replaceTo: (route: Route, attributes?: ToAttributes) => RouterAction;
111111
goBack: () => RouterAction;
112112
goForward: () => RouterAction;

src/types.js.flow

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,9 @@ export type RouterAction = Action<EntireRouterState, ContainerProps, *>;
215215
type UnregisterCallback = () => void;
216216

217217
export type RouterActionsType = {|
218-
push: (path: Href, state?: any) => void,
218+
push: (path: Href | Location, state?: any) => void,
219219
pushTo: (route: Route, attributes: ToAttributes) => void,
220-
replace: (path: Href, state?: any) => void,
220+
replace: (path: Href | Location, state?: any) => void,
221221
replaceTo: (route: Route, attributes: ToAttributes) => void,
222222
goBack: () => void,
223223
goForward: () => void,

0 commit comments

Comments
 (0)