diff --git a/addons/mail/static/src/js/discuss.js b/addons/mail/static/src/js/discuss.js index 7f297f76298..3ac9e3b0ed5 100644 --- a/addons/mail/static/src/js/discuss.js +++ b/addons/mail/static/src/js/discuss.js @@ -170,18 +170,20 @@ var Discuss = AbstractAction.extend(ControlPanelMixin, { this.basicComposer.on('input_focused', this, this._onComposerFocused); this.extendedComposer.on('post_message', this, this._onPostMessage); this.extendedComposer.on('input_focused', this, this._onComposerFocused); + this._renderButtons(); var defs = []; - defs.push(this._renderButtons()); defs.push(this._renderThread()); defs.push(this.basicComposer.appendTo(this.$('.o_mail_chat_content'))); defs.push(this.extendedComposer.appendTo(this.$('.o_mail_chat_content'))); defs.push(this._renderSearchView()); - return $.when.apply($, defs) - .then(this._setChannel.bind(this, defaultChannel)) - .then(this._updateChannels.bind(this)) + return this.alive($.when.apply($, defs)) .then(function () { + return self.alive(self._setChannel(defaultChannel)); + }) + .then(function () { + self._updateChannels(); self._startListening(); self.thread.$el.on("scroll", null, _.debounce(function () { if (self.thread.get_scrolltop() < 20 && @@ -413,7 +415,7 @@ var Discuss = AbstractAction.extend(ControlPanelMixin, { disable_groupby: true, }; this.searchview = new SearchView(this, this.dataset, this.fields_view, options); - return this.searchview.appendTo($("
")).then(function () { + return this.alive(this.searchview.appendTo($("
"))).then(function () { self.$searchview_buttons = self.searchview.$buttons.contents(); // manually call do_search to generate the initial domain and filter // the messages in the default channel diff --git a/addons/mail/static/src/js/discuss_mobile.js b/addons/mail/static/src/js/discuss_mobile.js index b427ab4b98c..556651ec67e 100644 --- a/addons/mail/static/src/js/discuss_mobile.js +++ b/addons/mail/static/src/js/discuss_mobile.js @@ -105,9 +105,9 @@ Discuss.include({ */ _setChannel: function (channel) { if (channel.type !== 'static') { - this.call('chat_manager', 'detachChannel', channel.id); + return this.call('chat_manager', 'detachChannel', channel.id); } else { - this._super.apply(this, arguments); + return this._super.apply(this, arguments); } }, /** diff --git a/addons/mail/static/tests/discuss_tests.js b/addons/mail/static/tests/discuss_tests.js index 0d6ae016e51..8d3ac86824e 100644 --- a/addons/mail/static/tests/discuss_tests.js +++ b/addons/mail/static/tests/discuss_tests.js @@ -1,11 +1,13 @@ odoo.define('mail.discuss_test', function (require) { "use strict"; +var Discuss = require('mail.chat_discuss'); var ChatManager = require('mail.ChatManager'); var mailTestUtils = require('mail.testUtils'); var Bus = require('web.Bus'); var concurrency = require('web.concurrency'); +var SearchView = require('web.SearchView'); var testUtils = require('web.test_utils'); var createBusService = mailTestUtils.createBusService; @@ -457,6 +459,86 @@ QUnit.test('"Unstar all" button should reset the starred counter', function (ass }); }); +QUnit.test('do not crash when destroyed before start is completed', function (assert) { + assert.expect(3); + var discuss; + + testUtils.patch(Discuss, { + init: function () { + discuss = this; + this._super.apply(this, arguments); + }, + }); + + createDiscuss({ + id: 1, + context: {}, + params: {}, + data: this.data, + services: this.services, + mockRPC: function (route, args) { + if (args.method) { + assert.step(args.method); + } + var result = this._super.apply(this, arguments); + if (args.method === 'message_fetch') { + discuss.destroy(); + } + return result; + }, + }); + + assert.verifySteps([ + "load_views", + "message_fetch" + ]); + + testUtils.unpatch(Discuss); +}); + +QUnit.test('do not crash when destroyed between start en end of _renderSearchView', function (assert) { + assert.expect(2); + var discuss; + + testUtils.patch(Discuss, { + init: function () { + discuss = this; + this._super.apply(this, arguments); + }, + }); + + var def = $.Deferred(); + + testUtils.patch(SearchView, { + willStart: function () { + var result = this._super.apply(this, arguments); + return def.then($.when(result)); + }, + }); + + createDiscuss({ + id: 1, + context: {}, + params: {}, + data: this.data, + services: this.services, + mockRPC: function (route, args) { + if (args.method) { + assert.step(args.method); + } + return this._super.apply(this, arguments); + }, + }); + + discuss.destroy(); + def.resolve(); + assert.verifySteps([ + "load_views", + ]); + + testUtils.unpatch(Discuss); + testUtils.unpatch(SearchView); +}); }); }); diff --git a/addons/mail/static/tests/helpers/test_utils.js b/addons/mail/static/tests/helpers/test_utils.js index f7292c7a67e..3382fa90dd0 100644 --- a/addons/mail/static/tests/helpers/test_utils.js +++ b/addons/mail/static/tests/helpers/test_utils.js @@ -78,7 +78,6 @@ function createDiscuss(params) { var selector = params.debug ? 'body' : '#qunit-fixture'; var controlPanel = new ControlPanel(parent); controlPanel.appendTo($(selector)); - discuss.appendTo($(selector)); // override 'destroy' of discuss so that it calls 'destroy' on the parent // instead, which is the parent of discuss and the mockServer. @@ -92,7 +91,7 @@ function createDiscuss(params) { // link the view to the control panel discuss.set_cp_bus(controlPanel.get_bus()); - return discuss.call('chat_manager', 'isReady').then(function () { + return discuss.appendTo($(selector)).then(function () { return discuss; }); }