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

View File

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

View File

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

View File

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