Refactored browser history management

This commit is contained in:
Camel Aissani 2016-07-23 12:31:40 +02:00
parent 5d75c4a259
commit f15cfed2e9
4 changed files with 38 additions and 29 deletions

View File

@ -83,7 +83,7 @@ export default class Application {
window.onpopstate = (event) => { window.onpopstate = (event) => {
if (event.state) { if (event.state) {
const {response, request} = event.state; const {request, response} = event.state;
const currentRoutes = this._routes(request.uri, request.method); const currentRoutes = this._routes(request.uri, request.method);
this._callMiddlewareEntered(currentRoutes, request); this._callMiddlewareEntered(currentRoutes, request);
@ -311,7 +311,9 @@ export default class Application {
* @private * @private
*/ */
_fetch({method, uri, headers, data, history}, resolve, reject) { _fetch(request, resolve, reject) {
let {method, uri, headers, data, history} = request;
const httpMethodTransformer = this.get(`http ${method} transformer`); const httpMethodTransformer = this.get(`http ${method} transformer`);
if (httpMethodTransformer) { if (httpMethodTransformer) {
uri = httpMethodTransformer.uri ? httpMethodTransformer.uri({uri, headers, data}) : uri; uri = httpMethodTransformer.uri ? httpMethodTransformer.uri({uri, headers, data}) : uri;
@ -326,27 +328,23 @@ export default class Application {
const currentRoutes = this._routes(uri, method); const currentRoutes = this._routes(uri, method);
// calls middleware entered method // calls middleware entered method
this._callMiddlewareEntered(currentRoutes, {method, uri, headers, data}); this._callMiddlewareEntered(currentRoutes, request);
// invokes http request // invokes http request
this.settings.get('http requester').fetch({method, uri, headers, data}, this.settings.get('http requester').fetch(request,
(request, response) => { (req, res) => {
if (history) { if (history) {
if (history.state) { window.history.pushState({request: req, response: res}, history.title, history.uri);
response.historyState = history.state;
}
history.state = {request, response};
window.history.pushState(history.state, history.title, history.uri);
} }
this._callMiddlewareUpdated(currentRoutes, request, response); this._callMiddlewareUpdated(currentRoutes, req, res);
if (resolve) { if (resolve) {
resolve(request, response); resolve(req, res);
} }
}, },
(request, response) => { (req, res) => {
this._callMiddlewareFailed(currentRoutes, request, response); this._callMiddlewareFailed(currentRoutes, req, res);
if (reject) { if (reject) {
reject(request, response); reject(req, res);
} }
}); });
} }

View File

@ -14,10 +14,12 @@ export default class Requester {
* @private * @private
*/ */
fetch({method, uri, headers, data}, resolve, reject) { fetch(request, resolve, reject) {
const {method, uri, headers, data, history} = request;
const success = (responseText) => { const success = (responseText) => {
resolve( resolve(
{method, uri, headers, data}, request,
{status: 200, statusText: 'OK', responseText} {status: 200, statusText: 'OK', responseText}
); );
}; };
@ -25,7 +27,7 @@ export default class Requester {
const fail = ({status, statusText, errorThrown}) => { const fail = ({status, statusText, errorThrown}) => {
const errors = this._analyzeErrors({status, statusText, errorThrown}); const errors = this._analyzeErrors({status, statusText, errorThrown});
reject( reject(
{method, uri, headers, data}, request,
{status, statusText, errorThrown, errors} {status, statusText, errorThrown, errors}
); );
}; };

View File

@ -11,7 +11,7 @@ import Requester from './requester';
* @private * @private
*/ */
export default class { export default class Settings {
/** /**

View File

@ -193,10 +193,11 @@ describe('Application', () => {
}); });
it('history management without state object', (done) => { it('history management without state object', (done) => {
let historyObj;
const requester = new Requester(); const requester = new Requester();
sinon.stub(requester, 'fetch', ({uri, method, headers, data}, resolve, reject) => { sinon.stub(requester, 'fetch', ({uri, method, headers, data, history}, resolve, reject) => {
resolve( resolve(
{uri, method, headers, data}, {uri, method, headers, data, history},
{status: 200, statusText: 'OK', responseText:''} {status: 200, statusText: 'OK', responseText:''}
); );
}); });
@ -205,7 +206,9 @@ describe('Application', () => {
const app = frontexpress(); const app = frontexpress();
const m = frontexpress.Middleware(); const m = frontexpress.Middleware();
const spy_middleware = sinon.stub(m, 'updated'); const spy_middleware = sinon.stub(m, 'updated', (req, res) => {
historyObj = req.history;
});
app.set('http requester', requester); app.set('http requester', requester);
app.use('/api/route1', m); app.use('/api/route1', m);
@ -228,17 +231,20 @@ describe('Application', () => {
window.history.forward(); window.history.forward();
assert(spy_onpopstate.calledOnce); assert(spy_onpopstate.calledOnce);
assert(spy_middleware.calledOnce); assert(spy_middleware.calledOnce);
assert(historyObj);
assert(historyObj.uri === '/route1');
assert(historyObj.title === 'route1');
done(); done();
}); });
}); });
it('history management with state object', (done) => { it('history management with state object', (done) => {
let stateObj; let historyObj;
const requester = new Requester(); const requester = new Requester();
sinon.stub(requester, 'fetch', ({uri, method, headers, data}, resolve, reject) => { sinon.stub(requester, 'fetch', ({uri, method, headers, data, history}, resolve, reject) => {
resolve( resolve(
{uri, method, headers, data}, {uri, method, headers, data, history},
{status: 200, statusText: 'OK', responseText:''} {status: 200, statusText: 'OK', responseText:''}
); );
}); });
@ -248,7 +254,7 @@ describe('Application', () => {
const app = frontexpress(); const app = frontexpress();
const m = frontexpress.Middleware(); const m = frontexpress.Middleware();
const spy_middleware = sinon.stub(m, 'updated', (req, res) => { const spy_middleware = sinon.stub(m, 'updated', (req, res) => {
stateObj = res.historyState; historyObj = req.history;
}); });
app.set('http requester', requester); app.set('http requester', requester);
@ -273,9 +279,12 @@ describe('Application', () => {
window.history.forward(); window.history.forward();
assert(spy_onpopstate.calledOnce); assert(spy_onpopstate.calledOnce);
assert(spy_middleware.calledOnce); assert(spy_middleware.calledOnce);
assert(stateObj); assert(historyObj);
assert(stateObj.a === 'b'); assert(historyObj.uri === '/route1');
assert(stateObj.c === 'd'); assert(historyObj.title === 'route1');
assert(historyObj.state);
assert(historyObj.state.a === 'b');
assert(historyObj.state.c === 'd');
done(); done();
}); });