(1.1.0) API changes and added some tests
This commit is contained in:
parent
70e426fc20
commit
7013a3c050
@ -15,7 +15,7 @@ A utility to expose an asynchronous API between a web worker and its parent.
|
|||||||
|
|
||||||
## [Router](./packages/router/README.md)
|
## [Router](./packages/router/README.md)
|
||||||
|
|
||||||
A slim and unopinionated router.
|
A slim and unopinionated hash router.
|
||||||
|
|
||||||
## [Trimkit](./packages/trimkit/README.md)
|
## [Trimkit](./packages/trimkit/README.md)
|
||||||
|
|
||||||
|
|||||||
@ -11,8 +11,8 @@ navigated. Parameters are: api (Router instance) badpath (string) lastGoodRoute
|
|||||||
descriptor object for the last good route.
|
descriptor object for the last good route.
|
||||||
|
|
||||||
returns an api object: goto(path) - match the path to a route and navigate there href(pathName,
|
returns an api object: goto(path) - match the path to a route and navigate there href(pathName,
|
||||||
vars) - build a path based on the name and supplied vars listen() - listen to window.onhashchange
|
vars) - build a path based on the name and supplied vars start(initialRoute) - listen to
|
||||||
for route changes current() - get the current route descriptor object
|
window.onhashchange for route changes current() - get the current route descriptor object
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -45,4 +45,5 @@ const router = Router(
|
|||||||
r.goto(lastGoodRoute.path || 'home');
|
r.goto(lastGoodRoute.path || 'home');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
router.start('/');
|
||||||
```
|
```
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "router",
|
"name": "router",
|
||||||
"version": "1.0.0",
|
"version": "1.1.0",
|
||||||
"description": "A slim and unopinionated router",
|
"description": "A slim and unopinionated router",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"jsnext:main": "src/index.js",
|
"jsnext:main": "src/index.js",
|
||||||
@ -14,7 +14,8 @@
|
|||||||
"npm run build:umd && uglifyjs -m --screw-ie8 -c -o dist/router.min.js dist/router.js",
|
"npm run build:umd && uglifyjs -m --screw-ie8 -c -o dist/router.min.js dist/router.js",
|
||||||
"build:umd:gzip": "npm run build:umd:min && gzip -c9 dist/router.min.js > dist/router.min.js.gz",
|
"build:umd:gzip": "npm run build:umd:min && gzip -c9 dist/router.min.js > dist/router.min.js.gz",
|
||||||
"build": "npm run build:umd:gzip && ls -l dist/",
|
"build": "npm run build:umd:gzip && ls -l dist/",
|
||||||
"prepublish": "npm run clean && npm run build"
|
"prepublish": "npm run clean && npm run build",
|
||||||
|
"test": "npm run build:lib && jasmine --verbose"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -41,6 +42,7 @@
|
|||||||
"uglifyjs": "2.4.10"
|
"uglifyjs": "2.4.10"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"jasmine": "^2.5.3",
|
||||||
"trimkit": "^1.0.2"
|
"trimkit": "^1.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
3
packages/router/spec/helpers/globals.js
Normal file
3
packages/router/spec/helpers/globals.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
self = window = {
|
||||||
|
location: {}
|
||||||
|
};
|
||||||
91
packages/router/spec/router.spec.js
Normal file
91
packages/router/spec/router.spec.js
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
const { Router } = require('../lib/index.js');
|
||||||
|
|
||||||
|
describe('router builds urls', () => {
|
||||||
|
describe('for hashed routes', () => {
|
||||||
|
const router = Router(
|
||||||
|
'#',
|
||||||
|
{
|
||||||
|
home: {
|
||||||
|
path: '/',
|
||||||
|
onenter: (r, route) => {},
|
||||||
|
onexit: (r, route, newRoute) => {}
|
||||||
|
},
|
||||||
|
article: {
|
||||||
|
path: '/article/:id',
|
||||||
|
vars: { id: /[a-f0-9]{6,40}/ },
|
||||||
|
onenter: (r, route) => {},
|
||||||
|
onexit: (r, route, newRoute) => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(r, path, lastGoodRoute) => {}
|
||||||
|
);
|
||||||
|
|
||||||
|
it('at the root', () => {
|
||||||
|
expect(router.href('home')).toEqual('#/');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with variables', () => {
|
||||||
|
expect(router.href('article', { id: 156234 })).toEqual('#/article/156234');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('but throws an error', () => {
|
||||||
|
it("if the route doesn't exist", () => {
|
||||||
|
expect(() => {
|
||||||
|
router.href('artcle', { id: 156 });
|
||||||
|
}).toThrowError(Error, 'Invalid route artcle.');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("if the vars don't match", () => {
|
||||||
|
expect(() => {
|
||||||
|
router.href('article', { id: 156 });
|
||||||
|
}).toThrowError(Error, 'Invalid value for route /article/:id var id: 156.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('router goes to routes', () => {
|
||||||
|
describe('for hashed routes', () => {
|
||||||
|
const router = Router(
|
||||||
|
'#',
|
||||||
|
{
|
||||||
|
home: {
|
||||||
|
path: '/',
|
||||||
|
onenter: (r, route) => {},
|
||||||
|
onexit: (r, route, newRoute) => {}
|
||||||
|
},
|
||||||
|
article: {
|
||||||
|
path: '/article/:id',
|
||||||
|
vars: { id: /[a-f0-9]{6,40}/ },
|
||||||
|
onenter: (r, route) => {},
|
||||||
|
onexit: (r, route, newRoute) => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(r, path, lastGoodRoute) => {}
|
||||||
|
);
|
||||||
|
it('at the root', done => {
|
||||||
|
router.goto('home').then(() => {
|
||||||
|
const current = router.current();
|
||||||
|
expect(current.name).toEqual('home');
|
||||||
|
expect(current.path).toEqual('#/');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('with vars', done => {
|
||||||
|
router.goto('article', { id: 156234 }).then(() => {
|
||||||
|
const current = router.current();
|
||||||
|
expect(current.name).toEqual('article');
|
||||||
|
expect(current.path).toEqual('#/article/156234');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('with a url', done => {
|
||||||
|
router.goto('#/article/156233').then(() => {
|
||||||
|
const current = router.current();
|
||||||
|
expect(current.name).toEqual('article');
|
||||||
|
expect(current.path).toEqual('#/article/156233');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
7
packages/router/spec/support/jasmine.json
Normal file
7
packages/router/spec/support/jasmine.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"spec_dir": "spec",
|
||||||
|
"spec_files": ["**/*[sS]pec.js"],
|
||||||
|
"helpers": ["helpers/**/*.js"],
|
||||||
|
"stopSpecOnExpectationFailure": false,
|
||||||
|
"random": false
|
||||||
|
}
|
||||||
@ -1,16 +1,10 @@
|
|||||||
import { isFunction, isUndefined, Null, ObjectKeys } from 'trimkit';
|
import { isFunction, isUndefined, Null, ObjectKeys } from 'trimkit';
|
||||||
|
|
||||||
function nop() {}
|
const VARMATCH_RE = /:([^\/]+)/g;
|
||||||
|
const ROUTEELEMENT_RE = /^[^\/]+$/;
|
||||||
export function Router(baseUrl, routes, unmatched) {
|
const nop = () => 1;
|
||||||
let listening = false;
|
const digestRoutes = (routes, baseUrl) =>
|
||||||
let currentRoute = Null;
|
ObjectKeys(routes).map(name => {
|
||||||
let reEnterHook = Null;
|
|
||||||
|
|
||||||
const VARMATCH_RE = /:([^\/]+)/g;
|
|
||||||
const ROUTEELEMENT_RE = /^[^\/]+$/;
|
|
||||||
|
|
||||||
const routeMatcher = ObjectKeys(routes).map(name => {
|
|
||||||
const route = routes[name];
|
const route = routes[name];
|
||||||
const reg = route.path.replace(VARMATCH_RE, (m, varName) => {
|
const reg = route.path.replace(VARMATCH_RE, (m, varName) => {
|
||||||
const varDef = route.vars || {};
|
const varDef = route.vars || {};
|
||||||
@ -25,6 +19,13 @@ export function Router(baseUrl, routes, unmatched) {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export function Router(baseUrl, routes, unmatched) {
|
||||||
|
let listening = false;
|
||||||
|
let currentRoute = Null;
|
||||||
|
let reEnterHook = Null;
|
||||||
|
|
||||||
|
let routeMatcher = digestRoutes(routes, baseUrl);
|
||||||
|
|
||||||
function goto(urlOrName, vars) {
|
function goto(urlOrName, vars) {
|
||||||
const url = urlOrName.startsWith(baseUrl) ? urlOrName : href(urlOrName, vars);
|
const url = urlOrName.startsWith(baseUrl) ? urlOrName : href(urlOrName, vars);
|
||||||
|
|
||||||
@ -69,10 +70,12 @@ export function Router(baseUrl, routes, unmatched) {
|
|||||||
currentRoute = newRoute;
|
currentRoute = newRoute;
|
||||||
} else {
|
} else {
|
||||||
let onexit = currentRoute && currentRoute.name ? routes[currentRoute.name].onexit || nop : nop;
|
let onexit = currentRoute && currentRoute.name ? routes[currentRoute.name].onexit || nop : nop;
|
||||||
Promise.resolve(onexit(api, currentRoute, newRoute)).then(() => {
|
return Promise.resolve(onexit(api, currentRoute, newRoute))
|
||||||
reEnterHook = routes[routeMatch.name].onenter(api, newRoute);
|
.catch(() => {})
|
||||||
currentRoute = newRoute;
|
.then(() => {
|
||||||
});
|
reEnterHook = routes[routeMatch.name].onenter(api, newRoute);
|
||||||
|
currentRoute = newRoute;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else if (unmatched) {
|
} else if (unmatched) {
|
||||||
unmatched(api, url, currentRoute);
|
unmatched(api, url, currentRoute);
|
||||||
@ -111,16 +114,24 @@ export function Router(baseUrl, routes, unmatched) {
|
|||||||
return location.hash;
|
return location.hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
function listen(initialRoute) {
|
function _handler() {
|
||||||
|
goto(_location());
|
||||||
|
}
|
||||||
|
|
||||||
|
function start(initialRoute) {
|
||||||
if (listening) {
|
if (listening) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.addEventListener('hashchange', () => goto(_location()), false);
|
self.addEventListener('hashchange', _handler, false);
|
||||||
listening = true;
|
listening = true;
|
||||||
goto(_location() || initialRoute);
|
goto(_location() || initialRoute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function stop() {
|
||||||
|
self.removeEventListener('hashchange', _handler);
|
||||||
|
}
|
||||||
|
|
||||||
function current() {
|
function current() {
|
||||||
return currentRoute;
|
return currentRoute;
|
||||||
}
|
}
|
||||||
@ -128,7 +139,8 @@ export function Router(baseUrl, routes, unmatched) {
|
|||||||
const api = {
|
const api = {
|
||||||
goto,
|
goto,
|
||||||
href,
|
href,
|
||||||
listen,
|
start,
|
||||||
|
stop,
|
||||||
current
|
current
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user