summaryrefslogtreecommitdiff
path: root/addons/bus/static
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2018-11-29 20:06:16 +0100
committerChristophe Simonis <chs@odoo.com>2018-11-29 20:06:16 +0100
commitce4cc24621bf6430d7d3a2d469b375b59120c200 (patch)
tree3837b5fe41ff88b24136ab53c871bc01f965cab1 /addons/bus/static
parent4d7aa97da38e497fef31a06543bfa5d2c8785708 (diff)
parent82a1e1dcc33d7c123e50d3e1aacb5e127f57c521 (diff)
[MERGE] forward port branch 12.0 up to 82a1e1dcc33
Diffstat (limited to 'addons/bus/static')
-rw-r--r--addons/bus/static/src/js/crosstab_bus.js7
-rw-r--r--addons/bus/static/tests/bus_tests.js102
2 files changed, 106 insertions, 3 deletions
diff --git a/addons/bus/static/src/js/crosstab_bus.js b/addons/bus/static/src/js/crosstab_bus.js
index df050b91e4c..46643cad0de 100644
--- a/addons/bus/static/src/js/crosstab_bus.js
+++ b/addons/bus/static/src/js/crosstab_bus.js
@@ -105,7 +105,7 @@ var CrossTabBus = Longpolling.extend({
$(window).on('unload.' + this._id, this._onUnload.bind(this));
- if (!this._callLocalStorage('getItem', 'peers')) {
+ if (!this._callLocalStorage('getItem', 'master')) {
this._startElection();
}
@@ -252,6 +252,7 @@ var CrossTabBus = Longpolling.extend({
//we're next in queue. Electing as master
this.lastHeartbeat = now;
this._callLocalStorage('setItem', 'heartbeat', this.lastHeartbeat);
+ this._callLocalStorage('setItem', 'master', true);
this._isMasterTab = true;
this.startPolling();
this.trigger('become_master');
@@ -297,7 +298,7 @@ var CrossTabBus = Longpolling.extend({
var value = JSON.parse(e.newValue);
var key = e.key;
- if (this._isRegistered && key === this._generateKey('peers') && !value) {
+ if (this._isRegistered && key === this._generateKey('master') && !value) {
//master was unloaded
this._startElection();
}
@@ -341,7 +342,7 @@ var CrossTabBus = Longpolling.extend({
// unload master
if (this._isMasterTab) {
- this._callLocalStorage('removeItem', 'peers');
+ this._callLocalStorage('removeItem', 'master');
}
},
});
diff --git a/addons/bus/static/tests/bus_tests.js b/addons/bus/static/tests/bus_tests.js
index 3c81398c09a..c8c7eab2bd9 100644
--- a/addons/bus/static/tests/bus_tests.js
+++ b/addons/bus/static/tests/bus_tests.js
@@ -214,4 +214,106 @@ QUnit.module('Bus', {
}, 3);
});
+
+ QUnit.test('cross tab bus elect new master on master unload', function (assert) {
+ var done = assert.async();
+ assert.expect(8);
+
+ // master
+ var pollDeferredMaster = $.Deferred();
+
+ var parentMaster = new Widget();
+ testUtils.addMockEnvironment(parentMaster, {
+ data: {},
+ services: {
+ bus_service: BusService,
+ local_storage: LocalStorageServiceMock,
+ },
+ mockRPC: function (route, args) {
+ if (route === '/longpolling/poll') {
+ assert.step(['master', route, args.channels.join(',')]);
+
+ pollDeferredMaster = $.Deferred();
+ pollDeferredMaster.abort = (function () {
+ this.reject({message: "XmlHttpRequestError abort"}, $.Event());
+ }).bind(pollDeferredMaster);
+ return pollDeferredMaster;
+ }
+ return this._super.apply(this, arguments);
+ }
+ });
+
+ var master = new Widget(parentMaster);
+ master.appendTo($('#qunit-fixture'));
+
+ master.call('bus_service', 'onNotification', master, function (notifications) {
+ assert.step(['master', 'notification', notifications]);
+ });
+ master.call('bus_service', 'addChannel', 'lambda');
+
+ // slave
+ setTimeout(function () {
+ var parentSlave = new Widget();
+ var pollDeferredSlave = $.Deferred();
+ testUtils.addMockEnvironment(parentSlave, {
+ data: {},
+ services: {
+ bus_service: BusService,
+ local_storage: LocalStorageServiceMock,
+ },
+ mockRPC: function (route, args) {
+ if (route === '/longpolling/poll') {
+ assert.step(['slave', route, args.channels.join(',')]);
+
+ pollDeferredSlave = $.Deferred();
+ pollDeferredSlave.abort = (function () {
+ this.reject({message: "XmlHttpRequestError abort"}, $.Event());
+ }).bind(pollDeferredSlave);
+ return pollDeferredSlave;
+ }
+ return this._super.apply(this, arguments);
+ }
+ });
+
+ var slave = new Widget(parentSlave);
+ slave.appendTo($('#qunit-fixture'));
+
+ slave.call('bus_service', 'onNotification', slave, function (notifications) {
+ assert.step(['slave', 'notification', notifications]);
+ });
+ slave.call('bus_service', 'addChannel', 'lambda');
+
+ pollDeferredMaster.resolve([{
+ id: 1,
+ channel: 'lambda',
+ message: 'beta',
+ }]);
+
+ // simulate unloading master
+ master.call('bus_service', '_onUnload');
+
+ pollDeferredSlave.resolve([{
+ id: 2,
+ channel: 'lambda',
+ message: 'gamma',
+ }]);
+
+ assert.verifySteps([
+ ["master", "/longpolling/poll", "lambda"],
+ ["master", "notification", [["lambda", "beta"]]],
+ ["slave", "notification", [["lambda", "beta"]]],
+ ["master", "/longpolling/poll", "lambda"],
+ ["slave", "/longpolling/poll", "lambda"],
+ ["slave", "notification", [["lambda", "gamma"]]],
+ ["slave", "/longpolling/poll", "lambda"],
+ ]);
+
+ parentMaster.destroy();
+ parentSlave.destroy();
+
+ done();
+
+ }, 3);
+ });
+
});});