Skip to content
This repository has been archived by the owner on Jul 15, 2019. It is now read-only.

Commit

Permalink
Merge pull request #76 from yahoo/firefox
Browse files Browse the repository at this point in the history
fix TypeError for firefox 35.0.1
  • Loading branch information
lingyan committed Feb 24, 2015
2 parents f3f4165 + 9b0b2d3 commit 0d0078b
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 97 deletions.
22 changes: 20 additions & 2 deletions lib/History.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,16 @@ History.prototype = {
pushState: function (state, title, url) {
var win = this.win;
if (this._hasPushState) {
win.history.pushState.apply(win.history, arguments);
try {
// not calling pushState(state, title, url), because
// some browsers update url with '/undefined' if url is undefined
win.history.pushState.apply(win.history, arguments);
} catch (error) {
// firefox 35 requires 3 args for pushState
if (arguments.length < 3) {
win.history.pushState(state, title, url);
}
}
} else if (url) {
win.location.href = url;
}
Expand All @@ -90,7 +99,16 @@ History.prototype = {
replaceState: function (state, title, url) {
var win = this.win;
if (this._hasPushState) {
win.history.replaceState.apply(win.history, arguments);
try {
// not calling pushState(state, title, url), because
// some browsers update url with '/undefined' if url is undefined
win.history.replaceState.apply(win.history, arguments);
} catch (error) {
// firefox 35 requires 3 args for replaceState
if (arguments.length < 3) {
win.history.replaceState(state, title, url);
}
}
} else if (url) {
win.location.replace(url);
}
Expand Down
90 changes: 90 additions & 0 deletions tests/mocks/mockWindow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
module.exports = function mockWindow(testResult) {
return {
HTML5: {
history: {
pushState: function (state, title, url) {
testResult.pushState = {
state: state,
title: title,
url: url
};
},
replaceState: function (state, title, url) {
testResult.replaceState = {
state: state,
title: title,
url: url
};
}
},
addEventListener: function (evt, listener) {
testResult.addEventListener = {
evt: evt,
listener: listener
};
},
removeEventListener: function (evt, listener) {
testResult.removeEventListener = {
evt: evt,
listener: listener
};
}
},
Firefox: {
history: {
pushState: function (state, title, url) {
if (arguments.length < 3) {
throw new TypeError("Not enough arguments to History.pushState.");
}
testResult.pushState = {
state: state,
title: title,
url: url
};
},
replaceState: function (state, title, url) {
if (arguments.length < 3) {
throw new TypeError("Not enough arguments to History.replaceState.");
}
testResult.pushState = {
state: state,
title: title,
url: url
};
testResult.replaceState = {
state: state,
title: title,
url: url
};
}
},
addEventListener: function (evt, listener) {
testResult.addEventListener = {
evt: evt,
listener: listener
};
},
removeEventListener: function (evt, listener) {
testResult.removeEventListener = {
evt: evt,
listener: listener
};
}
},
OLD: {
addEventListener: function (evt, listener) {
testResult.addEventListener = {
evt: evt,
listener: listener
};
},
removeEventListener: function (evt, listener) {
testResult.removeEventListener = {
evt: evt,
listener: listener
};
}
}
};

};
83 changes: 37 additions & 46 deletions tests/unit/lib/History-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,57 +9,12 @@ var History = require('../../../lib/History'),
windowMock,
testResult;

windowMock = {
HTML5: {
history: {
pushState: function (state, title, url) {
testResult.pushState = {
state: state,
title: title,
url: url
};
},
replaceState: function (state, title, url) {
testResult.replaceState = {
state: state,
title: title,
url: url
};
}
},
addEventListener: function (evt, listener) {
testResult.addEventListener = {
evt: evt,
listener: listener
};
},
removeEventListener: function (evt, listener) {
testResult.removeEventListener = {
evt: evt,
listener: listener
};
}
},
OLD: {
addEventListener: function (evt, listener) {
testResult.addEventListener = {
evt: evt,
listener: listener
};
},
removeEventListener: function (evt, listener) {
testResult.removeEventListener = {
evt: evt,
listener: listener
};
}
}
};

describe('History', function () {

beforeEach(function () {
testResult = {};
windowMock = require('../../mocks/mockWindow')(testResult);
});

describe('constructor', function () {
Expand Down Expand Up @@ -214,6 +169,24 @@ describe('History', function () {
expect(testResult.pushState.title).to.equal('t');
expect(testResult.pushState.url).to.equal('/url?a=b&x=y');
});
it ('has pushState, Firefox', function () {
var history = new History({win: windowMock.Firefox});

history.pushState({foo: 'bar'});
expect(testResult.pushState.state).to.eql({foo: 'bar'});
expect(testResult.pushState.title).to.equal(undefined);
expect(testResult.pushState.url).to.equal(undefined);

history.pushState({foo: 'bar'}, 't');
expect(testResult.pushState.state).to.eql({foo: 'bar'});
expect(testResult.pushState.title).to.equal('t');
expect(testResult.pushState.url).to.equal(undefined);

history.pushState({foo: 'bar'}, 't', '/url');
expect(testResult.pushState.state).to.eql({foo: 'bar'});
expect(testResult.pushState.title).to.equal('t');
expect(testResult.pushState.url).to.equal('/url');
});
it ('no pushState', function () {
var win = _.extend(windowMock.OLD, {
location: {}
Expand Down Expand Up @@ -255,6 +228,24 @@ describe('History', function () {
expect(testResult.replaceState.title).to.equal('t');
expect(testResult.replaceState.url).to.equal('/url?a=b&x=y', 'url has query');
});
it ('has pushState, Firefox', function () {
var history = new History({win: windowMock.Firefox});

history.replaceState({foo: 'bar'});
expect(testResult.replaceState.state).to.eql({foo: 'bar'});
expect(testResult.replaceState.title).to.equal(undefined);
expect(testResult.replaceState.url).to.equal(undefined);

history.replaceState({foo: 'bar'}, 't');
expect(testResult.replaceState.state).to.eql({foo: 'bar'});
expect(testResult.replaceState.title).to.equal('t');
expect(testResult.replaceState.url).to.equal(undefined);

history.replaceState({foo: 'bar'}, 't', '/url');
expect(testResult.replaceState.state).to.eql({foo: 'bar'});
expect(testResult.replaceState.title).to.equal('t');
expect(testResult.replaceState.url).to.equal('/url');
});
it ('no pushState', function () {
var win = _.extend(windowMock.OLD, {
location: {
Expand Down
74 changes: 27 additions & 47 deletions tests/unit/utils/HistoryWithHash-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,57 +9,11 @@ var HistoryWithHash = require('../../../utils/HistoryWithHash'),
windowMock,
testResult;

windowMock = {
HTML5: {
history: {
pushState: function (state, title, url) {
testResult.pushState = {
state: state,
title: title,
url: url
};
},
replaceState: function (state, title, url) {
testResult.replaceState = {
state: state,
title: title,
url: url
};
}
},
addEventListener: function (evt, listener) {
testResult.addEventListener = {
evt: evt,
listener: listener
};
},
removeEventListener: function (evt, listener) {
testResult.removeEventListener = {
evt: evt,
listener: listener
};
}
},
OLD: {
addEventListener: function (evt, listener) {
testResult.addEventListener = {
evt: evt,
listener: listener
};
},
removeEventListener: function (evt, listener) {
testResult.removeEventListener = {
evt: evt,
listener: listener
};
}
}
};

describe('HistoryWithHash', function () {

beforeEach(function () {
testResult = {};
windowMock = require('../../mocks/mockWindow')(testResult);
});

describe('constructor', function () {
Expand Down Expand Up @@ -238,6 +192,19 @@ describe('HistoryWithHash', function () {
expect(testResult.pushState.title).to.equal('t');
expect(testResult.pushState.url).to.equal('/url?a=b&x=y');
});
it ('useHashRoute=false; has pushState; Firefox', function () {
var history = new HistoryWithHash({win: windowMock.Firefox});

history.pushState({foo: 'bar'});
expect(testResult.pushState.state).to.eql({foo: 'bar'});
expect(testResult.pushState.title).to.equal(undefined);
expect(testResult.pushState.url).to.equal(undefined);

history.pushState({foo: 'bar'}, 't', '/url');
expect(testResult.pushState.state).to.eql({foo: 'bar'});
expect(testResult.pushState.title).to.equal('t');
expect(testResult.pushState.url).to.equal('/url');
});
it ('useHashRoute=false; no pushState', function () {
var win = _.extend({}, windowMock.OLD, {location: {}});
var history = new HistoryWithHash({
Expand Down Expand Up @@ -330,6 +297,19 @@ describe('HistoryWithHash', function () {
expect(testResult.replaceState.title).to.equal('t');
expect(testResult.replaceState.url).to.equal('/url?a=b&x=y', 'url has query');
});
it ('useHashRouter=false; has pushState; Firefox', function () {
var history = new HistoryWithHash({win: windowMock.Firefox});

history.replaceState({foo: 'bar'});
expect(testResult.replaceState.state).to.eql({foo: 'bar'});
expect(testResult.replaceState.title).to.equal(undefined);
expect(testResult.replaceState.url).to.equal(undefined);

history.replaceState({foo: 'bar'}, 't', '/url');
expect(testResult.replaceState.state).to.eql({foo: 'bar'});
expect(testResult.replaceState.title).to.equal('t');
expect(testResult.replaceState.url).to.equal('/url');
});
it ('useHashRouter=false; no pushState', function () {
var win = _.extend({}, windowMock.OLD, {
location: {
Expand Down
22 changes: 20 additions & 2 deletions utils/HistoryWithHash.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,16 @@ HistoryWithHash.prototype = {
}
} else {
if (this._hasPushState) {
history.pushState.apply(history, arguments);
try {
// not calling pushState(state, title, url), because
// some browsers update url with '/undefined' if url is undefined
history.pushState.apply(history, arguments);
} catch (error) {
// firefox 35 requires 3 args for pushState
if (arguments.length < 3) {
history.pushState(state, title, url);
}
}
} else if (url) {
location.href = url;
}
Expand Down Expand Up @@ -170,7 +179,16 @@ HistoryWithHash.prototype = {
}
} else {
if (this._hasPushState) {
history.replaceState.apply(history, arguments);
try {
// not calling replaceState(state, title, url), because
// some browsers update url with '/undefined' if url is undefined
history.replaceState.apply(history, arguments);
} catch (error) {
// firefox 35 requires 3 args for replaceState
if (arguments.length < 3) {
history.replaceState(state, title, url);
}
}
} else if (url) {
location.replace(url);
}
Expand Down

0 comments on commit 0d0078b

Please sign in to comment.