-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: extract common code to find & parse matching route from URL (…
…#80) * refactor: extract common code to find & parse matching route from URL extract the common code from both history-adapter.ts and static-adapter.ts and expose the new common function for use in setting up the initialState of the routerStore * refactor: rename files for consistency
- Loading branch information
1 parent
eda74bf
commit 98cf4af
Showing
5 changed files
with
128 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { JsRouterState, Route } from '../router-store'; | ||
import { matchUrl } from './match-url'; | ||
import { parse } from 'query-string'; | ||
import { Location } from 'history'; | ||
|
||
/* | ||
* Find a route that matches the URL to a pattern and extracts the components. | ||
* | ||
* Can be used to generate the initial routerState when initialising the RouterStore. | ||
* e.g. | ||
* const history = createBrowserHistory(); | ||
routerStore = new RouterStore( | ||
rootStore, | ||
routes, | ||
notFound, | ||
findMatchingRoute(history.location, routes) | ||
); | ||
*/ | ||
export const findMatchingRoute = ( | ||
location: Location, | ||
routes: Route[] | ||
): JsRouterState | undefined => { | ||
// Find the matching route | ||
let matchingRoute = null; | ||
let params = undefined; | ||
for (let i = 0; i < routes.length; i++) { | ||
const route = routes[i]; | ||
params = matchUrl(location.pathname, route.pattern); | ||
if (params) { | ||
matchingRoute = route; | ||
break; | ||
} | ||
} | ||
if (matchingRoute) { | ||
return { | ||
routeName: matchingRoute.name, | ||
params, | ||
queryParams: parse(location.search) | ||
}; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import { findMatchingRoute } from '../src/adapters/find-matching-route'; | ||
import { createLocation } from 'history'; | ||
import { Route } from '../src/router-store'; | ||
|
||
const routes: Route[] = [ | ||
{ name: 'home', pattern: '/' }, | ||
{ | ||
name: 'department', | ||
pattern: '/departments' | ||
}, | ||
{ | ||
name: 'department-category', | ||
pattern: '/departments/:id/:category' | ||
}, | ||
{ name: 'notFound', pattern: '/not-found' } | ||
]; | ||
|
||
describe('findMatchingRoute', () => { | ||
test('returns params when url matches pattern, no params, no queryParams', () => { | ||
const jsRouterState = findMatchingRoute( | ||
createLocation('/departments'), | ||
routes | ||
); | ||
expect(jsRouterState).toEqual({ | ||
routeName: 'department', | ||
params: {}, | ||
queryParams: {} | ||
}); | ||
}); | ||
|
||
test('returns params when url matches pattern, params, no queryParams', () => { | ||
const jsRouterState = findMatchingRoute( | ||
createLocation('/departments/electronics/computers'), | ||
routes | ||
); | ||
expect(jsRouterState).toEqual({ | ||
routeName: 'department-category', | ||
params: { id: 'electronics', category: 'computers' }, | ||
queryParams: {} | ||
}); | ||
}); | ||
|
||
test('returns params when url matches pattern, params, single queryParam', () => { | ||
const jsRouterState = findMatchingRoute( | ||
createLocation('/departments/electronics/computers?q=apple'), | ||
routes | ||
); | ||
expect(jsRouterState).toEqual({ | ||
routeName: 'department-category', | ||
params: { id: 'electronics', category: 'computers' }, | ||
queryParams: { q: 'apple' } | ||
}); | ||
}); | ||
|
||
test('returns params when url matches pattern, params, multiple queryParams', () => { | ||
const jsRouterState = findMatchingRoute( | ||
createLocation('/departments/electronics/computers?q=apple&r=pear'), | ||
routes | ||
); | ||
expect(jsRouterState).toEqual({ | ||
routeName: 'department-category', | ||
params: { id: 'electronics', category: 'computers' }, | ||
queryParams: { q: 'apple', r: 'pear' } | ||
}); | ||
}); | ||
|
||
test('returns undefined when url matches no pattern', () => { | ||
const jsRouterState = findMatchingRoute( | ||
createLocation('/notValidUrl'), | ||
routes | ||
); | ||
expect(jsRouterState).toEqual(undefined); | ||
}); | ||
}); |