summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Schippefilt <vsc@odoo.com>2019-03-06 14:02:19 +0100
committerAaron Bohy <aab@odoo.com>2019-03-06 20:07:17 +0100
commit1ae64793fa489b2c1d07408cd9671bc7126f78fa (patch)
tree23d908222f4e705b908dd23ef3823c26daf3baf0
parentaa900d976f6fbb10f3940639b4d918d31a7556ca (diff)
[REF] mail: adapt code after jQuery update
Part of task 1896658 Co-authored-by: Aaron Bohy <aab@odoo.com> Co-authored-by: Christophe Matthieu <chm@odoo.com> Co-authored-by: Mathieu Duckerts-Antoine <dam@odoo.com> Co-authored-by: David Monjoie <dmo@odoo.com> Co-authored-by: Martin Geubelle <mge@odoo.com> Co-authored-by: svs-odoo <svs@odoo.com> Co-authored-by: Vincent Schippefilt <vsc@odoo.com>
-rw-r--r--addons/mail/static/src/js/activity.js22
-rw-r--r--addons/mail/static/src/js/chatter.js53
-rw-r--r--addons/mail/static/src/js/composers/basic_composer.js55
-rw-r--r--addons/mail/static/src/js/composers/chatter_composer.js256
-rw-r--r--addons/mail/static/src/js/composers/extended_composer.js2
-rw-r--r--addons/mail/static/src/js/composers/mention_manager.js2
-rw-r--r--addons/mail/static/src/js/discuss.js27
-rw-r--r--addons/mail/static/src/js/discuss_mobile.js4
-rw-r--r--addons/mail/static/src/js/document_viewer.js4
-rw-r--r--addons/mail/static/src/js/followers.js38
-rw-r--r--addons/mail/static/src/js/form_renderer.js12
-rw-r--r--addons/mail/static/src/js/many2many_tags_email.js58
-rw-r--r--addons/mail/static/src/js/models/messages/message.js2
-rw-r--r--addons/mail/static/src/js/models/threads/abstract_thread.js14
-rw-r--r--addons/mail/static/src/js/models/threads/channel.js32
-rw-r--r--addons/mail/static/src/js/models/threads/document_thread.js14
-rw-r--r--addons/mail/static/src/js/models/threads/livechat.js2
-rw-r--r--addons/mail/static/src/js/models/threads/mailbox.js6
-rw-r--r--addons/mail/static/src/js/models/threads/mixins/thread_typing_mixin.js4
-rw-r--r--addons/mail/static/src/js/models/threads/multi_user_channel.js2
-rw-r--r--addons/mail/static/src/js/models/threads/searchable_thread.js4
-rw-r--r--addons/mail/static/src/js/models/threads/thread.js22
-rw-r--r--addons/mail/static/src/js/models/threads/two_user_channel.js2
-rw-r--r--addons/mail/static/src/js/services/mail_document_thread_manager.js2
-rw-r--r--addons/mail/static/src/js/services/mail_manager.js152
-rw-r--r--addons/mail/static/src/js/services/mail_notification_manager.js29
-rw-r--r--addons/mail/static/src/js/services/mail_status_manager.js2
-rw-r--r--addons/mail/static/src/js/services/mail_window_manager.js27
-rw-r--r--addons/mail/static/src/js/systray/systray_activity_menu.js2
-rw-r--r--addons/mail/static/src/js/systray/systray_messaging_menu.js4
-rw-r--r--addons/mail/static/src/js/thread_field.js14
-rw-r--r--addons/mail/static/src/js/thread_widget.js10
-rw-r--r--addons/mail/static/src/js/thread_windows/abstract_thread_window.js2
-rw-r--r--addons/mail/static/src/js/thread_windows/thread_window.js4
-rw-r--r--addons/mail/static/src/js/views/activity/activity_model.js6
-rw-r--r--addons/mail/static/src/js/views/activity/activity_renderer.js33
-rw-r--r--addons/mail/static/tests/activity_tests.js64
-rw-r--r--addons/mail/static/tests/chatter_tests.js576
-rw-r--r--addons/mail/static/tests/discuss_mobile_tests.js90
-rw-r--r--addons/mail/static/tests/discuss_moderation_tests.js101
-rw-r--r--addons/mail/static/tests/discuss_seen_indicator_tests.js805
-rw-r--r--addons/mail/static/tests/discuss_tests.js1274
-rw-r--r--addons/mail/static/tests/discuss_typing_notification_tests.js697
-rw-r--r--addons/mail/static/tests/document_thread_window_tests.js73
-rw-r--r--addons/mail/static/tests/document_viewer_tests.js45
-rw-r--r--addons/mail/static/tests/helpers/mock_server.js26
-rw-r--r--addons/mail/static/tests/helpers/test_utils.js6
-rw-r--r--addons/mail/static/tests/mail_status_manager_tests.js27
-rw-r--r--addons/mail/static/tests/models/cc_throttle_function_tests.js20
-rw-r--r--addons/mail/static/tests/models/timer_tests.js35
-rw-r--r--addons/mail/static/tests/systray/systray_activity_menu_tests.js45
-rw-r--r--addons/mail/static/tests/systray/systray_messaging_menu_mail_failure_tests.js18
-rw-r--r--addons/mail/static/tests/systray/systray_messaging_menu_tests.js138
-rw-r--r--addons/mail/static/tests/thread_window/basic_thread_window_tests.js109
-rw-r--r--addons/mail/static/tests/thread_window/blank_thread_window_tests.js85
-rw-r--r--addons/mail/static/tests/thread_window/hidden_thread_window_tests.js15
-rw-r--r--addons/mail/static/tests/thread_window/moderation_thread_window_tests.js5
-rw-r--r--addons/mail/static/tests/thread_window/typing_thread_window_tests.js13
-rw-r--r--addons/mail/static/tests/tools/debug_manager_tests.js9
59 files changed, 2588 insertions, 2612 deletions
diff --git a/addons/mail/static/src/js/activity.js b/addons/mail/static/src/js/activity.js
index 68ff4b0b86f..607f1b8c553 100644
--- a/addons/mail/static/src/js/activity.js
+++ b/addons/mail/static/src/js/activity.js
@@ -25,11 +25,11 @@ var _t = core._t;
*
* @param {Widget} self a widget instance that can perform RPCs
* @param {Array} ids the ids of activities to read
- * @return {Deferred<Array>} resolved with the activities
+ * @return {Promise<Array>} resolved with the activities
*/
function _readActivities(self, ids) {
if (!ids.length) {
- return $.when([]);
+ return Promise.resolve([]);
}
var context = self.getSession().user_context;
if (self.record && !_.isEmpty(self.record.getContext())) {
@@ -64,7 +64,7 @@ BasicModel.include({
* @private
* @param {Object} record - an element from the localData
* @param {string} fieldName
- * @return {Deferred<Array>} resolved with the activities
+ * @return {Promise<Array>} resolved with the activities
*/
_fetchSpecialActivity: function (record, fieldName) {
var localID = (record._changes && fieldName in record._changes) ?
@@ -144,7 +144,7 @@ var BasicActivity = AbstractField.extend({
/**
* @param {integer} previousActivityTypeID
- * @return {$.Promise}
+ * @return {Promise}
*/
scheduleActivity: function () {
var callback = this._reload.bind(this, { activity: true, thread: true });
@@ -213,7 +213,7 @@ var BasicActivity = AbstractField.extend({
* @param {integer} id
* @param {integer} previousActivityTypeID
* @param {function} callback
- * @return {$.Deferred}
+ * @return {Promise}
*/
_openActivityForm: function (id, callback) {
var action = {
@@ -237,7 +237,7 @@ var BasicActivity = AbstractField.extend({
* @param {integer} activityID
* @param {string} feedback
* @param {integer[]} attachmentIds
- * @return {$.Promise}
+ * @return {Promise}
*/
_sendActivityFeedback: function (activityID, feedback, attachmentIds) {
return this._rpc({
@@ -303,7 +303,7 @@ var BasicActivity = AbstractField.extend({
/**
* @private
* @param {MouseEvent} ev
- * @returns {$.Promise}
+ * @returns {Promise}
*/
_onEditActivity: function (ev) {
ev.preventDefault();
@@ -449,7 +449,7 @@ var BasicActivity = AbstractField.extend({
/**
* @private
* @param {MouseEvent} ev
- * @returns {$.Deferred}
+ * @returns {Promise}
*/
_onPreviewMailTemplate: function (ev) {
ev.stopPropagation();
@@ -477,7 +477,7 @@ var BasicActivity = AbstractField.extend({
/**
* @private
* @param {MouseEvent} ev
- * @returns {$.Promise}
+ * @returns {Promise}
*/
_onSendMailTemplate: function (ev) {
ev.stopPropagation();
@@ -493,7 +493,7 @@ var BasicActivity = AbstractField.extend({
/**
* @private
* @param {MouseEvent} ev
- * @returns {$.Deferred}
+ * @returns {Promise}
*/
_onScheduleActivity: function (ev) {
ev.preventDefault();
@@ -504,7 +504,7 @@ var BasicActivity = AbstractField.extend({
* @private
* @param {MouseEvent} ev
* @param {Object} options
- * @returns {$.Promise}
+ * @returns {Promise}
*/
_onUnlinkActivity: function (ev, options) {
ev.preventDefault();
diff --git a/addons/mail/static/src/js/chatter.js b/addons/mail/static/src/js/chatter.js
index 72971fbeee9..397ae2c8a16 100644
--- a/addons/mail/static/src/js/chatter.js
+++ b/addons/mail/static/src/js/chatter.js
@@ -103,7 +103,7 @@ var Chatter = Widget.extend({
}));
// start and append the widgets
var fieldDefs = _.invoke(this.fields, 'appendTo', $('<div>'));
- var def = this._dp.add($.when.apply($, fieldDefs));
+ var def = this._dp.add(Promise.all(fieldDefs));
this._render(def).then(this._updateMentionSuggestions.bind(this));
return this._super.apply(this, arguments);
@@ -153,7 +153,7 @@ var Chatter = Widget.extend({
fieldsToReset = this.fields;
}
var fieldDefs = _.invoke(fieldsToReset, 'reset', record);
- var def = this._dp.add($.when.apply($, fieldDefs));
+ var def = this._dp.add(Promise.all(fieldDefs));
this._render(def).then(function () {
self.$el.height('auto');
self._updateMentionSuggestions();
@@ -203,17 +203,18 @@ var Chatter = Widget.extend({
* Discard changes on the record.
*
* @private
- * @returns {$.Deferred} resolved if successfully discarding changes on
+ * @returns {Promise} resolved if successfully discarding changes on
* the record, rejected otherwise
*/
_discardChanges: function () {
- var def = $.Deferred();
- this.trigger_up('discard_changes', {
- recordID: this.record.id,
- onSuccess: def.resolve.bind(def),
- onFailure: def.reject.bind(def),
+ var self = this;
+ return new Promise(function (resolve, reject) {
+ self.trigger_up('discard_changes', {
+ recordID: self.record.id,
+ onSuccess: resolve,
+ onFailure: reject,
+ });
});
- return def;
},
/**
* Discard changes on the record if the message will reload the record
@@ -221,14 +222,14 @@ var Chatter = Widget.extend({
*
* @private
* @param {Object} messageData
- * @return {$.Deferred} resolved if no reload or proceed to discard the
+ * @return {Promise} resolved if no reload or proceed to discard the
* changes on the record, rejected otherwise
*/
_discardOnReload: function (messageData) {
if (this._reloadAfterPost(messageData)) {
return this._discardChanges();
}
- return $.when();
+ return Promise.resolve();
},
/**
* @private
@@ -323,7 +324,7 @@ var Chatter = Widget.extend({
self._reloadAttachmentBox();
self.trigger_up('reload', {fieldNames: ['message_attachment_count'], keepChanges: true});
}
- }).fail(function () {
+ }).guardedCatch(function () {
self._enableComposer();
});
});
@@ -375,9 +376,9 @@ var Chatter = Widget.extend({
_render: function (def) {
// the rendering of the chatter is aynchronous: relational data of its fields needs to be
// fetched (in some case, it might be synchronous as they hold an internal cache).
- // this function takes a deferred as argument, which is resolved once all fields have
+ // this function takes a promise as argument, which is resolved once all fields have
// fetched their data
- // this function appends the fields where they should be once the given deferred is resolved
+ // this function appends the fields where they should be once the given promise is resolved
// and if it takes more than 500ms, displays a spinner to indicate that it is loading
var self = this;
@@ -385,6 +386,11 @@ var Chatter = Widget.extend({
concurrency.rejectAfter(concurrency.delay(500), def).then(function () {
$spinner.appendTo(self.$el);
});
+ var always = function () {
+ // disable widgets in create mode, otherwise enable
+ self._isCreateMode ? self._disableChatter() : self._enableChatter();
+ $spinner.remove();
+ };
return def.then(function () {
if (self.fields.activity) {
@@ -400,11 +406,7 @@ var Chatter = Widget.extend({
if (self.fields.thread) {
self.fields.thread.$el.appendTo(self.$el);
}
- }).always(function () {
- // disable widgets in create mode, otherwise enable
- self._isCreateMode ? self._disableChatter() : self._enableChatter();
- $spinner.remove();
- });
+ }).then(always).guardedCatch(always);
},
/**
* @private
@@ -517,7 +519,7 @@ var Chatter = Widget.extend({
if (!this._areAttachmentsLoaded) {
def = this._fetchAttachments();
}
- $.when(def).then(this._openAttachmentBox.bind(this));
+ Promise.resolve(def).then(this._openAttachmentBox.bind(this));
}
},
/**
@@ -534,10 +536,10 @@ var Chatter = Widget.extend({
_onOpenComposerMessage: function () {
var self = this;
if (!this.suggested_partners_def) {
- this.suggested_partners_def = $.Deferred();
- var method = 'message_get_suggested_recipients';
- var args = [[this.context.default_res_id], this.context];
- this._rpc({model: this.record.model, method: method, args: args})
+ this.suggested_partners_def = new Promise(function (resolve, reject) {
+ var method = 'message_get_suggested_recipients';
+ var args = [[self.context.default_res_id], self.context];
+ self._rpc({model: self.record.model, method: method, args: args})
.then(function (result) {
if (!self.suggested_partners_def) {
return; // widget has been reset (e.g. we just switched to another record)
@@ -555,8 +557,9 @@ var Chatter = Widget.extend({
reason: recipient[2],
});
});
- self.suggested_partners_def.resolve(suggested_partners);
+ resolve(suggested_partners);
});
+ });
}
this.suggested_partners_def.then(function (suggested_partners) {
self._openComposer({ isLog: false, suggested_partners: suggested_partners });
diff --git a/addons/mail/static/src/js/composers/basic_composer.js b/addons/mail/static/src/js/composers/basic_composer.js
index 9def912612c..72936152ae5 100644
--- a/addons/mail/static/src/js/composers/basic_composer.js
+++ b/addons/mail/static/src/js/composers/basic_composer.js
@@ -128,7 +128,7 @@ var BasicComposer = Widget.extend({
.on('update_typing_partners', this, this._onUpdateTypingPartners);
// Mention
- this._mentionManager.prependTo(this.$('.o_composer'));
+ var prependPromise = this._mentionManager.prependTo(this.$('.o_composer'));
// Drag-Drop files
// Allowing body to detect dragenter and dragleave for display
@@ -137,7 +137,7 @@ var BasicComposer = Widget.extend({
$body.on('dragleave.' + this._dropZoneNS, this._onBodyFileDragLeave.bind(this));
$body.on("dragover." + this._dropZoneNS, this._onBodyFileDragover.bind(this));
$body.on("drop." + this._dropZoneNS, this._onBodyFileDrop.bind(this));
- return this._super();
+ return Promise.all([this._super(), prependPromise]);
},
destroy: function () {
$("body").off('dragleave.' + this._dropZoneNS);
@@ -236,7 +236,7 @@ var BasicComposer = Widget.extend({
* displayed to the user. If none of them match, then it will fetch for more
* partner suggestions (@see _mentionFetchPartners).
*
- * @param {$.Deferred<Object[]>} prefetchedPartners list of list of
+ * @param {Promise<Object[]>} prefetchedPartners list of list of
* prefetched partners.
*/
mentionSetPrefetchedPartners: function (prefetchedPartners) {
@@ -299,20 +299,21 @@ var BasicComposer = Widget.extend({
/**
* @private
* @param {string} search
- * @returns {$.Deferred<Object[]>}
+ * @returns {Promise<Object[]>}
*/
_mentionGetCannedResponses: function (search) {
var self = this;
- var def = $.Deferred();
- clearTimeout(this._cannedTimeout);
- this._cannedTimeout = setTimeout(function () {
- var cannedResponses = self.call('mail_service', 'getCannedResponses');
- var matches = fuzzy.filter(utils.unaccent(search), _.pluck(cannedResponses, 'source'));
- var indexes = _.pluck(matches.slice(0, self.options.mentionFetchLimit), 'index');
- def.resolve(_.map(indexes, function (index) {
- return cannedResponses[index];
- }));
- }, 500);
+ var def = new Promise(function (resolve, reject) {
+ clearTimeout(self._cannedTimeout);
+ self._cannedTimeout = setTimeout(function () {
+ var cannedResponses = self.call('mail_service', 'getCannedResponses');
+ var matches = fuzzy.filter(utils.unaccent(search), _.pluck(cannedResponses, 'source'));
+ var indexes = _.pluck(matches.slice(0, self.options.mentionFetchLimit), 'index');
+ resolve(_.map(indexes, function (index) {
+ return cannedResponses[index];
+ }));
+ }, 500);
+ });
return def;
},
/**
@@ -346,7 +347,7 @@ var BasicComposer = Widget.extend({
*/
_mentionFetchPartners: function (search) {
var self = this;
- return $.when(this._mentionPrefetchedPartners).then(function (prefetchedPartners) {
+ return Promise.resolve(this._mentionPrefetchedPartners).then(function (prefetchedPartners) {
// filter prefetched partners with the given search string
var suggestions = [];
var limit = self.options.mentionFetchLimit;
@@ -371,7 +372,7 @@ var BasicComposer = Widget.extend({
{ limit: limit, search: search }
);
}
- return $.when(suggestions).then(function (suggestions) {
+ return Promise.resolve(suggestions).then(function (suggestions) {
//add im_status on suggestions
_.each(suggestions, function (suggestionsSet) {
_.each(suggestionsSet, function (suggestion) {
@@ -387,27 +388,27 @@ var BasicComposer = Widget.extend({
* @param {string} model
* @param {string} method
* @param {Object} kwargs
- * @return {$.Deferred}
+ * @return {Promise}
*/
_mentionFetchThrottled: function (model, method, kwargs) {
var self = this;
// Delays the execution of the RPC to prevent unnecessary RPCs when the user is still typing
- var def = $.Deferred();
- clearTimeout(this.mentionFetchTimer);
- this.mentionFetchTimer = setTimeout(function () {
- return self._rpc({model: model, method: method, kwargs: kwargs})
+ return new Promise(function (resolve, reject) {
+ clearTimeout(self.mentionFetchTimer);
+ self.mentionFetchTimer = setTimeout(function () {
+ return self._rpc({model: model, method: method, kwargs: kwargs})
.then(function (results) {
- def.resolve(results);
+ resolve(results);
});
- }, this.MENTION_THROTTLE);
- return def;
+ }, self.MENTION_THROTTLE);
+ });
},
/**
* @private
- * @returns {$.Deferred}
+ * @returns {Promise}
*/
_preprocessMessage: function () {
- // Return a deferred as this function is extended with asynchronous
+ // Return a promise as this function is extended with asynchronous
// behavior for the chatter composer
//Removing unwanted extra spaces from message
@@ -420,7 +421,7 @@ var BasicComposer = Widget.extend({
var commands = this.options.commandsEnabled ?
this._mentionManager.getListenerSelection('/') :
[];
- return $.when({
+ return Promise.resolve({
content: this._mentionManager.generateLinks(value),
attachment_ids: _.pluck(this.get('attachment_ids'), 'id'),
partner_ids: _.uniq(_.pluck(this._mentionManager.getListenerSelection('@'), 'id')),
diff --git a/addons/mail/static/src/js/composers/chatter_composer.js b/addons/mail/static/src/js/composers/chatter_composer.js
index 777467e6eb8..8aaaf08dd6d 100644
--- a/addons/mail/static/src/js/composers/chatter_composer.js
+++ b/addons/mail/static/src/js/composers/chatter_composer.js
@@ -59,109 +59,112 @@ var ChatterComposer = BasicComposer.extend({
* @private
* @param {Array} checkedSuggestedPartners list of 'recipient' partners to
* complete informations or validate
- * @returns {Deferred} resolved with the list of checked suggested partners
+ * @returns {Promise} resolved with the list of checked suggested partners
* (real partner)
**/
_checkSuggestedPartners: function (checkedSuggestedPartners) {
var self = this;
- var checkDone = $.Deferred();
+ var checkDone = new Promise(function (resolve, reject) {
+ var recipients = _.filter(checkedSuggestedPartners, function (recipient) {
+ return recipient.checked;
+ });
+ var recipientsToFind = _.filter(recipients, function (recipient) {
+ return (! recipient.partner_id);
+ });
+ var namesToFind = _.pluck(recipientsToFind, 'full_name');
+ var recipientsToCheck = _.filter(recipients, function (recipient) {
+ return (recipient.partner_id && ! recipient.email_address);
+ });
+ var recipientIDs = _.pluck(_.filter(recipients, function (recipient) {
+ return recipient.partner_id && recipient.email_address;
+ }), 'partner_id');
- var recipients = _.filter(checkedSuggestedPartners, function (recipient) {
- return recipient.checked;
- });
- var recipientsToFind = _.filter(recipients, function (recipient) {
- return (! recipient.partner_id);
- });
- var namesToFind = _.pluck(recipientsToFind, 'full_name');
- var recipientsToCheck = _.filter(recipients, function (recipient) {
- return (recipient.partner_id && ! recipient.email_address);
- });
- var recipientIDs = _.pluck(_.filter(recipients, function (recipient) {
- return recipient.partner_id && recipient.email_address;
- }), 'partner_id');
+ var namesToRemove = [];
+ var recipientIDsToRemove = [];
- var namesToRemove = [];
- var recipientIDsToRemove = [];
+ // have unknown names
+ // -> call message_get_partner_info_from_emails to try to find
+ // partner_id
+ var def;
+ if (namesToFind.length > 0) {
+ def = self._rpc({
+ model: self._model,
+ method: 'message_partner_info_from_emails',
+ args: [[self.context.default_res_id], namesToFind],
+ });
+ }
- // have unknown names
- // -> call message_get_partner_info_from_emails to try to find
- // partner_id
- var def;
- if (namesToFind.length > 0) {
- def = this._rpc({
- model: this._model,
- method: 'message_partner_info_from_emails',
- args: [[this.context.default_res_id], namesToFind],
- });
- }
+ // for unknown names + incomplete partners
+ // -> open popup - cancel = remove from recipients
+ Promise.resolve(def).then(function (result) {
+ result = result || [];
+ var emailDefs = [];
+ var recipientPopups = result.concat(recipientsToCheck);
- // for unknown names + incomplete partners
- // -> open popup - cancel = remove from recipients
- $.when(def).pipe(function (result) {
- result = result || [];
- var emailDefs = [];
- var recipientPopups = result.concat(recipientsToCheck);
+ _.each(recipientPopups, function (partnerInfo) {
+ var prom = new Promise(function(innerResolve, innerReject) {
+ var partnerName = partnerInfo.full_name;
+ var partnerID = partnerInfo.partner_id;
+ var parsedEmail = mailUtils.parseEmail(partnerName);
- _.each(recipientPopups, function (partnerInfo) {
- var deferred = $.Deferred();
- emailDefs.push(deferred);
+ var dialog = new viewDialogs.FormViewDialog(self, {
+ res_model: 'res.partner',
+ res_id: partnerID,
+ context: {
+ active_model: self._model,
+ active_id: self.context.default_res_id,
+ force_email: true,
+ ref: 'compound_context',
+ default_name: parsedEmail[0],
+ default_email: parsedEmail[1],
+ },
+ title: _t("Please complete customer's informations"),
+ disable_multiple_selection: true,
+ }).open();
+ dialog.on('closed', self, function () {
+ innerResolve();
+ });
+ dialog.opened().then(function () {
+ dialog.form_view.on('on_button_cancel', self, function () {
+ namesToRemove.push(partnerName);
+ if (partnerID) {
+ recipientIDsToRemove.push(partnerID);
+ }
+ });
+ });
+ });
- var partnerName = partnerInfo.full_name;
- var partnerID = partnerInfo.partner_id;
- var parsedEmail = mailUtils.parseEmail(partnerName);
+ emailDefs.push(prom);
- var dialog = new viewDialogs.FormViewDialog(self, {
- res_model: 'res.partner',
- res_id: partnerID,
- context: {
- active_model: self._model,
- active_id: self.context.default_res_id,
- force_email: true,
- ref: 'compound_context',
- default_name: parsedEmail[0],
- default_email: parsedEmail[1],
- },
- title: _t("Please complete customer's informations"),
- disable_multiple_selection: true,
- }).open();
- dialog.on('closed', self, function () {
- deferred.resolve();
- });
- dialog.opened().then(function () {
- dialog.form_view.on('on_button_cancel', self, function () {
- namesToRemove.push(partnerName);
- if (partnerID) {
- recipientIDsToRemove.push(partnerID);
- }
- });
});
- });
- $.when.apply($, emailDefs).then(function () {
- var newNamesToFind = _.difference(namesToFind, namesToRemove);
- var def;
- if (newNamesToFind.length > 0) {
- def = self._rpc({
- model: self._model,
- method: 'message_partner_info_from_emails',
- args: [[self.context.default_res_id], newNamesToFind, true],
+ Promise.all(emailDefs).then(function () {
+ var newNamesToFind = _.difference(namesToFind, namesToRemove);
+ var def;
+ if (newNamesToFind.length > 0) {
+ def = self._rpc({
+ model: self._model,
+ method: 'message_partner_info_from_emails',
+ args: [[self.context.default_res_id], newNamesToFind, true],
+ });
+ }
+ Promise.resolve(def).then(function (result) {
+ result = result || [];
+ var recipientPopups = result.concat(recipientsToCheck);
+ _.each(recipientPopups, function (partnerInfo) {
+ if (
+ partnerInfo.partner_id &&
+ _.indexOf(partnerInfo.partner_id, recipientIDsToRemove) === -1
+ ) {
+ recipientIDs.push(partnerInfo.partner_id);
+ }
});
- }
- $.when(def).pipe(function (result) {
- result = result || [];
- var recipientPopups = result.concat(recipientsToCheck);
- _.each(recipientPopups, function (partnerInfo) {
- if (
- partnerInfo.partner_id &&
- _.indexOf(partnerInfo.partner_id, recipientIDsToRemove) === -1
- ) {
- recipientIDs.push(partnerInfo.partner_id);
- }
+ }).then(function () {
+ resolve(recipientIDs);
});
- }).pipe(function () {
- checkDone.resolve(recipientIDs);
});
});
});
+
return checkDone;
},
/**
@@ -187,41 +190,40 @@ var ChatterComposer = BasicComposer.extend({
/**
* @override
* @private
- * @returns {$.Deferred}
+ * @returns {Promise}
*/
_preprocessMessage: function () {
var self = this;
- var def = $.Deferred();
- this._super().then(function (message) {
- message = _.extend(message, {
- subtype: 'mail.mt_comment',
- message_type: 'comment',
- context: _.defaults({}, self.context, session.user_context),
- });
+ return new Promise(function (resolve, reject) {
+ self._super().then(function (message) {
+ message = _.extend(message, {
+ subtype: 'mail.mt_comment',
+ message_type: 'comment',
+ context: _.defaults({}, self.context, session.user_context),
+ });
- // Subtype
- if (self.options.isLog) {
- message.subtype = 'mail.mt_note';
- }
+ // Subtype
+ if (self.options.isLog) {
+ message.subtype = 'mail.mt_note';
+ }
- // Partner_ids
- if (!self.options.isLog) {
- var checkedSuggestedPartners = self._getCheckedSuggestedPartners();
- self._checkSuggestedPartners(checkedSuggestedPartners).done(function (partnerIDs) {
- message.partner_ids = (message.partner_ids || []).concat(partnerIDs);
- // update context
- message.context = _.defaults({}, message.context, {
- mail_post_autofollow: true,
+ // Partner_ids
+ if (!self.options.isLog) {
+ var checkedSuggestedPartners = self._getCheckedSuggestedPartners();
+ self._checkSuggestedPartners(checkedSuggestedPartners).then(function (partnerIDs) {
+ message.partner_ids = (message.partner_ids || []).concat(partnerIDs);
+ // update context
+ message.context = _.defaults({}, message.context, {
+ mail_post_autofollow: true,
+ });
+ resolve(message);
});
- def.resolve(message);
- });
- } else {
- def.resolve(message);
- }
+ } else {
+ resolve(message);
+ }
+ });
});
-
- return def;
},
/**
* @override
@@ -244,20 +246,20 @@ var ChatterComposer = BasicComposer.extend({
}
var self = this;
- var recipientDoneDef = $.Deferred();
-
- // any operation on the full-composer will reload the record, so
- // warn the user that any unsaved changes on the record will be lost.
- this.trigger_up('discard_record_changes', {
- proceed: function () {
- if (self.options.isLog) {
- recipientDoneDef.resolve([]);
- } else {
- var checkedSuggestedPartners = self._getCheckedSuggestedPartners();
- self._checkSuggestedPartners(checkedSuggestedPartners)
- .then(recipientDoneDef.resolve.bind(recipientDoneDef));
- }
- },
+ var recipientDoneDef = new Promise(function (resolve, reject) {
+ // any operation on the full-composer will reload the record, so
+ // warn the user that any unsaved changes on the record will be lost.
+ self.trigger_up('discard_record_changes', {
+ proceed: function () {
+ if (self.options.isLog) {
+ resolve([]);
+ } else {
+ var checkedSuggestedPartners = self._getCheckedSuggestedPartners();
+ self._checkSuggestedPartners(checkedSuggestedPartners)
+ .then(resolve);
+ }
+ },
+ });
});
recipientDoneDef.then(function (partnerIDs) {
diff --git a/addons/mail/static/src/js/composers/extended_composer.js b/addons/mail/static/src/js/composers/extended_composer.js
index 917b71fa880..1acfba1058c 100644
--- a/addons/mail/static/src/js/composers/extended_composer.js
+++ b/addons/mail/static/src/js/composers/extended_composer.js
@@ -102,7 +102,7 @@ var ExtendedComposer = BasicComposer.extend({
/**
* @override
* @private
- * @returns {$.Deferred}
+ * @returns {Promise}
*/
_preprocessMessage: function () {
var self = this;
diff --git a/addons/mail/static/src/js/composers/mention_manager.js b/addons/mail/static/src/js/composers/mention_manager.js
index 6cbaab5002a..7ad8a36b39a 100644
--- a/addons/mail/static/src/js/composers/mention_manager.js
+++ b/addons/mail/static/src/js/composers/mention_manager.js
@@ -114,7 +114,7 @@ var MentionManager = Widget.extend({
if (this._activeListener) {
var mentionWord = this._mentionWord;
- $.when(this._activeListener.fetchCallback(mentionWord))
+ Promise.resolve(this._activeListener.fetchCallback(mentionWord))
.then(function (suggestions) {
if (mentionWord === self._mentionWord) {
// update suggestions only if mentionWord didn't change
diff --git a/addons/mail/static/src/js/discuss.js b/addons/mail/static/src/js/discuss.js
index 0e3b66dd720..4e88434f86d 100644
--- a/addons/mail/static/src/js/discuss.js
+++ b/addons/mail/static/src/js/discuss.js
@@ -82,7 +82,7 @@ var PartnerInviteDialog = Dialog.extend({
/**
* @private
- * @returns {$.Promise}
+ * @returns {Promise}
*/
_addChannel: function () {
var self = this;
@@ -297,7 +297,7 @@ var Discuss = AbstractAction.extend({
* @override
*/
willStart: function () {
- return $.when(this._super(), this.call('mail_service', 'isReady'));
+ return Promise.all([this._super(), this.call('mail_service', 'isReady')]);
},
/**
* @override
@@ -331,7 +331,7 @@ var Discuss = AbstractAction.extend({
this._extendedComposer.appendTo(this.$('.o_mail_discuss_content')));
defs.push(this._super.apply(this, arguments));
- return $.when.apply($, defs)
+ return Promise.all(defs)
.then(function () {
return self._setThread(self._defaultThreadID);
})
@@ -474,7 +474,7 @@ var Discuss = AbstractAction.extend({
},
/**
* @private
- * @returns {$.Promise}
+ * @returns {Promise}
*/
_fetchAndRenderThread: function () {
var self = this;
@@ -567,7 +567,7 @@ var Discuss = AbstractAction.extend({
* loaded when scrolling to the top, so they can't be loaded if there is no
* scrollbar)
*
- * @returns {Deferred} resolved when there are enough messages to fill the
+ * @returns {Promise} resolved when there are enough messages to fill the
* screen, or when there is no more message to fetch
*/
_loadEnoughMessages: function () {
@@ -583,7 +583,7 @@ var Discuss = AbstractAction.extend({
* Load more messages for the current thread
*
* @private
- * @returns {$.Promise}
+ * @returns {Promise}
*/
_loadMoreMessages: function () {
var self = this;
@@ -647,7 +647,7 @@ var Discuss = AbstractAction.extend({
autoFocus: true,
source: function (request, response) {
self._lastSearchVal = _.escape(request.term);
- self._searchChannel(self._lastSearchVal).done(function (result){
+ self._searchChannel(self._lastSearchVal).then(function (result){
result.push({
label: _.str.sprintf(
'<strong>' + _t("Create %s (Public)") + '</strong>',
@@ -689,7 +689,7 @@ var Discuss = AbstractAction.extend({
autoFocus: true,
source: function (request, response) {
self._lastSearchVal = _.escape(request.term);
- self.call('mail_service', 'searchPartner', self._lastSearchVal, 10).done(response);
+ self.call('mail_service', 'searchPartner', self._lastSearchVal, 10).then(response);
},
select: function (ev, ui) {
var partnerID = ui.item.id;
@@ -819,7 +819,7 @@ var Discuss = AbstractAction.extend({
* Renders, binds events and appends a thread widget.
*
* @private
- * @returns {Deferred}
+ * @returns {Promise}
*/
_renderThread: function () {
this._threadWidget = new ThreadWidget(this, {
@@ -877,7 +877,7 @@ var Discuss = AbstractAction.extend({
/**
* @private
* @param {string} searchVal
- * @returns {$.Promise<Array>}
+ * @returns {Promise<Array>}
*/
_searchChannel: function (searchVal){
return this._rpc({
@@ -915,7 +915,7 @@ var Discuss = AbstractAction.extend({
this._extendedComposer.do_show();
this._threadWidget.scrollToMessage({
- msgID: messageID,
+ messageID: messageID,
duration: 200,
onlyIfNecessary: true
});
@@ -927,7 +927,7 @@ var Discuss = AbstractAction.extend({
*
* @private
* @param {integer} threadID a thread with such ID
- * @returns {$.Promise}
+ * @returns {Promise}
*/
_setThread: function (threadID) {
var self = this;
@@ -1483,9 +1483,6 @@ var Discuss = AbstractAction.extend({
} else {
self._threadWidget.scrollToBottom();
}
- })
- .fail(function () {
- // todo: display notifications
});
},
/**
diff --git a/addons/mail/static/src/js/discuss_mobile.js b/addons/mail/static/src/js/discuss_mobile.js
index 549e05b78fd..617700c20c1 100644
--- a/addons/mail/static/src/js/discuss_mobile.js
+++ b/addons/mail/static/src/js/discuss_mobile.js
@@ -116,7 +116,7 @@ Discuss.include({
this._thread = thread;
if (thread.getType() !== 'mailbox') {
this.call('mail_service', 'openThreadWindow', threadID);
- return $.when();
+ return Promise.resolve();
} else {
return this._super.apply(this, arguments);
}
@@ -179,7 +179,7 @@ Discuss.include({
});
def = this.call('mail_service', 'getChannelPreviews', channels);
}
- return $.when(def).then(function (previews) {
+ return Promise.resolve(def).then(function (previews) {
// update content
if (inMailbox) {
if (!previouslyInInbox) {
diff --git a/addons/mail/static/src/js/document_viewer.js b/addons/mail/static/src/js/document_viewer.js
index 9affc3f41cf..77f33d152c0 100644
--- a/addons/mail/static/src/js/document_viewer.js
+++ b/addons/mail/static/src/js/document_viewer.js
@@ -76,7 +76,7 @@ var DocumentViewer = Widget.extend({
start: function () {
this.$el.modal('show');
this.$el.on('hidden.bs.modal', _.bind(this._onDestroy, this));
- this.$('.o_viewer_img').load(_.bind(this._onImageLoaded, this));
+ this.$('.o_viewer_img').on("load", _.bind(this._onImageLoaded, this));
this.$('[data-toggle="tooltip"]').tooltip({delay: 0});
return this._super.apply(this, arguments);
},
@@ -132,7 +132,7 @@ var DocumentViewer = Widget.extend({
this.$('.o_viewer_content').html(QWeb.render('DocumentViewer.Content', {
widget: this
}));
- this.$('.o_viewer_img').load(_.bind(this._onImageLoaded, this));
+ this.$('.o_viewer_img').on("load", _.bind(this._onImageLoaded, this));
this.$('[data-toggle="tooltip"]').tooltip({delay: 0});
this._reset();
},
diff --git a/addons/mail/static/src/js/followers.js b/addons/mail/static/src/js/followers.js
index 0a760516607..a8475f43219 100644
--- a/addons/mail/static/src/js/followers.js
+++ b/addons/mail/static/src/js/followers.js
@@ -55,14 +55,14 @@ var Followers = AbstractField.extend({
// note: the rendering of this widget is asynchronous as it needs to
// fetch the details of the followers, but it performs a first rendering
// synchronously (_displayGeneric), and updates its rendering once it
- // has fetched the required data, so this function doesn't return a deferred
+ // has fetched the required data, so this function doesn't return a promise
// as we don't want to wait to the data to be loaded to display the widget
var self = this;
var fetch_def = this.dp.add(this._readFollowers());
concurrency.rejectAfter(concurrency.delay(0), fetch_def).then(this._displayGeneric.bind(this));
- fetch_def.then(function () {
+ return fetch_def.then(function () {
self._displayButtons();
self._displayFollowers(self.followers);
if (self.subtypes) { // current user is follower
@@ -203,7 +203,7 @@ var Followers = AbstractField.extend({
params: { follower_ids: missing_ids, res_model: this.model }
});
}
- return $.when(def).then(function (results) {
+ return Promise.resolve(def).then(function (results) {
if (results) {
self.followers = _.uniq(results.followers.concat(self.followers), 'id');
if (results.subtypes) { //read_followers will return False if current user is not in the list
@@ -241,27 +241,27 @@ var Followers = AbstractField.extend({
*/
_unfollow: function (ids) {
var self = this;
- var def = $.Deferred();
- var text = _t("Warning! \n If you remove a follower, he won't be notified of any email or discussion on this document.\n Do you really want to remove this follower ?");
- Dialog.confirm(this, text, {
- confirm_callback: function () {
- var args = [
- [self.res_id],
- ids.partner_ids,
- ids.channel_ids,
- {}, // FIXME
- ];
- self._rpc({
+ return new Promise(function (resolve, reject) {
+ var text = _t("Warning! \n If you remove a follower, he won't be notified of any email or discussion on this document.\n Do you really want to remove this follower ?");
+ Dialog.confirm(this, text, {
+ confirm_callback: function () {
+ var args = [
+ [self.res_id],
+ ids.partner_ids,
+ ids.channel_ids,
+ {}, // FIXME
+ ];
+ self._rpc({
model: self.model,
method: 'message_unsubscribe',
args: args
})
.then(self._reload.bind(self));
- def.resolve();
- },
- cancel_callback: def.reject.bind(def),
+ resolve();
+ },
+ cancel_callback: reject,
+ });
});
- return def;
},
_updateSubscription: function (event, followerID, isChannel) {
var ids = {};
@@ -290,7 +290,7 @@ var Followers = AbstractField.extend({
// If no more subtype followed, unsubscribe the follower
if (!checklist.length) {
- this._unfollow(ids).fail(function () {
+ this._unfollow(ids).guardedCatch(function () {
$(event.currentTarget).find('input').addBack('input').prop('checked', true);
});
} else {
diff --git a/addons/mail/static/src/js/form_renderer.js b/addons/mail/static/src/js/form_renderer.js
index 91d2c2033c4..e7b767c0b2f 100644
--- a/addons/mail/static/src/js/form_renderer.js
+++ b/addons/mail/static/src/js/form_renderer.js
@@ -50,18 +50,24 @@ FormRenderer.include({
* @private
*/
_renderNode: function (node) {
+ var self = this;
if (node.tag === 'div' && node.attrs.class === 'oe_chatter') {
if (!this.chatter) {
this.chatter = new Chatter(this, this.state, this.mailFields, {
isEditable: this.activeActions.edit,
viewType: 'form',
});
- this.chatter.appendTo($('<div>'));
- this._handleAttributes(this.chatter.$el, node);
+
+ var $temporaryParentDiv = $('<div>');
+ this.defs.push(this.chatter.appendTo($temporaryParentDiv).then(function () {
+ self.chatter.$el.unwrap();
+ self._handleAttributes(self.chatter.$el, node);
+ }));
+ return $temporaryParentDiv;
} else {
this.chatter.update(this.state);
+ return this.chatter.$el;
}
- return this.chatter.$el;
} else {
return this._super.apply(this, arguments);
}
diff --git a/addons/mail/static/src/js/many2many_tags_email.js b/addons/mail/static/src/js/many2many_tags_email.js
index e66412a7a2c..6648ef50423 100644
--- a/addons/mail/static/src/js/many2many_tags_email.js
+++ b/addons/mail/static/src/js/many2many_tags_email.js
@@ -20,7 +20,7 @@ BasicModel.include({
* @private
* @param {Object} record - an element from the localData
* @param {string} fieldName
- * @return {Deferred<Object>} the deferred is resolved with the
+ * @return {Promise<Object>} the promise is resolved with the
* invalidPartnerIds
*/
_setInvalidMany2ManyTagsEmail: function (record, fieldName) {
@@ -42,10 +42,10 @@ BasicModel.include({
var changes = {operation: 'DELETE', ids: _.pluck(invalidPartnerIds, 'id')};
def = this._applyX2ManyChange(record, fieldName, changes);
}
- return $.when(def).then(function () {
- return $.when({
+ return Promise.resolve(def).then(function () {
+ return {
invalidPartnerIds: _.pluck(invalidPartnerIds, 'res_id'),
- });
+ };
});
},
});
@@ -65,7 +65,7 @@ var FieldMany2ManyTagsEmail = M2MTags.extend({
* Open a popup for each invalid partners (without email) to fill the email.
*
* @private
- * @returns {Deferred}
+ * @returns {Promise}
*/
_checkEmailPopup: function () {
var self = this;
@@ -75,25 +75,25 @@ var FieldMany2ManyTagsEmail = M2MTags.extend({
// propose the user to correct invalid partners
_.each(this.record.specialData[this.name].invalidPartnerIds, function (resID) {
- var def = $.Deferred();
- popupDefs.push(def);
-
- var pop = new form_common.FormViewDialog(self, {
- res_model: self.field.relation,
- res_id: resID,
- context: self.record.context,
- title: "",
- on_saved: function (record) {
- if (record.data.email) {
- validPartners.push(record.res_id);
- }
- },
- }).open();
- pop.on('closed', self, function () {
- def.resolve();
+ var def = new Promise(function (resolve, reject) {
+ var pop = new form_common.FormViewDialog(self, {
+ res_model: self.field.relation,
+ res_id: resID,
+ context: self.record.context,
+ title: "",
+ on_saved: function (record) {
+ if (record.data.email) {
+ validPartners.push(record.res_id);
+ }
+ },
+ }).open();
+ pop.on('closed', self, function () {
+ resolve();
+ });
});
+ popupDefs.push(def);
});
- return $.when.apply($, popupDefs).then(function() {
+ return Promise.all(popupDefs).then(function() {
// All popups have been processed for the given ids
// It is now time to set the final value with valid partners ids.
validPartners = _.uniq(validPartners);
@@ -117,14 +117,14 @@ var FieldMany2ManyTagsEmail = M2MTags.extend({
*/
_render: function () {
var self = this;
- var def = $.Deferred();
var _super = this._super.bind(this);
- if (this.record.specialData[this.name].invalidPartnerIds.length) {
- def = this._checkEmailPopup();
- } else {
- def.resolve();
- }
- return def.then(function () {
+ return new Promise(function (resolve, reject) {
+ if (self.record.specialData[self.name].invalidPartnerIds.length) {
+ resolve(self._checkEmailPopup());
+ } else {
+ resolve();
+ }
+ }).then(function () {
return _super.apply(self, arguments);
});
},
diff --git a/addons/mail/static/src/js/models/messages/message.js b/addons/mail/static/src/js/models/messages/message.js
index a414a11874b..77e4120da29 100644
--- a/addons/mail/static/src/js/models/messages/message.js
+++ b/addons/mail/static/src/js/models/messages/message.js
@@ -511,7 +511,7 @@ var Message = AbstractMessage.extend(Mixins.EventDispatcherMixin, ServicesMixin
* @see {mail.Manager.Notification} for the receipt of 'toggle_star'
* notification after this rpc.
*
- * @return {$.Promise}
+ * @return {Promise}
*/
toggleStarStatus: function () {
return this._rpc({
diff --git a/addons/mail/static/src/js/models/threads/abstract_thread.js b/addons/mail/static/src/js/models/threads/abstract_thread.js
index a515c4d2f8a..192d0e58c93 100644
--- a/addons/mail/static/src/js/models/threads/abstract_thread.js
+++ b/addons/mail/static/src/js/models/threads/abstract_thread.js
@@ -150,18 +150,18 @@ var AbstractThread = Class.extend(Mixins.EventDispatcherMixin, {
* Mark the thread as read, which resets the unread counter to 0. This is
* only performed if the unread counter is not 0.
*
- * @returns {$.Promise}
+ * @returns {Promise}
*/
markAsRead: function () {
if (this._unreadCounter > 0) {
return this._markAsRead();
}
- return $.when();
+ return Promise.resolve();
},
/**
* Post a message on this thread
*
- * @returns {$.Promise} resolved with the message object to be sent to the
+ * @returns {Promise} resolved with the message object to be sent to the
* server
*/
postMessage: function () {
@@ -200,22 +200,22 @@ var AbstractThread = Class.extend(Mixins.EventDispatcherMixin, {
* Mark the thread as read
*
* @private
- * @returns {$.Promise}
+ * @returns {Promise}
*/
_markAsRead: function () {
this.resetUnreadCounter();
- return $.when();
+ return Promise.resolve();
},
/**
* Post a message on this thread
*
* @abstract
* @private
- * @returns {$.Promise} resolved with the message object to be sent to the
+ * @returns {Promise} resolved with the message object to be sent to the
* server
*/
_postMessage: function () {
- return $.when();
+ return Promise.resolve();
},
/**
* Warn views (e.g. discuss app, thread window, etc.) to update visually
diff --git a/addons/mail/static/src/js/models/threads/channel.js b/addons/mail/static/src/js/models/threads/channel.js
index 9f0f37264db..9e9f3ac6a39 100644
--- a/addons/mail/static/src/js/models/threads/channel.js
+++ b/addons/mail/static/src/js/models/threads/channel.js
@@ -70,7 +70,7 @@ var Channel = SearchableThread.extend(ThreadTypingMixin, {
this._isMyselfModerator = data.is_moderator;
this._lastMessageDate = undefined;
this._members = data.members || [];
- // Deferred that is resolved on fetched members of this channel.
+ // Promise that is resolved on fetched members of this channel.
this._membersDef = undefined;
// number of messages that are 'needaction', which is equivalent to the
// number of messages in this channel that are in inbox.
@@ -129,19 +129,21 @@ var Channel = SearchableThread.extend(ThreadTypingMixin, {
* @pverride
*/
detach: function () {
- this._super.apply(this, arguments);
- this._rpc({
- model: 'mail.channel',
- method: 'channel_minimize',
- args: [this.getUUID(), true],
- }, {
- shadow: true,
+ var self = this;
+ return this._super.apply(this, arguments).then(function () {
+ self._rpc({
+ model: 'mail.channel',
+ method: 'channel_minimize',
+ args: [self.getUUID(), true],
+ }, {
+ shadow: true,
+ });
});
},
/**
* Force fetch members of the channel
*
- * @returns {$.Promise<Object[]>} resolved with list of channel listeners
+ * @returns {Promise<Object[]>} resolved with list of channel listeners
*/
forceFetchMembers: function () {
this._membersDef = undefined;
@@ -186,7 +188,7 @@ var Channel = SearchableThread.extend(ThreadTypingMixin, {
/**
* Get listeners of a channel
*
- * @returns {$.Promise<Array<Object[]>>} resolved with list of list of
+ * @returns {Promise<Object[]>} resolved with list of list of
* channel listeners.
*/
getMentionPartnerSuggestions: function () {
@@ -302,7 +304,7 @@ var Channel = SearchableThread.extend(ThreadTypingMixin, {
* Unsubscribes from channel
*
* @abstract
- * @returns {$.Promise} resolve when unsubscribed
+ * @returns {Promise} resolve when unsubscribed
*/
unsubscribe: function () {},
/**
@@ -381,19 +383,19 @@ var Channel = SearchableThread.extend(ThreadTypingMixin, {
*
* @override
* @private
- * @returns {$.Promise} resolved when message has been marked as read
+ * @returns {Promise} resolved when message has been marked as read
*/
_markAsRead: function () {
var superDef = this._super.apply(this, arguments);
var seenDef = this._notifySeen();
- return $.when(superDef, seenDef);
+ return Promise.all([superDef, seenDef]);
},
/**
* @override {mail.model.ThreadTypingMixin}
* @private
* @param {Object} params
* @param {boolean} params.typing
- * @returns {$.Promise}
+ * @returns {Promise}
*/
_notifyMyselfTyping: function (params) {
return this._rpc({
@@ -424,7 +426,7 @@ var Channel = SearchableThread.extend(ThreadTypingMixin, {
* @override
* @private
* @param {Object} data data related to the new message
- * @returns {$.Promise<Object>} resolved when the message has been sent to
+ * @returns {Promise<Object>} resolved when the message has been sent to
* the server, with the object message that has been sent to the server.
*/
_postMessage: function (data) {
diff --git a/addons/mail/static/src/js/models/threads/document_thread.js b/addons/mail/static/src/js/models/threads/document_thread.js
index 6c15b39d25e..08e441610ee 100644
--- a/addons/mail/static/src/js/models/threads/document_thread.js
+++ b/addons/mail/static/src/js/models/threads/document_thread.js
@@ -92,7 +92,7 @@ var DocumentThread = Thread.extend({
* @param {Object} options
* @param {boolean} [options.forceFetch] if true, fetch anyway, as user
* clicked on 'load more'.
- * @returns {$.Promise<mail.model.Message[]>}
+ * @returns {Promise<mail.model.Message[]>}
*/
fetchMessages: function (options) {
var self = this;
@@ -217,14 +217,14 @@ var DocumentThread = Thread.extend({
* Get most up to date messageIDs
*
* @private
- * @returns {$.Promise} resolved when message IDs have been fetched and set
+ * @returns {Promise} resolved when message IDs have been fetched and set
* in the model
*/
_fetchMessageIDs: function () {
var self = this;
var resID = this.getDocumentID();
if (!resID || !this._mustFetchMessageIDs) {
- return $.when();
+ return Promise.resolve();
}
return this._rpc({
model: this.getDocumentModel(),
@@ -239,7 +239,7 @@ var DocumentThread = Thread.extend({
* @private
* @param {Object} options
* @param {boolean} [options.forceFetch]
- * @returns {$.Promise} resolved when messages have been fetched + document
+ * @returns {Promise} resolved when messages have been fetched + document
* thread has updated messages
*/
_fetchMessages: function (options) {
@@ -273,7 +273,7 @@ var DocumentThread = Thread.extend({
});
});
} else {
- return $.when();
+ return Promise.resolve();
}
});
@@ -284,7 +284,7 @@ var DocumentThread = Thread.extend({
*
* @override
* @private
- * @returns {$.Promise} resolved when messages have been marked as read on
+ * @returns {Promise} resolved when messages have been marked as read on
* the server.
*/
_markAsRead: function () {
@@ -299,7 +299,7 @@ var DocumentThread = Thread.extend({
* @override
* @private
* @param {Object} data data related to the new message
- * @return {$.Promise<Object>} resolved when the message has been sent to
+ * @return {Promise<Object>} resolved when the message has been sent to
* the server, with the object message that has been sent to the server.
*/
_postMessage: function (data) {
diff --git a/addons/mail/static/src/js/models/threads/livechat.js b/addons/mail/static/src/js/models/threads/livechat.js
index 45cab5aef10..c3b4a5e2b4d 100644
--- a/addons/mail/static/src/js/models/threads/livechat.js
+++ b/addons/mail/static/src/js/models/threads/livechat.js
@@ -34,7 +34,7 @@ var Livechat = TwoUserChannel.extend({
* display of a user that is typing.
*
* @override
- * @returns {$.Promise<Array<Object[]>>} resolved with list of list of
+ * @returns {Promise<Object[]>} resolved with list of list of
* livechat members.
*/
getMentionPartnerSuggestions: function () {
diff --git a/addons/mail/static/src/js/models/threads/mailbox.js b/addons/mail/static/src/js/models/threads/mailbox.js
index 263072f575e..bedd6af27e1 100644
--- a/addons/mail/static/src/js/models/threads/mailbox.js
+++ b/addons/mail/static/src/js/models/threads/mailbox.js
@@ -59,7 +59,7 @@ var Mailbox = SearchableThread.extend({
* channel, only keep the lastest message of this document/channel in the
* previews.
*
- * @returns {$.Promise<Object[]>}
+ * @returns {Promise<Object[]>}
*/
getMessagePreviews: function () {
var self = this;
@@ -119,7 +119,7 @@ var Mailbox = SearchableThread.extend({
* makes only sense for 'Inbox'.
*
* @param {Array} domain
- * @return {$.Promise} resolved when all messages have been marked as read
+ * @return {Promise} resolved when all messages have been marked as read
* on the server
*/
markAllMessagesAsRead: function (domain) {
@@ -133,7 +133,7 @@ var Mailbox = SearchableThread.extend({
},
});
}
- return $.when();
+ return Promise.resolve();
},
//--------------------------------------------------------------------------
diff --git a/addons/mail/static/src/js/models/threads/mixins/thread_typing_mixin.js b/addons/mail/static/src/js/models/threads/mixins/thread_typing_mixin.js
index f995b4e09b3..7d97538dbb9 100644
--- a/addons/mail/static/src/js/models/threads/mixins/thread_typing_mixin.js
+++ b/addons/mail/static/src/js/models/threads/mixins/thread_typing_mixin.js
@@ -239,11 +239,11 @@ var ThreadTypingMixin = {
* @private
* @param {Object} params
* @param {boolean} params.typing whether we are typing something or not
- * @returns {$.Promise} resolved if the server is notified, rejected
+ * @returns {Promise} resolved if the server is notified, rejected
* otherwise
*/
_notifyMyselfTyping: function (params) {
- return $.when();
+ return Promise.resolve();
},
/**
* Warn views that the list of users that are currently typing on this
diff --git a/addons/mail/static/src/js/models/threads/multi_user_channel.js b/addons/mail/static/src/js/models/threads/multi_user_channel.js
index bac417c361d..3dab9337502 100644
--- a/addons/mail/static/src/js/models/threads/multi_user_channel.js
+++ b/addons/mail/static/src/js/models/threads/multi_user_channel.js
@@ -56,7 +56,7 @@ var MultiUserChannel = Channel.extend({
* Unsubscribes from channel
*
* @override
- * @returns {$.Promise} resolve when unsubscribed
+ * @returns {Promise} resolve when unsubscribed
*/
unsubscribe: function () {
return this._rpc({
diff --git a/addons/mail/static/src/js/models/threads/searchable_thread.js b/addons/mail/static/src/js/models/threads/searchable_thread.js
index 8ddff5457af..511bc6348c8 100644
--- a/addons/mail/static/src/js/models/threads/searchable_thread.js
+++ b/addons/mail/static/src/js/models/threads/searchable_thread.js
@@ -49,7 +49,7 @@ var SearchableThread = Thread.extend({
}
var cache = this._getCache(domain);
if (cache.loaded) {
- return $.when(cache.messages);
+ return Promise.all(cache.messages);
} else {
return this._fetchMessages(domain);
}
@@ -159,7 +159,7 @@ var SearchableThread = Thread.extend({
* @private
* @param {Array} [pDomain] filter on the messages of the channel
* @param {boolean} [loadMore] Whether it should load more message
- * @return {$.Promise<mail.model.Message[]>} resolved with list of messages
+ * @return {Promise<mail.model.Message[]>} resolved with list of messages
*/
_fetchMessages: function (pDomain, loadMore) {
var self = this;
diff --git a/addons/mail/static/src/js/models/threads/thread.js b/addons/mail/static/src/js/models/threads/thread.js
index 8c622779bb3..8f4e8956d27 100644
--- a/addons/mail/static/src/js/models/threads/thread.js
+++ b/addons/mail/static/src/js/models/threads/thread.js
@@ -58,12 +58,13 @@ var Thread = AbstractThread.extend(ServicesMixin, {
* of this thread. Otherwise unfold it while detaching it.
* @param {boolean} [options.passively=false] if set, if the thread window
* will be created passively.
+ * @returns {Promise}
*/
detach: function (options) {
options = options || {};
this._detached = true;
this._folded = options.keepFoldState ? this._folded : false;
- this._warnUpdatedWindowState({
+ return this._warnUpdatedWindowState({
passively: options.passively,
});
},
@@ -79,10 +80,10 @@ var Thread = AbstractThread.extend(ServicesMixin, {
* `this.LIMIT` number of messages at a time.
*
* @abstract
- * @returns {$.Promise<mail.model.Message[]>}
+ * @returns {Promise<mail.model.Message[]>}
*/
fetchMessages: function () {
- return $.when([]);
+ return Promise.resolve([]);
},
/**
* Updates the folded state of the thread. Must be overriden to reflect
@@ -110,10 +111,10 @@ var Thread = AbstractThread.extend(ServicesMixin, {
* By default, a thread has not listener.
*
* @abstract
- * @returns {$.Promise<Array<Object[]>>}
+ * @returns {Promise<Array<Object[]>>}
*/
getMentionPartnerSuggestions: function () {
- return $.when([]);
+ return Promise.resolve([]);
},
/**
* Returns the information required to render the preview of this channel.
@@ -287,10 +288,10 @@ var Thread = AbstractThread.extend(ServicesMixin, {
/**
* @abstract
* @private
- * @return {$.Promise}
+ * @return {Promise}
*/
_fetchMessages: function () {
- return $.when();
+ return Promise.resolve();
},
/**
* Replace character representations of emojis by their unicode
@@ -330,7 +331,7 @@ var Thread = AbstractThread.extend(ServicesMixin, {
* @abstract
* @private
* @param {Object} data
- * @returns {$.Promise<Object>} resolved with the message object to be sent
+ * @returns {Promise<Object>} resolved with the message object to be sent
* to the server
*/
_postMessage: function (data) {
@@ -355,7 +356,7 @@ var Thread = AbstractThread.extend(ServicesMixin, {
messageData.subject = data.subject;
}
return this._super.apply(this, arguments).then(function () {
- return $.when(messageData);
+ return messageData;
});
},
/**
@@ -374,10 +375,11 @@ var Thread = AbstractThread.extend(ServicesMixin, {
* @private
* @param {Object} [options={}]
* @param {boolean} [options.passively=false]
+ * @returns {Promise}
*/
_warnUpdatedWindowState: function (options) {
options = options || {};
- this.call('mail_service', 'updateThreadWindow', this.getID(), options);
+ return this.call('mail_service', 'updateThreadWindow', this.getID(), options);
},
});
diff --git a/addons/mail/static/src/js/models/threads/two_user_channel.js b/addons/mail/static/src/js/models/threads/two_user_channel.js
index 204fd95eb82..54a4145bd13 100644
--- a/addons/mail/static/src/js/models/threads/two_user_channel.js
+++ b/addons/mail/static/src/js/models/threads/two_user_channel.js
@@ -15,7 +15,7 @@ var TwoUserChannel = Channel.extend({
* Unpin from two-user thread
*
* @override
- * @returns {$.Promise} resolve when unsubscribed
+ * @returns {Promise} resolve when unsubscribed
*/
unsubscribe: function () {
return this._rpc({
diff --git a/addons/mail/static/src/js/services/mail_document_thread_manager.js b/addons/mail/static/src/js/services/mail_document_thread_manager.js
index a98ae317c9d..f1d9eefb44a 100644
--- a/addons/mail/static/src/js/services/mail_document_thread_manager.js
+++ b/addons/mail/static/src/js/services/mail_document_thread_manager.js
@@ -182,7 +182,7 @@ MailManager.include({
resModel: resModel,
});
}
- this._super.apply(this, arguments);
+ return this._super.apply(this, arguments);
},
/**
* Updates the thread windows related to document threads.
diff --git a/addons/mail/static/src/js/services/mail_manager.js b/addons/mail/static/src/js/services/mail_manager.js
index 5eb588d24e7..27a7183ec88 100644
--- a/addons/mail/static/src/js/services/mail_manager.js
+++ b/addons/mail/static/src/js/services/mail_manager.js
@@ -80,13 +80,14 @@ var MailManager = AbstractService.extend({
* the unread_counter of channel.
* @param {boolean} [options.silent] whether it should inform in the mailBus
* of the newly created message.
- * @returns {mail.model.Message} message object
+ * @returns {Promise<mail.model.Message>}
*/
addMessage: function (data, options) {
options = options || {};
var message = this.getMessage(data.id);
+ var prom = Promise.resolve();
if (!message) {
- message = this._addNewMessage(data, options);
+ prom = this._addNewMessage(data, options);
} else {
if (data.moderation_status === 'accepted') {
message.setModerationStatus('accepted', {
@@ -97,7 +98,7 @@ var MailManager = AbstractService.extend({
this._addMessageToThreads(message, options);
}
}
- return message;
+ return prom;
},
/**
* Creates a channel, can be either a true channel or a DM chat based on
@@ -105,7 +106,7 @@ var MailManager = AbstractService.extend({
*
* @param {integer|string} name id of partner (in case of dm) or name
* @param {string} type ['dm_chat', 'public', 'private']
- * @returns {$.Promise<integer>} resolved with ID of the newly created
+ * @returns {Promise<integer>} resolved with ID of the newly created
* channel
*/
createChannel: function (name, type) {
@@ -150,7 +151,7 @@ var MailManager = AbstractService.extend({
* Returns the content that will be shown in the mail navbar dropdown
*
* @param {mail.model.Channel[]} channels
- * @returns {$.Promise<Object[]>} resolved with list of channel previews
+ * @returns {Promise<Object[]>} resolved with list of channel previews
*/
getChannelPreviews: function (channels) {
var self = this;
@@ -227,23 +228,22 @@ var MailManager = AbstractService.extend({
*
* @param {string} [filter=undefined] specify 'chat' or 'channels' to only
* get previews for that type of threads
- * @returns {$.Promise<Object[]>} resolved with list of objects that have a
+ * @returns {Promise<Object[]>} resolved with list of objects that have a
* valid format for rendering a messaging menu preview items.
*/
getSystrayPreviews: function (filter) {
var self = this;
- var defs = [];
var channelDef = this._getSystrayChannelPreviews(filter);
var inboxDef = this._getSystrayInboxPreviews(filter);
var failureDef = this._getSystrayMailFailurePreviews(filter);
- defs = defs.concat([channelDef, inboxDef, failureDef]);
- return $.when.apply($, defs)
- .then(function (previewsChannel, previewsInbox, previewsFailure) {
+
+ return Promise.all([channelDef, inboxDef, failureDef])
+ .then(function (result) { //previewsChannel, previewsInbox, previewsFailure
// order: failures > inbox > channel, each group must be sorted
- previewsChannel = self._sortPreviews(previewsChannel);
- previewsInbox = self._sortPreviews(previewsInbox);
- previewsFailure = self._sortPreviews(previewsFailure);
+ var previewsChannel = self._sortPreviews(result[0]);
+ var previewsInbox = self._sortPreviews(result[1]);
+ var previewsFailure = self._sortPreviews(result[2]);
return _.union(previewsFailure, previewsInbox, previewsChannel);
});
},
@@ -295,7 +295,7 @@ var MailManager = AbstractService.extend({
* This is the case when it has fetched the initial state from the server,
* by means of the route 'mail/init_messaging'
*
- * @returns {$.Promise}
+ * @returns {Promise}
*/
isReady: function () {
return this._isReady;
@@ -306,24 +306,24 @@ var MailManager = AbstractService.extend({
*
* @param {integer} channelID
* @param {Object} [options] options to be passed on channel add
- * @returns {$.Promise<integer>} resolved with channelID joined
+ * @returns {Promise<integer>} resolved with channelID joined
*/
joinChannel: function (channelID, options) {
- var def;
+ var prom;
var channel = this.getChannel(channelID);
if (channel) {
// channel already joined
- def = $.when(channelID);
+ prom = Promise.resolve(channelID);
} else {
- def = this._joinAndAddChannel(channelID, options);
+ prom = this._joinAndAddChannel(channelID, options);
}
- return def;
+ return prom;
},
/**
* Mark messages as read
*
* @param {Array} messageIDs list of messages IDs
- * @returns {$.Promise} resolved when messages have been marked as read on
+ * @returns {Promise} resolved when messages have been marked as read on
* the server.
*/
markMessagesAsRead: function (messageIDs) {
@@ -341,7 +341,7 @@ var MailManager = AbstractService.extend({
args: [ids],
});
} else {
- return $.when();
+ return Promise.resolve();
}
},
/**
@@ -396,19 +396,19 @@ var MailManager = AbstractService.extend({
*
* @param {string} searchVal
* @param {integer} limit max number of found partners in the response
- * @returns {$.Promise<Object[]>} list of found partners (matching
+ * @returns {Promise<Object[]>} list of found partners (matching
* 'searchVal')
*/
searchPartner: function (searchVal, limit) {
- var def = $.Deferred();
+ var self = this;
var partners = this._searchPartnerPrefetch(searchVal, limit);
-
- if (!partners.length) {
- def = this._searchPartnerFetch(searchVal, limit);
- } else {
- def = $.when(partners);
- }
- return def.then(function (partners) {
+ return new Promise(function (resolve, reject) {
+ if (!partners.length) {
+ resolve(self._searchPartnerFetch(searchVal, limit));
+ } else {
+ resolve(partners);
+ }
+ }).then(function (partners) {
var suggestions = _.map(partners, function (partner) {
return {
id: partner.id,
@@ -422,7 +422,7 @@ var MailManager = AbstractService.extend({
/**
* Unstars all messages from all channels
*
- * @returns {$.Promise}
+ * @returns {Promise}
*/
unstarAll: function () {
return this._rpc({
@@ -448,11 +448,13 @@ var MailManager = AbstractService.extend({
* @param {string} [data.state] e.g. 'open', 'folded'
* @param {Object|integer} [options=undefined]
* @param {boolean} [options.silent=false]
- * @returns {integer} the ID of the newly or already existing channel
+ * @returns {Promise<integer>} resolves with the ID of the newly or already
+ * existing channel
*/
_addChannel: function (data, options) {
options = typeof options === 'object' ? options : {};
var channel = this.getChannel(data.id);
+ var proms = [];
if (!channel) {
channel = this._makeChannel(data, options);
if (channel.getType() === 'dm_chat') {
@@ -462,14 +464,16 @@ var MailManager = AbstractService.extend({
if (data.last_message) {
// channel_info in mobile, necessary for showing channel
// preview in mobile
- this.addMessage(data.last_message);
+ proms.push(this.addMessage(data.last_message));
}
this._sortThreads();
if (!options.silent) {
- this._mailBus.trigger('new_channel', channel);
+ this._mailBus.trigger('new_channel', channel, proms);
}
}
- return channel.getID();
+ return Promise.all(proms).then(function () {
+ return channel.getID();
+ });
},
/**
* Add a new mailbox
@@ -516,21 +520,23 @@ var MailManager = AbstractService.extend({
* @private
* @param {Object} data
* @param {Object} options
- * @returns {mail.model.Message}
+ * @return {Promise<mail.model.Message>}
*/
_addNewMessage: function (data, options) {
+ var self = this;
var message = this._makeMessage(data);
// Keep the array ordered by ID when inserting the new message
var index = _.sortedIndex(this._messages, message, function (msg) {
return msg.getID();
});
this._messages.splice(index, 0, message);
- this._addNewMessagePostprocessThread(message, options);
- this._addMessageToThreads(message, options);
- if (!options.silent) {
- this._mailBus.trigger('new_message', message);
- }
- return message;
+ return this._addNewMessagePostprocessThread(message, options).then(function () {
+ self._addMessageToThreads(message, options);
+ if (!options.silent) {
+ self._mailBus.trigger('new_message', message);
+ }
+ return message;
+ });
},
/**
* For newly added message, postprocess threads linked to this message
@@ -541,9 +547,11 @@ var MailManager = AbstractService.extend({
* @param {Array} [options.domain]
* @param {boolean} [options.incrementUnread]
* @param {boolean} [options.showNotification]
+ * @returns {Promise}
*/
_addNewMessagePostprocessThread: function (message, options) {
var self = this;
+ var proms = [];
_.each(message.getThreadIDs(), function (threadID) {
var thread = self.getThread(threadID);
if (thread) {
@@ -553,6 +561,7 @@ var MailManager = AbstractService.extend({
!message.isSystemNotification()
) {
if (thread.isTwoUserThread() && options.showNotification) {
+ var prom = Promise.resolve();
if (
!self._isDiscussOpen() &&
!config.device.isMobile &&
@@ -560,17 +569,21 @@ var MailManager = AbstractService.extend({
) {
// automatically open thread window
// while keeping it unread
- thread.detach({ passively: true });
- }
- var query = { isVisible: false };
- self._mailBus.trigger('is_thread_bottom_visible', thread, query);
- if (!self.call('bus_service', 'isOdooFocused') || !query.isVisible) {
- self._notifyIncomingMessage(message);
+ prom = thread.detach({ passively: true });
}
+ proms.push(prom);
+ prom.then(function () {
+ var query = { isVisible: false };
+ self._mailBus.trigger('is_thread_bottom_visible', thread, query);
+ if (!self.call('bus_service', 'isOdooFocused') || !query.isVisible) {
+ self._notifyIncomingMessage(message);
+ }
+ });
}
}
}
});
+ return Promise.all(proms);
},
/**
* Create a Channel (other than a DM)
@@ -578,7 +591,7 @@ var MailManager = AbstractService.extend({
* @private
* @param {string} name
* @param {string} type
- * @returns {$.Promise<integer>} ID of the created channel
+ * @returns {Promise<integer>} ID of the created channel
*/
_createChannel: function (name, type) {
var context = _.extend({ isMobile: config.device.isMobile }, session.user_context);
@@ -595,7 +608,7 @@ var MailManager = AbstractService.extend({
*
* @private
* @param {string} name
- * @returns {$.Promise<integer>} ID of the created channel
+ * @returns {Promise<integer>} ID of the created channel
*/
_createDMChat: function (name) {
var context = _.extend({ isMobile: config.device.isMobile }, session.user_context);
@@ -610,7 +623,7 @@ var MailManager = AbstractService.extend({
/**
* @private
* @param {integer[]} channelIDs
- * @returns {$.Promise<Object[]>} resolved with list of channel preview
+ * @returns {Promise<Object[]>} resolved with list of channel preview
*/
_fetchChannelPreviews: function (channelIDs) {
return this._rpc({
@@ -652,7 +665,7 @@ var MailManager = AbstractService.extend({
*
* @private
* @param {mail.model.Channel[]} channels
- * @returns {$.Deferred<Object[]>} resolved with list of channel previews
+ * @returns {Promise<Object[]>} resolved with list of channel previews
*/
_getChannelPreviews: function (channels) {
var self = this;
@@ -667,19 +680,22 @@ var MailManager = AbstractService.extend({
});
fetchDef = this._fetchChannelPreviews(ids);
} else {
- fetchDef = $.when();
+ fetchDef = Promise.resolve();
}
return fetchDef.then(function (fetchedPreviews) {
// add fetched messages
+ var proms = [];
_.each(fetchedPreviews, function (fetchedPreview) {
if (fetchedPreview.last_message) {
- self.addMessage(fetchedPreview.last_message);
+ proms.push(self.addMessage(fetchedPreview.last_message));
}
// mark the channel as previewed, so that we do not need to
// fetch preview again
var channel = self.getChannel(fetchedPreview.id);
channel.markAsPreviewed();
});
+ return Promise.all(proms);
+ }).then(function () {
return _.map(channels, function (channel) {
return channel.getPreview();
});
@@ -694,7 +710,7 @@ var MailManager = AbstractService.extend({
* the documentID is omitted for a model preview, whereas it is set for a
* preview of a failure related to a document.
*
- * @returns {$.Promise<Object[]>} resolved with previews of mail failures
+ * @returns {Promise<Object[]>} resolved with previews of mail failures
*/
_getMailFailurePreviews: function () {
// items = list of objects:
@@ -754,7 +770,7 @@ var MailManager = AbstractService.extend({
* @private
* @param {string|undefined} [filter] the filter to apply on channel
* previews in systray messaging menu
- * @returns {$.Promise<Object[]>} resolved with object valid for template
+ * @returns {Promise<Object[]>} resolved with object valid for template
* mail.Preview on channel previews, based on selected filter
*/
_getSystrayChannelPreviews: function (filter) {
@@ -796,7 +812,7 @@ var MailManager = AbstractService.extend({
*
* @private
* @param {string|undefined} [filter]
- * @returns {$.Deferred<Object[]>} resolved with valid objects for template
+ * @returns {Promise<Object[]>} resolved with valid objects for template
* mail.Preview on inbox message previews
*/
_getSystrayInboxPreviews: function (filter) {
@@ -806,7 +822,7 @@ var MailManager = AbstractService.extend({
var inbox = this.getMailbox('inbox');
return inbox.getMessagePreviews();
} else {
- return $.when([]);
+ return Promise.resolve([]);
}
},
/**
@@ -820,7 +836,7 @@ var MailManager = AbstractService.extend({
if (filter === 'mailbox_inbox' || !filter) {
return this._getMailFailurePreviews();
} else {
- return $.when([]);
+ return Promise.resolve([]);
}
},
/**
@@ -863,7 +879,7 @@ var MailManager = AbstractService.extend({
* @private
* @param {integer|string} channelID
* @param {Object} options options passed on channel add
- * @returns {$.Promise<integer>} channelID of joined and added channel
+ * @returns {Promise<integer>} channelID of joined and added channel
*/
_joinAndAddChannel: function (channelID, options) {
var self = this;
@@ -941,7 +957,7 @@ var MailManager = AbstractService.extend({
this._toNotifyChannelFetchedIDs = [];
if (_.isEmpty(channelIDs)) {
// no channel to notify fetched
- return $.when();
+ return Promise.resolve();
}
return this._rpc({
model: 'mail.channel',
@@ -1098,7 +1114,7 @@ var MailManager = AbstractService.extend({
* @private
* @param {string} searchVal
* @param {integer} limit
- * @returns {$.Promise<Object[]>} fetched partners matching 'searchVal'
+ * @returns {Promise<Object[]>} fetched partners matching 'searchVal'
*/
_searchPartnerFetch: function (searchVal, limit) {
return this._rpc({
@@ -1194,12 +1210,17 @@ var MailManager = AbstractService.extend({
* (e.g. list of public channel data are stored in 'channel_channel')
* @param {Object[]} [data.channel_slots[i] list of data of channel of type
* `i`
+ * @returns {Promise}
*/
_updateChannelsFromServer: function (data) {
var self = this;
+ var proms = [];
_.each(data.channel_slots, function (channels) {
- _.each(channels, self._addChannel.bind(self));
+ _.each(channels, function (channel) {
+ proms.push(self._addChannel(channel));
+ });
});
+ return Promise.all(proms);
},
/**
* Update commands from mail data fetched from the server
@@ -1221,11 +1242,12 @@ var MailManager = AbstractService.extend({
* @param {Array<Object[]>} result.mention_partner_suggestions list of
* suggestions.
* @param {integer} result.menu_id the menu ID of discuss app
+ * @returns {Promise}
*/
_updateInternalStateFromServer: function (result) {
// commands are needed for channel instantiation
this._updateCommandsFromServer(result);
- this._updateChannelsFromServer(result);
+ var prom = this._updateChannelsFromServer(result);
this._updateModerationSettingsFromServer(result);
this._updateMailboxesFromServer(result);
this._updateMailFailuresFromServer(result);
@@ -1233,6 +1255,8 @@ var MailManager = AbstractService.extend({
this._mentionPartnerSuggestions = result.mention_partner_suggestions;
this._discussMenuID = result.menu_id;
+
+ return prom;
},
/**
* Update the mailboxes with mail data fetched from server, namely 'Inbox',
diff --git a/addons/mail/static/src/js/services/mail_notification_manager.js b/addons/mail/static/src/js/services/mail_notification_manager.js
index fb3527b2b90..75754f375d8 100644
--- a/addons/mail/static/src/js/services/mail_notification_manager.js
+++ b/addons/mail/static/src/js/services/mail_notification_manager.js
@@ -101,12 +101,12 @@ MailManager.include({
channelAlreadyInCache = !!this.getChannel(messageData.channel_ids[0]);
def = this.joinChannel(messageData.channel_ids[0], { autoswitch: false });
} else {
- def = $.when();
+ def = Promise.resolve();
}
def.then(function () {
// don't increment unread if channel wasn't in cache yet as
// its unread counter has just been fetched
- self.addMessage(messageData, {
+ return self.addMessage(messageData, {
showNotification: true,
incrementUnread: channelAlreadyInCache
});
@@ -179,18 +179,19 @@ MailManager.include({
_handleNeedactionNotification: function (messageData) {
var self = this;
var inbox = this.getMailbox('inbox');
- var message = this.addMessage(messageData, {
+ this.addMessage(messageData, {
incrementUnread: true,
showNotification: true,
+ }).then(function (message) {
+ inbox.incrementMailboxCounter();
+ _.each(message.getThreadIDs(), function (threadID) {
+ var channel = self.getChannel(threadID);
+ if (channel) {
+ channel.incrementNeedactionCounter();
+ }
+ });
+ self._mailBus.trigger('update_needaction', inbox.getMailboxCounter());
});
- inbox.incrementMailboxCounter();
- _.each(message.getThreadIDs(), function (threadID) {
- var channel = self.getChannel(threadID);
- if (channel) {
- channel.incrementNeedactionCounter();
- }
- });
- this._mailBus.trigger('update_needaction', inbox.getMailboxCounter());
},
/**
* Called when an activity record has been updated on the server
@@ -381,8 +382,10 @@ MailManager.include({
* @param {Object} data.message data of message
*/
_handlePartnerMessageModeratorNotification: function (data) {
- this.addMessage(data.message);
- this._mailBus.trigger('update_moderation_counter');
+ var self = this;
+ this.addMessage(data.message).then(function () {
+ self._mailBus.trigger('update_moderation_counter');
+ });
},
/**
* On receiving a notification that is specific to a user
diff --git a/addons/mail/static/src/js/services/mail_status_manager.js b/addons/mail/static/src/js/services/mail_status_manager.js
index 5ca151d47bf..4a2df2af94f 100644
--- a/addons/mail/static/src/js/services/mail_status_manager.js
+++ b/addons/mail/static/src/js/services/mail_status_manager.js
@@ -81,7 +81,7 @@ MailManager.include({
var self = this;
var partnerIDs = data.partnerIDs;
if (_.isEmpty(partnerIDs)) {
- return $.when();
+ return Promise.resolve();
}
return this._rpc({
model: 'res.partner',
diff --git a/addons/mail/static/src/js/services/mail_window_manager.js b/addons/mail/static/src/js/services/mail_window_manager.js
index 4e481d6892a..083b46c9ff2 100644
--- a/addons/mail/static/src/js/services/mail_window_manager.js
+++ b/addons/mail/static/src/js/services/mail_window_manager.js
@@ -94,6 +94,7 @@ MailManager.include({
* is not open yet, and do nothing otherwise.
* @param {boolean} [options.keepFoldState=false] if set to true, keep the
* fold state of the thread
+ * @returns {Promise}
*/
openThreadWindow: function (threadID, options) {
var self = this;
@@ -108,10 +109,10 @@ MailManager.include({
return;
}
var threadWindow = this._getThreadWindow(threadID);
- var def = $.when();
+ var prom = Promise.resolve();
if (!threadWindow) {
thread.isCreatingWindow = true;
- def = thread.fetchMessages().then(function () {
+ prom = thread.fetchMessages().then(function () {
threadWindow = self._makeNewThreadWindow(thread, options);
self._placeNewThreadWindow(threadWindow, options.passively);
return threadWindow.appendTo($(self.THREAD_WINDOW_APPENDTO));
@@ -126,12 +127,12 @@ MailManager.include({
) {
thread.markAsRead();
}
- }).fail(function () {
+ thread.isCreatingWindow = false;
+ }).guardedCatch(function () {
// thread window could not be open, which may happen due to
// access error while fetching messages to the document.
// abort opening the thread window in this case.
thread.close();
- }).always(function () {
thread.isCreatingWindow = false;
});
} else if (!options.passively) {
@@ -139,7 +140,7 @@ MailManager.include({
this._makeThreadWindowVisible(threadWindow);
}
}
- def.then(function () {
+ return prom.then(function () {
threadWindow.updateVisualFoldState();
});
},
@@ -155,14 +156,16 @@ MailManager.include({
*/
updateThreadWindow: function (threadID, options) {
var thread = this.getThread(threadID);
+ var prom = Promise.resolve();
if (thread) {
if (thread.isDetached()) {
_.extend(options, { keepFoldState: true });
- this.openThreadWindow(threadID, options);
+ prom = this.openThreadWindow(threadID, options);
} else {
this._closeThreadWindow(threadID);
}
}
+ return prom;
},
//--------------------------------------------------------------------------
@@ -429,7 +432,7 @@ MailManager.include({
*
* @private
* @param {integer} partnerID
- * @returns {$.Promise<integer>} resolved with ID of the DM chat
+ * @returns {Promise<integer>} resolved with ID of the DM chat
*/
_openAndDetachDMChat: function (partnerID) {
return this._rpc({
@@ -647,10 +650,16 @@ MailManager.include({
*
* @private
* @param {mail.model.Channel} channel
+ * @param {Promise[]} proms used to synchronize async operations on the
+ * channel (like the rendering of its window)
*/
- _onNewChannel: function (channel) {
+ _onNewChannel: function (channel, proms) {
if (channel.isDetached()) {
- this.openThreadWindow(channel.getID(), { keepFoldState: true, passively: true });
+ var prom = this.openThreadWindow(channel.getID(), {
+ keepFoldState: true,
+ passively: true,
+ });
+ proms.push(prom);
} else {
this._closeThreadWindow(channel.getID());
}
diff --git a/addons/mail/static/src/js/systray/systray_activity_menu.js b/addons/mail/static/src/js/systray/systray_activity_menu.js
index 593cac91506..fae95a78c2f 100644
--- a/addons/mail/static/src/js/systray/systray_activity_menu.js
+++ b/addons/mail/static/src/js/systray/systray_activity_menu.js
@@ -20,7 +20,7 @@ var ActivityMenu = Widget.extend({
'show.bs.dropdown': '_onActivityMenuShow',
},
willStart: function () {
- return $.when(this.call('mail_service', 'isReady'));
+ return Promise.resolve(this.call('mail_service', 'isReady'));
},
start: function () {
this._$activitiesPreview = this.$('.o_mail_systray_dropdown_items');
diff --git a/addons/mail/static/src/js/systray/systray_messaging_menu.js b/addons/mail/static/src/js/systray/systray_messaging_menu.js
index df35de47174..4dacae435d4 100644
--- a/addons/mail/static/src/js/systray/systray_messaging_menu.js
+++ b/addons/mail/static/src/js/systray/systray_messaging_menu.js
@@ -30,7 +30,7 @@ var MessagingMenu = Widget.extend({
* @override
*/
willStart: function () {
- return $.when(this._super.apply(this, arguments), this.call('mail_service', 'isReady'));
+ return Promise.all([this._super.apply(this, arguments), this.call('mail_service', 'isReady')]);
},
/**
* @override
@@ -112,7 +112,7 @@ var MessagingMenu = Widget.extend({
},
/**
* @private
- * @returns {$.Promise<Object[]>} resolved with list of previews that are
+ * @returns {Promise<Object[]>} resolved with list of previews that are
* compatible with the 'mail.Preview' template.
*/
_getPreviews: function () {
diff --git a/addons/mail/static/src/js/thread_field.js b/addons/mail/static/src/js/thread_field.js
index a3807802ad7..ab8023b06ad 100644
--- a/addons/mail/static/src/js/thread_field.js
+++ b/addons/mail/static/src/js/thread_field.js
@@ -57,7 +57,7 @@ var ThreadField = AbstractField.extend({
var def1 = this._threadWidget.appendTo(this.$el);
var def2 = this._super.apply(this, arguments);
- return this.alive($.when(def1, def2)).then(function () {
+ return this.alive(Promise.all([def1, def2])).then(function () {
// unwrap the thread to remove an unnecessary level on div
self.setElement(self._threadWidget.$el);
var mailBus = self.call('mail_service', 'getMailBus');
@@ -86,7 +86,7 @@ var ThreadField = AbstractField.extend({
/**
* @param {Object} message
* @param {integer[]} message.partner_ids
- * @return {$.Promise}
+ * @return {Promise}
*/
postMessage: function (message) {
var self = this;
@@ -95,9 +95,9 @@ var ThreadField = AbstractField.extend({
if (message.partner_ids.length) {
self.trigger_up('reload_mail_fields', { followers: true });
}
- })
- .fail(function () {
+ }).guardedCatch(function () {
self.do_notify(_t("Sending Error"), _t("Your message has not been sent."));
+ return Promise.reject();
});
},
@@ -109,7 +109,7 @@ var ThreadField = AbstractField.extend({
* @private
* @param {Object} [options]
* @param {boolean} [options.forceFetch]
- * @return {$.Deferred}
+ * @return {Promise}
*/
_fetchAndRenderThread: function (options) {
var self = this;
@@ -117,7 +117,7 @@ var ThreadField = AbstractField.extend({
var thread = new CreateModeDocumentThread();
options = { isCreateMode: true };
self._threadWidget.render(thread, options);
- return $.when();
+ return Promise.resolve();
} else {
var fetchDef = this.dp.add(this._documentThread.fetchMessages(options));
return fetchDef.then(function () {
@@ -134,7 +134,7 @@ var ThreadField = AbstractField.extend({
/**
* @override
* @private
- * @returns {$.Deferred}
+ * @returns {Promise}
*/
_render: function () {
return this._fetchAndRenderThread();
diff --git a/addons/mail/static/src/js/thread_widget.js b/addons/mail/static/src/js/thread_widget.js
index cbac2c3b417..56945533946 100644
--- a/addons/mail/static/src/js/thread_widget.js
+++ b/addons/mail/static/src/js/thread_widget.js
@@ -248,16 +248,16 @@ var ThreadWidget = Widget.extend({
*/
removeMessageAndRender: function (messageID, thread, options) {
var self = this;
- var done = $.Deferred();
- this.$('.o_thread_message[data-message-id="' + messageID + '"]')
+ return new Promise(function (resolve, reject) {
+ self.$('.o_thread_message[data-message-id="' + messageID + '"]')
.fadeOut({
done: function () {
self.render(thread, options);
- done.resolve();
+ resolve();
},
duration: 200,
});
- return done;
+ });
},
/**
* Scroll to the bottom of the thread
@@ -273,7 +273,7 @@ var ThreadWidget = Widget.extend({
* @param {boolean} [options.onlyIfNecessary]
*/
scrollToMessage: function (options) {
- var $target = this.$('.o_thread_message[data-message-id="' + options.msgID + '"]');
+ var $target = this.$('.o_thread_message[data-message-id="' + options.messageID + '"]');
if (options.onlyIfNecessary) {
var delta = $target.parent().height() - $target.height();
var offset = delta < 0 ?
diff --git a/addons/mail/static/src/js/thread_windows/abstract_thread_window.js b/addons/mail/static/src/js/thread_windows/abstract_thread_window.js
index 300bfb11a3e..ff5acfea0d2 100644
--- a/addons/mail/static/src/js/thread_windows/abstract_thread_window.js
+++ b/addons/mail/static/src/js/thread_windows/abstract_thread_window.js
@@ -95,7 +95,7 @@ var AbstractThreadWindow = Widget.extend({
var def = this._threadWidget.replace(this.$('.o_thread_window_content')).then(function () {
self._threadWidget.$el.on('scroll', self, self._debouncedOnScroll);
});
- return $.when(this._super(), def);
+ return Promise.all([this._super(), def]);
},
/**
* @override
diff --git a/addons/mail/static/src/js/thread_windows/thread_window.js b/addons/mail/static/src/js/thread_windows/thread_window.js
index e5496e0bc3c..9999014a08d 100644
--- a/addons/mail/static/src/js/thread_windows/thread_window.js
+++ b/addons/mail/static/src/js/thread_windows/thread_window.js
@@ -83,7 +83,7 @@ var ThreadWindow = AbstractThreadWindow.extend({
}
this._updateOutOfOfficeReadMoreLessButton();
- return $.when(superDef, composerDef);
+ return Promise.all([superDef, composerDef]);
},
//--------------------------------------------------------------------------
@@ -241,7 +241,7 @@ var ThreadWindow = AbstractThreadWindow.extend({
autoFocus: true,
source: function (request, response) {
self.call('mail_service', 'searchPartner', request.term, 10)
- .done(response);
+ .then(response);
},
select: function (event, ui) {
// remember partner ID so that we can replace this window
diff --git a/addons/mail/static/src/js/views/activity/activity_model.js b/addons/mail/static/src/js/views/activity/activity_model.js
index 738cdb55ca1..f5a2feee988 100644
--- a/addons/mail/static/src/js/views/activity/activity_model.js
+++ b/addons/mail/static/src/js/views/activity/activity_model.js
@@ -19,7 +19,7 @@ var ActivityModel = AbstractModel.extend({
* @override
* @param {Object} params
* @param {Array[]} params.domain
- * @returns {Deferred}
+ * @returns {Promise}
*/
load: function (params) {
this.domain = params.domain;
@@ -31,7 +31,7 @@ var ActivityModel = AbstractModel.extend({
* @param {any} handle
* @param {Object} params
* @param {Array[]} params.domain
- * @returns {Deferred}
+ * @returns {Promise}
*/
reload: function (handle, params) {
if (params && 'domain' in params) {
@@ -48,7 +48,7 @@ var ActivityModel = AbstractModel.extend({
* Fetch activity data.
*
* @private
- * @returns {Deferred}
+ * @returns {Promise}
*/
_fetchData: function () {
var self = this;
diff --git a/addons/mail/static/src/js/views/activity/activity_renderer.js b/addons/mail/static/src/js/views/activity/activity_renderer.js
index d139a4e84cd..75eb25367e4 100644
--- a/addons/mail/static/src/js/views/activity/activity_renderer.js
+++ b/addons/mail/static/src/js/views/activity/activity_renderer.js
@@ -5,8 +5,8 @@ var AbstractRenderer = require('web.AbstractRenderer');
var core = require('web.core');
var field_registry = require('web.field_registry');
-var QWeb = core.qweb;
var _t = core._t;
+var QWeb = core.qweb;
var ActivityRenderer = AbstractRenderer.extend({
className: 'o_activity_view',
@@ -125,21 +125,22 @@ var ActivityRenderer = AbstractRenderer.extend({
};
var KanbanActivity = field_registry.get('kanban_activity');
var widget = new KanbanActivity(self, "activity_ids", record, {});
- widget.appendTo($td);
- // replace clock by closest deadline
- var $date = $('<div>');
- var formated_date = moment(activity_group.o_closest_deadline).format('ll');
- var current_year = (new Date()).getFullYear();
- if (formated_date.endsWith(current_year)) { // Dummy logic to remove year (only if current year), we will maybe need to improve it
- formated_date = formated_date.slice(0, -4);
- formated_date = formated_date.replace(/( |,)*$/g, "");
- }
- $date
- .text(formated_date)
- .addClass('o_closest_deadline');
- $td.find('a')
- .empty()
- .append($date);
+ widget.appendTo($td).then(function() {
+ // replace clock by closest deadline
+ var $date = $('<div>');
+ var formated_date = moment(activity_group.o_closest_deadline).format('ll');
+ var current_year = (new Date()).getFullYear();
+ if (formated_date.endsWith(current_year)) { // Dummy logic to remove year (only if current year), we will maybe need to improve it
+ formated_date = formated_date.slice(0, -4);
+ formated_date = formated_date.replace(/( |,)*$/g, "");
+ }
+ $date
+ .text(formated_date)
+ .addClass('o_closest_deadline');
+ $td.find('a')
+ .empty()
+ .append($date);
+ });
return $td;
});
var $tr = $('<tr/>', {class: 'o_data_row'})
diff --git a/addons/mail/static/tests/activity_tests.js b/addons/mail/static/tests/activity_tests.js
index 19f4f6eaf5d..4e3e509936c 100644
--- a/addons/mail/static/tests/activity_tests.js
+++ b/addons/mail/static/tests/activity_tests.js
@@ -162,19 +162,19 @@ QUnit.module('activity view', {
}
});
-QUnit.test('activity view: simple activity rendering', function (assert) {
+QUnit.test('activity view: simple activity rendering', async function (assert) {
assert.expect(7);
- var activity = createView({
+ var activity = await createView({
View: ActivityView,
model: 'task',
data: this.data,
arch: '<activity string="Task"/>',
mockRPC: function(route, args) {
if (args.method === 'get_activity_data') {
- return $.when(ACTIVITY_DATA);
+ return Promise.resolve(ACTIVITY_DATA);
}
return this._super(route, args);
- }
+ },
});
assert.containsOnce(activity, 'table',
@@ -194,16 +194,16 @@ QUnit.test('activity view: simple activity rendering', function (assert) {
activity.destroy();
});
-QUnit.test('activity view: no content rendering', function (assert) {
+QUnit.test('activity view: no content rendering', async function (assert) {
assert.expect(2);
- var activity = createView({
+ var activity = await createView({
View: ActivityView,
model: 'task',
data: this.data,
arch: '<activity string="Task"/>',
mockRPC: function (route, args) {
if (args.method === 'get_activity_data') {
- return $.when({ activity_types: [] });
+ return Promise.resolve({ activity_types: [] });
}
return this._super(route, args);
},
@@ -218,20 +218,20 @@ QUnit.test('activity view: no content rendering', function (assert) {
activity.destroy();
});
-QUnit.test('activity view: batch send mail on activity', function (assert) {
+QUnit.test('activity view: batch send mail on activity', async function (assert) {
assert.expect(6);
- var activity = createView({
+ var activity = await createView({
View: ActivityView,
model: 'task',
data: this.data,
arch: '<activity string="Task"/>',
mockRPC: function(route, args) {
if (args.method === 'activity_send_mail'){
- assert.step(args.args);
- return $.when();
+ assert.step(JSON.stringify(args.args));
+ return Promise.resolve();
}
if (args.method === 'get_activity_data') {
- return $.when(ACTIVITY_DATA);
+ return Promise.resolve(ACTIVITY_DATA);
}
return this._super(route, args);
},
@@ -250,16 +250,16 @@ QUnit.test('activity view: batch send mail on activity', function (assert) {
testUtils.dom.click(activity.$('table thead tr:first th:nth-child(2) span:nth-child(2) i.fa-ellipsis-v'));
testUtils.dom.click(activity.$('table thead tr:first th:nth-child(2) span:nth-child(2) .dropdown-menu.show .o_send_mail_template:nth-child(2):contains(Task: Reception Acknowledgment)'));
assert.verifySteps([
- [[13, 30], 9], //send mail template 9 on tasl 13 and 30
- [[13, 30], 8] //send mail template 8 on tasl 13 and 30
+ '[[13,30],9]', // send mail template 9 on tasks 13 and 30
+ '[[13,30],8]', // send mail template 8 on tasks 13 and 30
]);
activity.destroy();
});
-QUnit.test('activity view: activity widget', function (assert) {
+QUnit.test('activity view: activity widget', async function (assert) {
assert.expect(16);
- var activity = createView({
+ var activity = await createView({
View: ActivityView,
model: 'task',
data: this.data,
@@ -268,16 +268,16 @@ QUnit.test('activity view: activity widget', function (assert) {
if (args.method === 'activity_send_mail'){
assert.deepEqual([[30],8],args.args, "Should send template 8 on record 30");
assert.step('activity_send_mail');
- return $.when();
+ return Promise.resolve();
}
if (args.method === 'action_feedback_schedule_next'){
assert.deepEqual([[3]],args.args, "Should execute action_feedback_schedule_next on activity 3 only ");
assert.equal(args.kwargs.feedback, "feedback2");
assert.step('action_feedback_schedule_next');
- return $.when({serverGeneratedAction: true});
+ return Promise.resolve({serverGeneratedAction: true});
}
if (args.method === 'get_activity_data') {
- return $.when(ACTIVITY_DATA);
+ return Promise.resolve(ACTIVITY_DATA);
}
return this._super(route, args);
},
@@ -305,12 +305,12 @@ QUnit.test('activity view: activity widget', function (assert) {
assert.step("Unexpected action");
}
},
- }
+ },
});
var today = activity.$('table tbody tr:first td:nth-child(2).today');
var dropdown = today.find('.dropdown-menu.o_activity');
- testUtils.dom.click(today.find('.o_closest_deadline'));
+ await testUtils.dom.click(today.find('.o_closest_deadline'));
assert.hasClass(dropdown,'show', "dropdown should be displayed");
assert.ok(dropdown.find('.o_activity_color_today:contains(Today)').length, "Title should be today");
assert.ok(dropdown.find('.o_activity_title_entry[data-activity-id="2"]:first div:contains(template8)').length,
@@ -318,20 +318,20 @@ QUnit.test('activity view: activity widget', function (assert) {
assert.ok(dropdown.find('.o_activity_title_entry[data-activity-id="2"]:eq(1) div:contains(template9)').length,
"template9 should be available");
- testUtils.dom.click(dropdown.find('.o_activity_title_entry[data-activity-id="2"]:first .o_activity_template_preview'));
- testUtils.dom.click(dropdown.find('.o_activity_title_entry[data-activity-id="2"]:first .o_activity_template_send'));
+ await testUtils.dom.click(dropdown.find('.o_activity_title_entry[data-activity-id="2"]:first .o_activity_template_preview'));
+ await testUtils.dom.click(dropdown.find('.o_activity_title_entry[data-activity-id="2"]:first .o_activity_template_send'));
var overdue = activity.$('table tbody tr:first td:nth-child(3).overdue');
- testUtils.dom.click(overdue.find('.o_closest_deadline'));
+ await testUtils.dom.click(overdue.find('.o_closest_deadline'));
dropdown = overdue.find('.dropdown-menu.o_activity');
assert.notOk(dropdown.find('.o_activity_title div div div:first span').length,
"No template should be available");
- testUtils.dom.click(dropdown.find('.o_schedule_activity'));
- testUtils.dom.click(overdue.find('.o_closest_deadline'));
- testUtils.dom.click(dropdown.find('.o_mark_as_done'));
+ await testUtils.dom.click(dropdown.find('.o_schedule_activity'));
+ await testUtils.dom.click(overdue.find('.o_closest_deadline'));
+ await testUtils.dom.click(dropdown.find('.o_mark_as_done'));
dropdown.find('#activity_feedback').val("feedback2");
- testUtils.dom.click(dropdown.find('.o_activity_popover_done_next'));
+ await testUtils.dom.click(dropdown.find('.o_activity_popover_done_next'));
assert.verifySteps([
"do_action_compose",
"activity_send_mail",
@@ -342,10 +342,10 @@ QUnit.test('activity view: activity widget', function (assert) {
activity.destroy();
});
-QUnit.test('activity view: no group_by_menu and no time_range_menu', function (assert) {
+QUnit.test('activity view: no group_by_menu and no time_range_menu', async function (assert) {
assert.expect(4);
- var actionManager = createActionManager({
+ var actionManager = await createActionManager({
actions: [{
id: 1,
name: 'Task Action',
@@ -365,13 +365,13 @@ QUnit.test('activity view: no group_by_menu and no time_range_menu', function (a
if (args.method === 'get_activity_data') {
assert.deepEqual(args.kwargs.context, {lang: 'zz_ZZ'},
'The context should have been passed');
- return $.when(ACTIVITY_DATA);
+ return Promise.resolve(ACTIVITY_DATA);
}
return this._super(route, args);
},
});
- actionManager.doAction(1);
+ await actionManager.doAction(1);
assert.containsN(actionManager, '.o_search_options .o_dropdown button:visible', 2,
"only two elements should be available in view search");
diff --git a/addons/mail/static/tests/chatter_tests.js b/addons/mail/static/tests/chatter_tests.js
index 7aaa35ac4e3..08f5c01fc34 100644
--- a/addons/mail/static/tests/chatter_tests.js
+++ b/addons/mail/static/tests/chatter_tests.js
@@ -3,13 +3,11 @@ odoo.define('mail.chatter_tests', function (require) {
var mailTestUtils = require('mail.testUtils');
-var concurrency = require('web.concurrency');
var core = require('web.core');
var FormView = require('web.FormView');
var KanbanView = require('web.KanbanView');
var testUtils = require('web.test_utils');
-var createAsyncView = testUtils.createAsyncView;
var createView = testUtils.createView;
var Activity = require('mail.Activity');
@@ -192,13 +190,12 @@ QUnit.module('Chatter', {
}
});
-QUnit.test('basic rendering', function (assert) {
+QUnit.test('basic rendering', async function (assert) {
assert.expect(9);
var count = 0;
var unwanted_read_count = 0;
-
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -219,7 +216,7 @@ QUnit.test('basic rendering', function (assert) {
}
if (route === '/mail/read_followers') {
count++;
- return $.when({
+ return Promise.resolve({
followers: [],
subtypes: [],
});
@@ -228,25 +225,24 @@ QUnit.test('basic rendering', function (assert) {
},
res_id: 2,
});
-
- assert.ok(form.$('.o_mail_activity').length, "there should be an activity widget");
- assert.ok(form.$('.o_chatter_topbar .o_chatter_button_schedule_activity').length,
- "there should be a 'Schedule an activity' button in the chatter's topbar");
- assert.ok(form.$('.o_chatter_topbar .o_followers').length,
- "there should be a followers widget, moved inside the chatter's topbar");
- assert.ok(form.$('.o_chatter').length, "there should be a chatter widget");
- assert.ok(form.$('.o_mail_thread').length, "there should be a mail thread");
+ assert.containsOnce(form, '.o_mail_activity', "there should be an activity widget");
+ assert.containsOnce(form, '.o_chatter_topbar .o_chatter_button_schedule_activity',
+ "there should be a 'Schedule an activity' button in the chatter's topbar");
+ assert.containsOnce(form, '.o_chatter_topbar .o_followers',
+ "there should be a followers widget, moved inside the chatter's topbar");
+ assert.containsOnce(form, '.o_chatter', "there should be a chatter widget");
+ assert.containsOnce(form, '.o_mail_thread');
assert.containsOnce(form, '.o_chatter_button_attachment', "should have one attachment button");
- assert.ok(!form.$('.o_chatter_topbar .o_chatter_button_log_note').length,
+ assert.containsNone(form, '.o_chatter_topbar .o_chatter_button_log_note',
"log note button should not be available");
- testUtils.form.clickEdit(form);
+ await testUtils.form.clickEdit(form);
assert.strictEqual(count, 0, "should have done no read_followers rpc as there are no followers");
assert.strictEqual(unwanted_read_count, 0, "followers should only be fetched with read_followers route");
form.destroy();
});
-QUnit.test('Activity Done keep feedback on blur', function (assert) {
+QUnit.test('Activity Done keep feedback on blur', async function (assert) {
assert.expect(3);
var done = assert.async();
@@ -255,8 +251,8 @@ QUnit.test('Activity Done keep feedback on blur', function (assert) {
];
this.data.partner.records[0].activity_ids = [1];
- var shownDef = $.Deferred();
- var hiddenDef = $.Deferred();
+ var shownDef = testUtils.makeTestPromise();
+ var hiddenDef = testUtils.makeTestPromise();
testUtils.mock.patch(Activity, {
_bindPopoverFocusout: function () {
this._super.apply(this, arguments);
@@ -264,7 +260,7 @@ QUnit.test('Activity Done keep feedback on blur', function (assert) {
},
});
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -276,7 +272,6 @@ QUnit.test('Activity Done keep feedback on blur', function (assert) {
'</div>' +
'</form>',
});
-
// sanity checks
var $activityEl = form.$('.o_mail_activity[name=activity_ids]');
assert.strictEqual($activityEl.find('.o_thread_message').length, 1,
@@ -288,18 +283,18 @@ QUnit.test('Activity Done keep feedback on blur', function (assert) {
$popoverEl.on('hidden.bs.popover', hiddenDef.resolve.bind(hiddenDef));
// open popover
- testUtils.dom.click($popoverEl);
+ await testUtils.dom.click($popoverEl);
shownDef.then(function () {
// write a feedback and focusout
var $feedbackPopover = $($popoverEl.data('bs.popover').tip);
$feedbackPopover.find('#activity_feedback').val('John Shaft').focusout();
- hiddenDef.then(function () {
- shownDef = $.Deferred();
+ hiddenDef.then(async function () {
+ shownDef = testUtils.makeTestPromise();
// re-open popover
- testUtils.dom.click($popoverEl);
+ await testUtils.dom.click($popoverEl);
shownDef.then(function () {
var $feedbackPopover = $($popoverEl.data('bs.popover').tip);
@@ -314,7 +309,7 @@ QUnit.test('Activity Done keep feedback on blur', function (assert) {
});
});
-QUnit.test('Activity Done by uploading a file', function (assert) {
+QUnit.test('Activity Done by uploading a file', async function (assert) {
assert.expect(4);
// simulate (shortcut) the upload and trigger the event when the
@@ -348,7 +343,7 @@ QUnit.test('Activity Done by uploading a file', function (assert) {
}];
this.data.partner.records[0].activity_ids = [1];
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -365,7 +360,7 @@ QUnit.test('Activity Done by uploading a file', function (assert) {
var done_ids = args.args[0];
this.data.partner.records[0].activity_ids = _.difference(current_ids, done_ids);
this.data.partner.records[0].activity_state = false;
- return $.when();
+ return Promise.resolve();
}
return this._super.apply(this, arguments);
},
@@ -379,7 +374,7 @@ QUnit.test('Activity Done by uploading a file', function (assert) {
// click on "upload" button
var $uploadBtn = $activity.find('.o_mark_as_done_upload_file');
- testUtils.dom.click($uploadBtn);
+ await testUtils.dom.click($uploadBtn);
assert.containsNone($activity, '.o_thread_message', 'The only activity should be marked as done');
@@ -387,14 +382,14 @@ QUnit.test('Activity Done by uploading a file', function (assert) {
form.destroy();
});
-QUnit.test('attachmentBox basic rendering', function (assert) {
+QUnit.test('attachmentBox basic rendering', async function (assert) {
assert.expect(19);
this.data.partner.records.push({
id: 7,
display_name: "attachment_test",
});
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -424,7 +419,7 @@ QUnit.test('attachmentBox basic rendering', function (assert) {
});
var $button = form.$('.o_chatter_button_attachment');
assert.strictEqual($button.length, 1, "should have one attachment button");
- testUtils.dom.click($button);
+ await testUtils.dom.click($button);
assert.containsOnce(form, '.o_mail_chatter_attachments',
"attachment widget should exist after a first click on the button");
assert.containsOnce(form, '.o_attachment_image', "there should be an image preview");
@@ -455,15 +450,15 @@ QUnit.test('attachmentBox basic rendering', function (assert) {
"the download URL of name1 must be correct");
assert.hasAttrValue(form.$('.o_attachment_download').eq(1), 'href', '/web/content/2?download=true',
"the download URL of name2 must be correct");
- testUtils.dom.click($button);
+ await testUtils.dom.click($button);
assert.containsNone(form, '.o_mail_chatter_attachments')
form.destroy();
});
-QUnit.test('chatter in create mode', function (assert) {
+QUnit.test('chatter in create mode', async function (assert) {
assert.expect(9);
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -479,7 +474,7 @@ QUnit.test('chatter in create mode', function (assert) {
res_id: 2,
mockRPC: function (route, args) {
if (route === "/web/dataset/call_kw/partner/message_get_suggested_recipients") {
- return $.when({2: []});
+ return Promise.resolve({2: []});
}
return this._super(route, args);
},
@@ -489,7 +484,7 @@ QUnit.test('chatter in create mode', function (assert) {
"chatter should be displayed");
// entering create mode
- testUtils.form.clickCreate(form);
+ await testUtils.form.clickCreate(form);
assert.hasClass(form.$el.find('.o_form_view'),'o_form_editable',
"we should be in create mode");
assert.containsOnce(form, '.o_chatter',
@@ -509,24 +504,24 @@ QUnit.test('chatter in create mode', function (assert) {
"the content of the message should be 'Creating a new record...'");
// getting out of create mode by saving
- testUtils.fields.editInput(form.$('.o_field_char'), 'coucou');
- testUtils.form.clickSave(form);
+ await testUtils.fields.editInput(form.$('.o_field_char'), 'coucou');
+ await testUtils.form.clickSave(form);
assert.containsOnce(form, '.o_chatter',
"chatter should still be displayed after saving from create mode");
// check if chatter buttons still work
- testUtils.dom.click(form.$('.o_chatter_button_new_message'));
+ await testUtils.dom.click(form.$('.o_chatter_button_new_message'));
assert.containsOnce(form, '.o_thread_composer:visible',
"chatter should be opened");
form.destroy();
});
-QUnit.test('chatter rendering inside the sheet', function (assert) {
+QUnit.test('chatter rendering inside the sheet', async function (assert) {
assert.expect(5);
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -546,7 +541,7 @@ QUnit.test('chatter rendering inside the sheet', function (assert) {
res_id: 2,
mockRPC: function (route, args) {
if (route === "/web/dataset/call_kw/partner/message_get_suggested_recipients") {
- return $.when({2: []});
+ return Promise.resolve({2: []});
}
return this._super(route, args);
},
@@ -555,32 +550,32 @@ QUnit.test('chatter rendering inside the sheet', function (assert) {
assert.containsOnce(form, '.o_chatter',
"chatter should be displayed");
- testUtils.form.clickCreate(form);
+ await testUtils.form.clickCreate(form);
assert.hasClass(form.$el.find('.o_form_view'),'o_form_editable',
"we should be in create mode");
assert.containsOnce(form, '.o_chatter',
"chatter should be displayed");
- testUtils.fields.editInput(form.$('.o_field_char'), 'coucou');
- testUtils.form.clickSave(form);
+ await testUtils.fields.editInput(form.$('.o_field_char'), 'coucou');
+ await testUtils.form.clickSave(form);
assert.containsOnce(form, '.o_chatter',
"chatter should be displayed");
// check if chatter buttons still work
- testUtils.dom.click(form.$('.o_chatter_button_new_message'));
+ await testUtils.dom.click(form.$('.o_chatter_button_new_message'));
assert.containsOnce(form, '.o_thread_composer:visible',
"chatter should be opened");
form.destroy();
});
-QUnit.test('kanban activity widget with no activity', function (assert) {
+QUnit.test('kanban activity widget with no activity', async function (assert) {
assert.expect(4);
var rpcCount = 0;
- var kanban = createView({
+ var kanban = await createView({
View: KanbanView,
model: 'partner',
data: this.data,
@@ -603,7 +598,7 @@ QUnit.test('kanban activity widget with no activity', function (assert) {
assert.strictEqual(rpcCount, 1, '1 RPC (search_read) should have been done');
// click on the activity button
- testUtils.dom.click($record.find('.o_activity_btn'));
+ await testUtils.dom.click($record.find('.o_activity_btn'));
assert.strictEqual(rpcCount, 1, 'no RPC should have been done as there is no activity');
assert.strictEqual($record.find('.o_no_activity').length, 1, "should have no activity scheduled");
@@ -612,7 +607,7 @@ QUnit.test('kanban activity widget with no activity', function (assert) {
kanban.destroy();
});
-QUnit.test('kanban activity widget with an activity', function (assert) {
+QUnit.test('kanban activity widget with an activity', async function (assert) {
assert.expect(12);
this.data.partner.records[0].activity_ids = [1];
@@ -628,7 +623,7 @@ QUnit.test('kanban activity widget with an activity', function (assert) {
activity_type_id: 1,
}];
var rpcCount = 0;
- var kanban = createView({
+ var kanban = await createView({
View: KanbanView,
model: 'partner',
data: this.data,
@@ -645,7 +640,7 @@ QUnit.test('kanban activity widget with an activity', function (assert) {
var done_ids = args.args[0];
this.data.partner.records[0].activity_ids = _.difference(current_ids, done_ids);
this.data.partner.records[0].activity_state = false;
- return $.when();
+ return Promise.resolve();
}
return this._super(route, args);
},
@@ -658,7 +653,7 @@ QUnit.test('kanban activity widget with an activity', function (assert) {
assert.strictEqual(rpcCount, 1, '1 RPC (search_read) should have been done');
// click on the activity button
- testUtils.dom.click($record.find('.o_activity_btn'));
+ await testUtils.dom.click($record.find('.o_activity_btn'));
assert.strictEqual(rpcCount, 2, 'a read should have been done to fetch the activity details');
assert.strictEqual($record.find('.o_activity_title').length, 1, "should have an activity scheduled");
var label = $record.find('.o_activity_log .o_activity_color_today');
@@ -666,16 +661,16 @@ QUnit.test('kanban activity widget with an activity', function (assert) {
assert.strictEqual(label.find('.badge-warning').text(), "1", "should display the correct count");
// click on the activity button to close the dropdown
- testUtils.dom.click($record.find('.o_activity_btn'));
+ await testUtils.dom.click($record.find('.o_activity_btn'));
assert.strictEqual(rpcCount, 2, 'no RPC should be done when closing the dropdown');
// click on the activity button to re-open dropdown
- testUtils.dom.click($record.find('.o_activity_btn'));
+ await testUtils.dom.click($record.find('.o_activity_btn'));
assert.strictEqual(rpcCount, 3, 'should have reloaded the activities');
// mark activity as done
- testUtils.dom.click($record.find('.o_mark_as_done'));
- testUtils.dom.click($record.find('.o_activity_popover_done'));
+ await testUtils.dom.click($record.find('.o_mark_as_done'));
+ await testUtils.dom.click($record.find('.o_activity_popover_done'));
$record = kanban.$('.o_kanban_record').first(); // the record widget has been reset
assert.strictEqual(rpcCount, 5, 'should have done an RPC to mark activity as done, and a read');
assert.ok($record.find('.o_mail_activity .o_activity_color_default:not(.o_activity_color_today)').length,
@@ -687,7 +682,7 @@ QUnit.test('kanban activity widget with an activity', function (assert) {
kanban.destroy();
});
-QUnit.test('kanban activity widget popover test', function (assert) {
+QUnit.test('kanban activity widget popover test', async function (assert) {
assert.expect(3);
this.data.partner.records[0].activity_ids = [1];
@@ -703,7 +698,7 @@ QUnit.test('kanban activity widget popover test', function (assert) {
activity_type_id: 1,
}];
var rpcCount = 0;
- var kanban = createView({
+ var kanban = await createView({
View: KanbanView,
model: 'partner',
data: this.data,
@@ -721,7 +716,7 @@ QUnit.test('kanban activity widget popover test', function (assert) {
var done_ids = args.args[0];
this.data.partner.records[0].activity_ids = _.difference(current_ids, done_ids);
this.data.partner.records[0].activity_state = false;
- return $.when();
+ return Promise.resolve();
}
return this._super(route, args);
},
@@ -729,25 +724,24 @@ QUnit.test('kanban activity widget popover test', function (assert) {
var $record = kanban.$('.o_kanban_record').first();
- testUtils.dom.click($record.find('.o_activity_btn'));
+ await testUtils.dom.click($record.find('.o_activity_btn'));
// Click on button and see popover no RPC call
- testUtils.dom.click($record.find('.o_mark_as_done'));
+ await testUtils.dom.click($record.find('.o_mark_as_done'));
assert.equal(rpcCount, 0, "");
// Click on discard no RPC call
- testUtils.dom.click($record.find('.o_activity_popover_discard'));
+ await testUtils.dom.click($record.find('.o_activity_popover_discard'));
assert.equal(rpcCount, 0, "");
// Click on button and then on done and schedule next
// RPC call
- testUtils.dom.click($record.find('.o_activity_popover_done_next'));
+ await testUtils.dom.click($record.find('.o_activity_popover_done_next'));
assert.equal(rpcCount, 1, "");
kanban.destroy();
});
-QUnit.test('chatter: post, receive and star messages', function (assert) {
- var done = assert.async();
- assert.expect(27);
+QUnit.test('chatter: post, receive and star messages', async function (assert) {
+ assert.expect(26);
this.data.partner.records[0].message_ids = [1];
this.data['mail.message'].records = [{
@@ -763,8 +757,8 @@ QUnit.test('chatter: post, receive and star messages', function (assert) {
res_id: 2,
}];
- var getSuggestionsDef = $.Deferred();
- var form = createView({
+ var getSuggestionsDef = testUtils.makeTestPromise();
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -780,11 +774,11 @@ QUnit.test('chatter: post, receive and star messages', function (assert) {
res_id: 2,
mockRPC: function (route, args) {
if (args.method === 'message_get_suggested_recipients') {
- return $.when({2: []});
+ return Promise.resolve({2: []});
}
if (args.method === 'get_mention_suggestions') {
getSuggestionsDef.resolve();
- return $.when([[{email: "test@odoo.com", id: 1, name: "Test User"}], []]);
+ return Promise.resolve([[{email: "test@odoo.com", id: 1, name: "Test User"}], []]);
}
if (args.method === 'message_post') {
var lastMessageData = _.max(this.data['mail.message'].records, function (messageData) {
@@ -804,7 +798,7 @@ QUnit.test('chatter: post, receive and star messages', function (assert) {
model: 'partner',
res_id: 2,
});
- return $.when(messageID);
+ return Promise.resolve(messageID);
}
if (args.method === 'toggle_message_starred') {
assert.ok(_.contains(args.args[0], 2),
@@ -823,7 +817,7 @@ QUnit.test('chatter: post, receive and star messages', function (assert) {
};
var notification = [[false, 'res.partner'], data];
form.call('bus_service', 'trigger', 'notification', [notification]);
- return $.when();
+ return Promise.resolve();
}
return this._super(route, args);
},
@@ -841,10 +835,10 @@ QUnit.test('chatter: post, receive and star messages', function (assert) {
"the message's author should be correct");
// send a message
- testUtils.dom.click(form.$('.o_chatter_button_new_message'));
+ await testUtils.dom.click(form.$('.o_chatter_button_new_message'));
assert.isVisible($('.oe_chatter .o_thread_composer'), "chatter should be opened");
form.$('.oe_chatter .o_composer_text_field:first()').val("My first message");
- testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
+ await testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
assert.isNotVisible($('.oe_chatter .o_thread_composer'), "chatter should be closed");
assert.containsN(form, '.o_thread_message', 2, "thread should contain two messages");
assert.ok(form.$('.o_thread_message:first().o_mail_discussion').length,
@@ -855,10 +849,10 @@ QUnit.test('chatter: post, receive and star messages', function (assert) {
"the message's author should be correct");
// log a note
- testUtils.dom.click(form.$('.o_chatter_button_log_note'));
+ await testUtils.dom.click(form.$('.o_chatter_button_log_note'));
assert.isVisible($('.oe_chatter .o_thread_composer'), "chatter should be opened");
form.$('.oe_chatter .o_composer_text_field:first()').val("My first note");
- testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
+ await testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
assert.isNotVisible($('.oe_chatter .o_thread_composer'), "chatter should be closed");
assert.containsN(form, '.o_thread_message', 3, "thread should contain three messages");
assert.ok(!form.$('.o_thread_message:first().o_mail_discussion').length,
@@ -871,17 +865,17 @@ QUnit.test('chatter: post, receive and star messages', function (assert) {
// star message 2
assert.ok(form.$('.o_thread_message[data-message-id=2] .o_thread_message_star.fa-star-o').length,
"message 2 should not be starred");
- testUtils.dom.click(form.$('.o_thread_message[data-message-id=2] .o_thread_message_star'));
+ await testUtils.dom.click(form.$('.o_thread_message[data-message-id=2] .o_thread_message_star'));
assert.ok(form.$('.o_thread_message[data-message-id=2] .o_thread_message_star.fa-star').length,
"message 2 should be starred");
// unstar message 2
- testUtils.dom.click(form.$('.o_thread_message[data-message-id=2] .o_thread_message_star'));
+ await testUtils.dom.click(form.$('.o_thread_message[data-message-id=2] .o_thread_message_star'));
assert.ok(form.$('.o_thread_message[data-message-id=2] .o_thread_message_star.fa-star-o').length,
"message 2 should not be starred");
// very basic test of mention
- testUtils.dom.click(form.$('.o_chatter_button_new_message'));
+ await testUtils.dom.click(form.$('.o_chatter_button_new_message'));
var $input = form.$('.oe_chatter .o_composer_text_field:first()');
$input.val('@');
// the cursor position must be set for the mention manager to detect that we are mentionning
@@ -889,30 +883,24 @@ QUnit.test('chatter: post, receive and star messages', function (assert) {
$input[0].selectionEnd = 1;
$input.trigger('keyup');
- assert.strictEqual(getSuggestionsDef.state(), "pending",
- "the mention suggestion RPC should be throttled");
-
- getSuggestionsDef
- .then(concurrency.delay.bind(concurrency, 0))
- .then(function () {
- assert.containsOnce(form, '.o_mention_proposition:visible',
- "there should be one mention suggestion");
- assert.strictEqual(form.$('.o_mention_proposition').data('id'), 1,
- "suggestion's id should be correct");
- assert.strictEqual(form.$('.o_mention_proposition .o_mention_name').text(), 'Test User',
- "suggestion should be displayed correctly");
- assert.strictEqual(form.$('.o_mention_proposition .o_mention_info').text(), '(test@odoo.com)',
- "suggestion should be displayed correctly");
-
- //cleanup
- form.destroy();
- done();
- });
+ await testUtils.nextTick();
+ await getSuggestionsDef;
+ await testUtils.nextTick();
+ assert.containsOnce(form, '.o_mention_proposition:visible',
+ "there should be one mention suggestion");
+ assert.strictEqual(form.$('.o_mention_proposition').data('id'), 1,
+ "suggestion's id should be correct");
+ assert.strictEqual(form.$('.o_mention_proposition .o_mention_name').text(), 'Test User',
+ "suggestion should be displayed correctly");
+ assert.strictEqual(form.$('.o_mention_proposition .o_mention_info').text(), '(test@odoo.com)',
+ "suggestion should be displayed correctly");
+ //cleanup
+ form.destroy();
});
-QUnit.test('chatter: post a message disable the send button', function(assert) {
+QUnit.test('chatter: post a message disable the send button', async function(assert) {
assert.expect(3);
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -929,15 +917,15 @@ QUnit.test('chatter: post a message disable the send button', function(assert) {
session: {},
mockRPC: function (route, args) {
if (args.method === 'message_get_suggested_recipients') {
- return $.when({2: []});
+ return Promise.resolve({2: []});
}
if (args.method === 'message_post') {
assert.ok(form.$('.o_composer_button_send').prop("disabled"),
"Send button should be disabled when a message is being sent");
- return $.when(57923);
+ return Promise.resolve(57923);
}
if (args.method === 'message_format') {
- return $.when([{
+ return Promise.resolve([{
author_id: ["42", "Me"],
model: 'partner',
}]);
@@ -946,20 +934,20 @@ QUnit.test('chatter: post a message disable the send button', function(assert) {
},
});
- testUtils.dom.click(form.$('.o_chatter_button_new_message'));
+ await testUtils.dom.click(form.$('.o_chatter_button_new_message'));
assert.notOk(form.$('.o_composer_button_send').prop('disabled'),
"Send button should be enabled when posting a message");
form.$('.oe_chatter .o_composer_text_field:first()').val("My first message");
- testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
- testUtils.dom.click(form.$('.o_chatter_button_new_message'));
+ await testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
+ await testUtils.dom.click(form.$('.o_chatter_button_new_message'));
assert.notOk(form.$('.o_composer_button_send').prop('disabled'),
"Send button should be enabled when posting another message");
form.destroy();
});
-QUnit.test('chatter: post message failure keep message', function(assert) {
+QUnit.test('chatter: post message failure keep message', async function(assert) {
assert.expect(4);
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -976,26 +964,27 @@ QUnit.test('chatter: post message failure keep message', function(assert) {
session: {},
mockRPC: function (route, args) {
if (args.method === 'message_get_suggested_recipients') {
- return $.when({2: []});
+ return Promise.resolve({2: []});
}
if (args.method === 'message_post') {
assert.ok(form.$('.o_composer_button_send').prop("disabled"),
"Send button should be disabled when a message is being sent");
// simulate failure
- return $.Deferred().reject();
+ return Promise.reject();
+
}
if (args.method === 'message_format') {
- return $.when([]);
+ return Promise.resolve([]);
}
return this._super(route, args);
},
});
- testUtils.dom.click(form.$('.o_chatter_button_new_message'));
+ await testUtils.dom.click(form.$('.o_chatter_button_new_message'));
assert.notOk(form.$('.o_composer_button_send').prop('disabled'),
"Send button should be enabled initially");
- form.$('.oe_chatter .o_composer_text_field:first()').val("My first message");
- testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
+ await testUtils.fields.editInput(form.$('.oe_chatter .o_composer_text_field:first()'), "My first message");
+ await testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
assert.strictEqual(form.$('.o_composer_text_field').val(), "My first message",
"Should keep unsent message in the composer on failure");
assert.notOk(form.$('.o_composer_button_send').prop('disabled'),
@@ -1003,10 +992,10 @@ QUnit.test('chatter: post message failure keep message', function(assert) {
form.destroy();
});
-QUnit.test('chatter: receive notif when document is open', function (assert) {
+QUnit.test('chatter: receive notif when document is open', async function (assert) {
assert.expect(2);
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -1043,14 +1032,14 @@ QUnit.test('chatter: receive notif when document is open', function (assert) {
this.data['mail.message'].records.push(needactionMessageData);
var notification = [[false, 'mail.channel', 1], needactionMessageData];
form.call('bus_service', 'trigger', 'notification', [notification]);
-
+ await testUtils.nextMicrotaskTick();
assert.strictEqual(thread.getUnreadCounter(), 1,
"document thread should now have one unread message");
form.destroy();
});
-QUnit.test('chatter: access document with some notifs', function (assert) {
+QUnit.test('chatter: access document with some notifs', async function (assert) {
assert.expect(3);
// simulate received needaction message on this document thread
@@ -1067,7 +1056,7 @@ QUnit.test('chatter: access document with some notifs', function (assert) {
this.data['mail.message'].records.push(needactionMessageData);
this.data['partner'].records[0].message_ids = [5];
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -1101,10 +1090,10 @@ QUnit.test('chatter: access document with some notifs', function (assert) {
form.destroy();
});
-QUnit.test('chatter: post a message and switch in edit mode', function (assert) {
+QUnit.test('chatter: post a message and switch in edit mode', async function (assert) {
assert.expect(5);
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -1121,7 +1110,7 @@ QUnit.test('chatter: post a message and switch in edit mode', function (assert)
session: {},
mockRPC: function (route, args) {
if (args.method === 'message_get_suggested_recipients') {
- return $.when({2: []});
+ return Promise.resolve({2: []});
}
if (args.method === 'message_post') {
this.data['mail.message'].records.push({
@@ -1136,7 +1125,7 @@ QUnit.test('chatter: post a message and switch in edit mode', function (assert)
model: 'partner',
res_id: 2,
});
- return $.when(42);
+ return Promise.resolve(42);
}
return this._super(route, args);
@@ -1146,15 +1135,15 @@ QUnit.test('chatter: post a message and switch in edit mode', function (assert)
assert.containsNone(form, '.o_thread_message', "thread should not contain messages");
// send a message
- testUtils.dom.click(form.$('.o_chatter_button_new_message'));
+ await testUtils.dom.click(form.$('.o_chatter_button_new_message'));
form.$('.oe_chatter .o_composer_text_field:first()').val("My first message");
- testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
+ await testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
assert.containsOnce(form, '.o_thread_message', "thread should contain a message");
assert.ok(form.$('.o_thread_message:first() .o_thread_message_core').text().indexOf('My first message') >= 0,
"the message's body should be correct");
// switch in edit mode
- testUtils.form.clickEdit(form);
+ await testUtils.form.clickEdit(form);
assert.containsOnce(form, '.o_thread_message', "thread should contain a message");
assert.ok(form.$('.o_thread_message:first() .o_thread_message_core').text().indexOf('My first message') >= 0,
"the message's body should be correct");
@@ -1162,13 +1151,13 @@ QUnit.test('chatter: post a message and switch in edit mode', function (assert)
form.destroy();
});
-QUnit.test('chatter: discard changes on message post with post_refresh "always"', function (assert) {
+QUnit.test('chatter: discard changes on message post with post_refresh "always"', async function (assert) {
// After posting a message that always reloads the record, if the record
// is dirty (= has some unsaved changes), we should warn the user that
// these changes will be lost if he proceeds.
assert.expect(2);
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -1186,7 +1175,7 @@ QUnit.test('chatter: discard changes on message post with post_refresh "always"'
session: {},
mockRPC: function (route, args) {
if (route === "/web/dataset/call_kw/partner/message_get_suggested_recipients") {
- return $.when({2: []});
+ return Promise.resolve({2: []});
}
return this._super(route, args);
},
@@ -1196,12 +1185,12 @@ QUnit.test('chatter: discard changes on message post with post_refresh "always"'
});
// Make record dirty
- testUtils.fields.editInput(form.$('.o_form_sheet input'), 'trululu');
+ await testUtils.fields.editInput(form.$('.o_form_sheet input'), 'trululu');
// Send a message
- testUtils.dom.click(form.$('.o_chatter_button_new_message'));
+ await testUtils.dom.click(form.$('.o_chatter_button_new_message'));
form.$('.oe_chatter .o_composer_text_field:first()').val("My first message");
- testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
+ await testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
var $modal = $('.modal-dialog');
assert.strictEqual($modal.length, 1, "should have a modal opened");
@@ -1212,14 +1201,14 @@ QUnit.test('chatter: discard changes on message post with post_refresh "always"'
form.destroy();
});
-QUnit.test('chatter: discard changes on message post without post_refresh', function (assert) {
+QUnit.test('chatter: discard changes on message post without post_refresh', async function (assert) {
// After posting a message, if the record is dirty and there are no
// post_refresh rule, it will not discard the changes on the record.
assert.expect(2);
var hasDiscardChanges = false; // set if `discard_changes` has been triggered up
var messages = [];
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -1237,13 +1226,13 @@ QUnit.test('chatter: discard changes on message post without post_refresh', func
session: {},
mockRPC: function (route, args) {
if (route === "/web/dataset/call_kw/partner/message_get_suggested_recipients") {
- return $.when({2: []});
+ return Promise.resolve({2: []});
}
if (args.method === 'message_format') {
var requested_msgs = _.filter(messages, function (msg) {
return _.contains(args.args[0], msg.id);
});
- return $.when(requested_msgs);
+ return Promise.resolve(requested_msgs);
}
if (args.method === 'message_post') {
messages.push({
@@ -1258,7 +1247,7 @@ QUnit.test('chatter: discard changes on message post without post_refresh', func
model: 'partner',
res_id: 2,
});
- return $.when(42);
+ return Promise.resolve(42);
}
return this._super(route, args);
},
@@ -1273,12 +1262,12 @@ QUnit.test('chatter: discard changes on message post without post_refresh', func
});
// Make record dirty
- testUtils.fields.editInput(form.$('.o_form_sheet input'), 'trululu');
+ await testUtils.fields.editInput(form.$('.o_form_sheet input'), 'trululu');
// Send a message
- testUtils.dom.click(form.$('.o_chatter_button_new_message'));
+ await testUtils.dom.click(form.$('.o_chatter_button_new_message'));
form.$('.oe_chatter .o_composer_text_field:first()').val("My first message");
- testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
+ await testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
var $modal = $('.modal-dialog');
assert.strictEqual($modal.length, 0, "should have no modal opened");
@@ -1287,18 +1276,17 @@ QUnit.test('chatter: discard changes on message post without post_refresh', func
form.destroy();
});
-QUnit.test('chatter: discard changes on message post with post_refresh "recipients"', function (assert) {
+QUnit.test('chatter: discard changes on message post with post_refresh "recipients"', async function (assert) {
// After posting a message with mentions, the record will be reloaded,
// as the rpc `message_post` may make changes on some fields of the record.
// If the record is dirty (= has some unsaved changes), we should warn the
// user that these changes will be lost if he proceeds.
assert.expect(2);
- var done = assert.async();
- var getSuggestionsDef = $.Deferred();
+ var getSuggestionsDef = testUtils.makeTestPromise();
var messages = [];
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -1316,17 +1304,17 @@ QUnit.test('chatter: discard changes on message post with post_refresh "recipien
session: {},
mockRPC: function (route, args) {
if (route === "/web/dataset/call_kw/partner/message_get_suggested_recipients") {
- return $.when({2: [[42, "Me"]]});
+ return Promise.resolve({2: [[42, "Me"]]});
}
if (args.method === 'get_mention_suggestions') {
getSuggestionsDef.resolve();
- return $.when([[{email: "me@odoo.com", id: 42, name: "Me"}], []]);
+ return Promise.resolve([[{email: "me@odoo.com", id: 42, name: "Me"}], []]);
}
if (args.method === 'message_format') {
var requested_msgs = _.filter(messages, function (msg) {
return _.contains(args.args[0], msg.id);
});
- return $.when(requested_msgs);
+ return Promise.resolve(requested_msgs);
}
if (args.method === 'message_post') {
messages.push({
@@ -1341,7 +1329,7 @@ QUnit.test('chatter: discard changes on message post with post_refresh "recipien
model: 'partner',
res_id: 2,
});
- return $.when(42);
+ return Promise.resolve(42);
}
return this._super(route, args);
},
@@ -1351,13 +1339,13 @@ QUnit.test('chatter: discard changes on message post with post_refresh "recipien
});
// Make record dirty
- testUtils.fields.editInput(form.$('.o_form_sheet input'), 'trululu');
+ await testUtils.fields.editInput(form.$('.o_form_sheet input'), 'trululu');
// create a new message
- testUtils.dom.click(form.$('.o_chatter_button_new_message'));
+ await testUtils.dom.click(form.$('.o_chatter_button_new_message'));
// Add a user as mention
- form.$('.oe_chatter .o_composer_text_field:first()').val("@");
+ await testUtils.fields.editInput(form.$('.oe_chatter .o_composer_text_field:first()'), "@");
var $input = form.$('.oe_chatter .o_composer_text_field:first()');
$input.val('@');
@@ -1365,38 +1353,35 @@ QUnit.test('chatter: discard changes on message post with post_refresh "recipien
$input[0].selectionStart = 1;
$input[0].selectionEnd = 1;
$input.trigger('keyup');
+ await getSuggestionsDef;
+ await testUtils.nextTick();
+ // click on mention
+ $input.trigger($.Event('keyup', {which: $.ui.keyCode.ENTER}));
+ await testUtils.nextTick();
+
+ // untick recipient as follower (prompts a res.partner form otherwise)
+ form.$('input[type="checkbox"]').prop('checked', false);
+ await testUtils.nextTick();
+ // send message
+ await testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
- getSuggestionsDef
- .then(concurrency.delay.bind(concurrency, 0))
- .then(function () {
- // click on mention
- $input.trigger($.Event('keyup', {which: $.ui.keyCode.ENTER}));
-
- // untick recipient as follower (prompts a res.partner form otherwise)
- form.$('input[type="checkbox"]').prop('checked', false);
-
- // send message
- testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
-
- var $modal = $('.modal-dialog');
- assert.strictEqual($modal.length, 1, "should have a modal opened");
- assert.strictEqual($modal.find('.modal-body').text(),
- "The record has been modified, your changes will be discarded. Do you want to proceed?",
- "should warn the user that any unsaved changes will be lost");
+ var $modal = $('.modal-dialog');
+ assert.strictEqual($modal.length, 1, "should have a modal opened");
+ assert.strictEqual($modal.find('.modal-body').text(),
+ "The record has been modified, your changes will be discarded. Do you want to proceed?",
+ "should warn the user that any unsaved changes will be lost");
- form.destroy();
- done();
- });
+ form.destroy();
});
-QUnit.test('chatter: discard changes on opening full-composer', function (assert) {
+QUnit.test('chatter: discard changes on opening full-composer', async function (assert) {
// When we open the full-composer, any following operations by the user
// will reload the record (even closing the full-composer). Therefore,
// we should warn the user when we open the full-composer if the record
// is dirty (= has some unsaved changes).
assert.expect(2);
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -1415,7 +1400,7 @@ QUnit.test('chatter: discard changes on opening full-composer', function (assert
session: {},
mockRPC: function (route, args) {
if (route === "/web/dataset/call_kw/partner/message_get_suggested_recipients") {
- return $.when({2: []});
+ return Promise.resolve({2: []});
}
return this._super(route, args);
},
@@ -1425,11 +1410,11 @@ QUnit.test('chatter: discard changes on opening full-composer', function (assert
});
// Make record dirty
- testUtils.fields.editInput(form.$('.o_form_sheet input'), 'trululu');
+ await testUtils.fields.editInput(form.$('.o_form_sheet input'), 'trululu');
// Open full-composer
- testUtils.dom.click(form.$('.o_chatter_button_new_message'));
- testUtils.dom.click(form.$('.o_composer_button_full_composer'));
+ await testUtils.dom.click(form.$('.o_chatter_button_new_message'));
+ await testUtils.dom.click(form.$('.o_composer_button_full_composer'));
var $modal = $('.modal-dialog');
assert.strictEqual($modal.length, 1, "should have a modal opened");
@@ -1440,7 +1425,7 @@ QUnit.test('chatter: discard changes on opening full-composer', function (assert
form.destroy();
});
-QUnit.test('chatter in x2many form view', function (assert) {
+QUnit.test('chatter in x2many form view', async function (assert) {
// the purpose of this test is to ensure that it doesn't crash when a x2many
// record is opened in form view (thus in a dialog), and when there is a
// chatter in the arch (typically, this may occur when the view used for the
@@ -1453,7 +1438,7 @@ QUnit.test('chatter in x2many form view', function (assert) {
};
this.data.partner.records[0].o2m = [2];
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -1474,7 +1459,7 @@ QUnit.test('chatter in x2many form view', function (assert) {
},
});
- testUtils.dom.click(form.$('.o_data_row:first'));
+ await testUtils.dom.click(form.$('.o_data_row:first'));
assert.strictEqual($('.modal .o_form_view').length, 1,
"should have open a form view in a modal");
@@ -1484,7 +1469,7 @@ QUnit.test('chatter in x2many form view', function (assert) {
form.destroy();
});
-QUnit.test('chatter: Attachment viewer', function (assert) {
+QUnit.test('chatter: Attachment viewer', async function (assert) {
assert.expect(6);
this.data.partner.records[0].message_ids = [1];
this.data['mail.message'].records = [{
@@ -1527,7 +1512,7 @@ QUnit.test('chatter: Attachment viewer', function (assert) {
res_id: 2,
}];
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -1545,7 +1530,7 @@ QUnit.test('chatter: Attachment viewer', function (assert) {
if (_.str.contains(route, '/mail/attachment/preview/') ||
_.str.contains(route, '/web/static/lib/pdfjs/web/viewer.html')){
var canvas = document.createElement('canvas');
- return $.when(canvas.toDataURL());
+ return Promise.resolve(canvas.toDataURL());
}
return this._super.apply(this, arguments);
},
@@ -1555,29 +1540,29 @@ QUnit.test('chatter: Attachment viewer', function (assert) {
assert.hasAttrValue(form.$('.o_thread_message .o_attachment a').first(), 'href', '/web/content/1?download=true',
"image caption should have correct download link");
// click on first image attachement
- testUtils.dom.click(form.$('.o_thread_message .o_attachment .o_image_box .o_image_overlay').first());
+ await testUtils.dom.click(form.$('.o_thread_message .o_attachment .o_image_box .o_image_overlay').first());
assert.strictEqual($('.o_modal_fullscreen img.o_viewer_img[data-src="/web/image/1?unique=1&signature=999&model=ir.attachment"]').length, 1,
"Modal popup should open with first image src");
// click on next button
- testUtils.dom.click($('.modal .arrow.arrow-right.move_next span'));
+ await testUtils.dom.click($('.modal .arrow.arrow-right.move_next span'));
assert.strictEqual($('.o_modal_fullscreen img.o_viewer_img[data-src="/web/image/2?unique=1&signature=999&model=ir.attachment"]').length, 1,
"Modal popup should have now second image src");
assert.strictEqual($('.o_modal_fullscreen .o_viewer_toolbar .o_download_btn').length, 1,
"Modal popup should have download button");
// close attachment popup
- testUtils.dom.click($('.o_modal_fullscreen .o_viewer-header .o_close_btn'));
+ await testUtils.dom.click($('.o_modal_fullscreen .o_viewer-header .o_close_btn'));
// click on pdf attachement
- testUtils.dom.click(form.$('span:contains(Test PDF 1)'));
+ await testUtils.dom.click(form.$('span:contains(Test PDF 1)'));
assert.strictEqual($('.o_modal_fullscreen iframe[data-src*="/web/content/4"]').length, 1,
"Modal popup should open with the pdf preview");
// close attachment popup
- testUtils.dom.click($('.o_modal_fullscreen .o_viewer-header .o_close_btn'));
+ await testUtils.dom.click($('.o_modal_fullscreen .o_viewer-header .o_close_btn'));
form.destroy();
});
-QUnit.test('chatter: keep context when sending a message', function(assert) {
+QUnit.test('chatter: keep context when sending a message', async function(assert) {
assert.expect(1);
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -1596,7 +1581,7 @@ QUnit.test('chatter: keep context when sending a message', function(assert) {
},
mockRPC: function (route, args) {
if (args.method === 'message_get_suggested_recipients') {
- return $.when({2: []});
+ return Promise.resolve({2: []});
}
if (args.method === 'message_post') {
assert.deepEqual(args.kwargs.context, {
@@ -1606,10 +1591,10 @@ QUnit.test('chatter: keep context when sending a message', function(assert) {
mail_post_autofollow: true,
},
"the context is incorrect");
- return $.when(57923);
+ return Promise.resolve(57923);
}
if (args.method === 'message_format') {
- return $.when([{
+ return Promise.resolve([{
author_id: [42, "Me"],
model: 'partner',
}]);
@@ -1618,13 +1603,13 @@ QUnit.test('chatter: keep context when sending a message', function(assert) {
},
});
- testUtils.dom.click(form.$('.o_chatter_button_new_message'));
- testUtils.fields.editInput(form.$('.oe_chatter .o_composer_text_field:first()'), 'Pouet');
- testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
+ await testUtils.dom.click(form.$('.o_chatter_button_new_message'));
+ await testUtils.fields.editInput(form.$('.oe_chatter .o_composer_text_field:first()'), 'Pouet');
+ await testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
form.destroy();
});
-QUnit.test('form activity widget: read RPCs', function (assert) {
+QUnit.test('form activity widget: read RPCs', async function (assert) {
// Records of model 'mail.activity' may be updated in business flows (e.g.
// the date of a 'Meeting' activity is updated when the associated meeting
// is dragged&dropped in the Calendar view). Because of that, the activities
@@ -1645,7 +1630,7 @@ QUnit.test('form activity widget: read RPCs', function (assert) {
}];
var nbReads = 0;
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -1670,15 +1655,15 @@ QUnit.test('form activity widget: read RPCs', function (assert) {
assert.strictEqual(form.$('.o_mail_activity .o_thread_message .o_activity_date').text(),
'Today', "the activity should be today");
- testUtils.form.clickEdit(form);
- testUtils.form.clickSave(form);
+ await testUtils.form.clickEdit(form);
+ await testUtils.form.clickSave(form);
assert.strictEqual(nbReads, 1, "should not have re-read the activities");
// simulate a date change, and a reload of the form view
var tomorrow = moment().add(1, 'day').format("YYYY-MM-DD");
this.data['mail.activity'].records[0].date_deadline = tomorrow;
- form.reload();
+ await form.reload();
assert.strictEqual(nbReads, 2, "should have re-read the activities");
assert.strictEqual(form.$('.o_mail_activity .o_thread_message .o_activity_date').text(),
@@ -1687,10 +1672,10 @@ QUnit.test('form activity widget: read RPCs', function (assert) {
form.destroy();
});
-QUnit.test('form activity widget on a new record', function (assert) {
+QUnit.test('form activity widget on a new record', async function (assert) {
assert.expect(0);
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -1711,7 +1696,7 @@ QUnit.test('form activity widget on a new record', function (assert) {
form.destroy();
});
-QUnit.test('form activity widget with another x2many field in view', function (assert) {
+QUnit.test('form activity widget with another x2many field in view', async function (assert) {
assert.expect(1);
this.data.partner.fields.m2m = {string: "M2M", type: 'many2many', relation: 'partner'};
@@ -1730,7 +1715,7 @@ QUnit.test('form activity widget with another x2many field in view', function (a
activity_type_id: 2,
}];
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -1750,7 +1735,7 @@ QUnit.test('form activity widget with another x2many field in view', function (a
form.destroy();
});
-QUnit.test('form activity widget: schedule next activity', function (assert) {
+QUnit.test('form activity widget: schedule next activity', async function (assert) {
assert.expect(4);
this.data.partner.records[0].activity_ids = [1];
this.data.partner.records[0].activity_state = 'today';
@@ -1765,7 +1750,7 @@ QUnit.test('form activity widget: schedule next activity', function (assert) {
activity_type_id: 2,
}];
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -1785,7 +1770,7 @@ QUnit.test('form activity widget: schedule next activity', function (assert) {
assert.ok(_.isEqual(args.args[0], [1]), "should call 'action_feedback_schedule_next' for id 1");
assert.strictEqual(args.kwargs.feedback, 'everything is ok',
"the feedback should be sent correctly");
- return $.when('test_result');
+ return Promise.resolve('test_result');
}
return this._super.apply(this, arguments);
},
@@ -1797,16 +1782,16 @@ QUnit.test('form activity widget: schedule next activity', function (assert) {
},
});
//Schedule next activity
- testUtils.dom.click(form.$('.o_mail_activity .o_mark_as_done[data-activity-id=1]'));
+ await testUtils.dom.click(form.$('.o_mail_activity .o_mark_as_done[data-activity-id=1]'));
assert.containsOnce(form, '.o_mail_activity_feedback.popover',
"a feedback popover should be visible");
$('.o_mail_activity_feedback.popover textarea').val('everything is ok'); // write a feedback
- testUtils.dom.click(form.$('.o_activity_popover_done_next'));
+ await testUtils.dom.click(form.$('.o_activity_popover_done_next'));
form.destroy();
});
-QUnit.test('form activity widget: edit next activity', function (assert) {
+QUnit.test('form activity widget: edit next activity', async function (assert) {
assert.expect(3);
var self = this;
this.data.partner.records[0].activity_ids = [1];
@@ -1822,7 +1807,7 @@ QUnit.test('form activity widget: edit next activity', function (assert) {
activity_type_id: 2,
}];
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -1866,13 +1851,13 @@ QUnit.test('form activity widget: edit next activity', function (assert) {
});
assert.strictEqual(form.$('.o_mail_activity .o_mail_info strong:eq(1)').text(), " Type 2",
"Initial type should be Type 2");
- testUtils.dom.click(form.$('.o_mail_activity .o_edit_activity[data-activity-id=1]'));
+ await testUtils.dom.click(form.$('.o_mail_activity .o_edit_activity[data-activity-id=1]'));
assert.strictEqual(form.$('.o_mail_activity .o_mail_info strong:eq(1)').text(), " Type 1",
"After edit type should be Type 1");
form.destroy();
});
-QUnit.test('form activity widget: clic mail template', function (assert) {
+QUnit.test('form activity widget: clic mail template', async function (assert) {
assert.expect(4);
this.data.partner.records[0].activity_ids = [1];
this.data.partner.records[0].activity_state = 'today';
@@ -1886,7 +1871,7 @@ QUnit.test('form activity widget: clic mail template', function (assert) {
activity_type_id: 2,
}];
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -1935,16 +1920,16 @@ QUnit.test('form activity widget: clic mail template', function (assert) {
"we should have one activity");
assert.containsOnce(form, '.o_activity_template_preview',
"Activity should contains one mail template");
- testUtils.dom.click(form.$('.o_activity_template_preview[data-template-id=100]'));
+ await testUtils.dom.click(form.$('.o_activity_template_preview[data-template-id=100]'));
assert.containsOnce(form, '.o_mail_activity .o_thread_message',
"activity should still be there");
form.destroy();
});
-QUnit.test('form activity widget: schedule activity does not discard changes', function (assert) {
+QUnit.test('form activity widget: schedule activity does not discard changes', async function (assert) {
assert.expect(1);
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -1976,18 +1961,18 @@ QUnit.test('form activity widget: schedule activity does not discard changes', f
});
// update value of foo field
- testUtils.fields.editInput(form.$('.o_field_widget[name=foo]'), 'new value');
+ await testUtils.fields.editInput(form.$('.o_field_widget[name=foo]'), 'new value');
// schedule an activity (this triggers a do_action)
- testUtils.dom.click(form.$('.o_chatter_button_schedule_activity'));
+ await testUtils.dom.click(form.$('.o_chatter_button_schedule_activity'));
// save the record
- testUtils.form.clickSave(form);
+ await testUtils.form.clickSave(form);
form.destroy();
});
-QUnit.test('form activity widget: mark as done and remove', function (assert) {
+QUnit.test('form activity widget: mark as done and remove', async function (assert) {
assert.expect(15);
var self = this;
@@ -2015,7 +2000,7 @@ QUnit.test('form activity widget: mark as done and remove', function (assert) {
activity_type_id: 1,
}];
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -2072,7 +2057,7 @@ QUnit.test('form activity widget: mark as done and remove', function (assert) {
"there should be two activities");
// remove activity 1
- testUtils.dom.click(form.$('.o_mail_activity .o_unlink_activity[data-activity-id=1]'));
+ await testUtils.dom.click(form.$('.o_mail_activity .o_unlink_activity[data-activity-id=1]'));
assert.containsOnce(form, '.o_mail_activity .o_thread_message',
"there should be one remaining activity");
assert.ok(!form.$('.o_mail_activity .o_unlink_activity[data-activity-id=1]').length,
@@ -2081,11 +2066,11 @@ QUnit.test('form activity widget: mark as done and remove', function (assert) {
// mark activity done
assert.ok(!form.$('.o_mail_thread .o_thread_message').length,
"there should be no chatter message");
- testUtils.dom.click(form.$('.o_mail_activity .o_mark_as_done[data-activity-id=2]'));
+ await testUtils.dom.click(form.$('.o_mail_activity .o_mark_as_done[data-activity-id=2]'));
assert.containsOnce(form, '.o_mail_activity_feedback.popover',
"a feedback popover should be visible");
$('.o_mail_activity_feedback.popover textarea').val('everything is ok'); // write a feedback
- testUtils.dom.click(form.$('.o_activity_popover_done'));
+ await testUtils.dom.click(form.$('.o_activity_popover_done'));
assert.containsNone(form, '.o_mail_activity_feedback.popover')
assert.ok(!form.$('.o_mail_activity .o_thread_message').length,
"there should be no more activity");
@@ -2096,7 +2081,7 @@ QUnit.test('form activity widget: mark as done and remove', function (assert) {
form.destroy();
});
-QUnit.test('followers widget: follow/unfollow, edit subtypes', function (assert) {
+QUnit.test('followers widget: follow/unfollow, edit subtypes', async function (assert) {
assert.expect(24);
var resID = 2;
@@ -2108,7 +2093,7 @@ QUnit.test('followers widget: follow/unfollow, edit subtypes', function (assert)
{id: 2, name: "Second subtype", followed: true},
{id: 3, name: "Third subtype", followed: false},
];
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -2146,10 +2131,10 @@ QUnit.test('followers widget: follow/unfollow, edit subtypes', function (assert)
res_model: 'partner',
});
}
- return $.when(true);
+ return Promise.resolve(true);
}
if (route === '/mail/read_followers') {
- return $.when({
+ return Promise.resolve({
followers: followers,
subtypes: subtypes,
// caution, subtype will only be returned if current user is in args follower list
@@ -2160,7 +2145,7 @@ QUnit.test('followers widget: follow/unfollow, edit subtypes', function (assert)
assert.ok(_.isEqual(args.args[1], [partnerID]), 'should call route for correct partner');
this.data.partner.records[0].message_follower_ids = [];
followers = [];
- return $.when(true);
+ return Promise.resolve(true);
}
if (route === '/web/dataset/call_kw/partner/read') {
nbReads++;
@@ -2182,7 +2167,7 @@ QUnit.test('followers widget: follow/unfollow, edit subtypes', function (assert)
'should display the "Follow" button');
// click to follow the document
- testUtils.dom.click(form.$('.o_followers_follow_button'));
+ await testUtils.dom.click(form.$('.o_followers_follow_button'));
assert.strictEqual(form.$('.o_followers_count').text(), "1", 'should have one follower');
assert.ok(form.$('.o_followers_follow_button.o_followers_following').length,
'should display the "Following/Unfollow" button');
@@ -2194,17 +2179,17 @@ QUnit.test('followers widget: follow/unfollow, edit subtypes', function (assert)
'subtype list should contain 3 subtypes');
assert.containsN(form, '.o_subtypes_list .o_subtype_checkbox:checked', 2,
'two subtypes should be checked by default');
- testUtils.dom.click(form.$('.o_subtypes_list .dropdown-toggle'));
+ await testUtils.dom.click(form.$('.o_subtypes_list .dropdown-toggle'));
assert.ok(form.$('.o_subtypes_list.show').length, 'dropdown should be opened');
- testUtils.dom.click(form.$('.o_subtypes_list .o_subtype input[data-id=2]'));
+ await testUtils.dom.click(form.$('.o_subtypes_list .o_subtype input[data-id=2]'));
assert.ok(form.$('.o_subtypes_list.show').length, 'dropdown should remain opened');
assert.ok(!form.$('.o_subtypes_list .o_subtype_checkbox[data-id=2]:checked').length,
'second subtype should now be unchecked');
// click to unfollow
- testUtils.dom.click(form.$('.o_followers_follow_button'));
+ await testUtils.dom.click(form.$('.o_followers_follow_button'));
assert.ok($('.modal').length, 'a confirm modal should be opened');
- testUtils.dom.click($('.modal .modal-footer .btn-primary'));
+ await testUtils.dom.click($('.modal .modal-footer .btn-primary'));
assert.strictEqual(form.$('.o_followers_count').text(), "0", 'should have no followers');
assert.ok(form.$('.o_followers_follow_button.o_followers_notfollow').length,
'should display the "Follow" button');
@@ -2212,7 +2197,7 @@ QUnit.test('followers widget: follow/unfollow, edit subtypes', function (assert)
form.destroy();
});
-QUnit.test('followers widget: do not display follower duplications', function (assert) {
+QUnit.test('followers widget: do not display follower duplications', async function (assert) {
assert.expect(2);
this.data.partner.records[0].message_follower_ids = [1];
@@ -2225,7 +2210,7 @@ QUnit.test('followers widget: do not display follower duplications', function (a
res_model: 'partner',
}];
var def;
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -2238,7 +2223,7 @@ QUnit.test('followers widget: do not display follower duplications', function (a
'</form>',
mockRPC: function (route, args) {
if (route === '/mail/read_followers') {
- return $.when(def).then(function () {
+ return Promise.resolve(def).then(function () {
return {
followers: _.filter(followers, function (follower) {
return _.contains(args.follower_ids, follower.id);
@@ -2266,11 +2251,11 @@ QUnit.test('followers widget: do not display follower duplications', function (a
// simulate concurrent calls to read_followers and check that those followers
// are not added twice in the dropdown
- def = $.Deferred();
+ def = testUtils.makeTestPromise();
form.reload();
form.reload();
- def.resolve();
-
+ await def.resolve();
+ await testUtils.nextTick();
assert.strictEqual(form.$('.o_followers_count').text(), '2',
"should have 2 followers");
assert.containsN(form, '.o_followers_list .o_partner', 2,
@@ -2279,12 +2264,12 @@ QUnit.test('followers widget: do not display follower duplications', function (a
form.destroy();
});
-QUnit.test('does not render and crash when destroyed before chat system is ready', function (assert) {
+QUnit.test('does not render and crash when destroyed before chat system is ready', async function (assert) {
assert.expect(0);
- var def = $.Deferred();
+ var def = testUtils.makeTestPromise();
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -2302,7 +2287,7 @@ QUnit.test('does not render and crash when destroyed before chat system is ready
res_id: 2,
mockRPC: function (route, args) {
if (args.method === 'message_format') {
- return $.when([{
+ return Promise.resolve([{
attachment_ids: [],
body: "",
date: "2016-12-20 09:35:40",
@@ -2312,7 +2297,7 @@ QUnit.test('does not render and crash when destroyed before chat system is ready
}]);
}
if (route === '/mail/read_followers') {
- return $.when({
+ return Promise.resolve({
followers: [],
subtypes: [],
});
@@ -2332,10 +2317,10 @@ QUnit.test('does not render and crash when destroyed before chat system is ready
// itself. We simply make sure here that no crashes occur (since the form
// view is destroyed, all rpcs will be dropped, and many other mechanisms
// relying on events will not work, such as the chat bus)
- def.resolve();
+ await def.resolve();
});
-QUnit.test('chatter: do not duplicate messages on (un)star message', function (assert) {
+QUnit.test('chatter: do not duplicate messages on (un)star message', async function (assert) {
assert.expect(4);
this.data.partner.records[0].message_ids = [1];
@@ -2352,7 +2337,7 @@ QUnit.test('chatter: do not duplicate messages on (un)star message', function (a
res_id: 2,
}];
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -2382,7 +2367,7 @@ QUnit.test('chatter: do not duplicate messages on (un)star message', function (a
};
var notification = [[false, 'res.partner'], data];
form.call('bus_service', 'trigger', 'notification', [notification]);
- return $.when();
+ return Promise.resolve();
}
return this._super(route, args);
},
@@ -2395,12 +2380,12 @@ QUnit.test('chatter: do not duplicate messages on (un)star message', function (a
"message should not be starred");
// star message
- testUtils.dom.click(form.$('.o_thread_message .o_thread_message_star'));
+ await testUtils.dom.click(form.$('.o_thread_message .o_thread_message_star'));
assert.containsOnce(form, '.o_thread_message',
"there should still be a single message in the chatter after starring the message");
// unstar message
- testUtils.dom.click(form.$('.o_thread_message .o_thread_message_star'));
+ await testUtils.dom.click(form.$('.o_thread_message .o_thread_message_star'));
assert.containsOnce(form, '.o_thread_message',
"there should still be a single message in the chatter after unstarring the message");
@@ -2408,7 +2393,7 @@ QUnit.test('chatter: do not duplicate messages on (un)star message', function (a
form.destroy();
});
-QUnit.test('chatter: new messages on document without any "display_name"', function (assert) {
+QUnit.test('chatter: new messages on document without any "display_name"', async function (assert) {
assert.expect(5);
this.data.partner.records[0].message_ids = [1];
@@ -2426,7 +2411,7 @@ QUnit.test('chatter: new messages on document without any "display_name"', funct
res_id: 2,
}];
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -2463,7 +2448,7 @@ QUnit.test('chatter: new messages on document without any "display_name"', funct
});
this.data.partner.records[0].message_ids.push(2);
- form.reload();
+ await form.reload();
assert.containsN(form, '.o_thread_message', 2,
"should have a two messages in the chatter after reload");
@@ -2476,7 +2461,7 @@ QUnit.test('chatter: new messages on document without any "display_name"', funct
form.destroy();
});
-QUnit.test('chatter: suggested partner auto-follow on message post', function (assert) {
+QUnit.test('chatter: suggested partner auto-follow on message post', async function (assert) {
// need post_refresh 'recipient' to auto-follow suggested recipients
// whose checkbox is checked.
assert.expect(20);
@@ -2507,7 +2492,7 @@ QUnit.test('chatter: suggested partner auto-follow on message post', function (a
res_model: 'partner',
});
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -2524,7 +2509,7 @@ QUnit.test('chatter: suggested partner auto-follow on message post', function (a
res_id: 2,
mockRPC: function (route, args) {
if (args.method === 'message_get_suggested_recipients') {
- return $.when({2: [
+ return Promise.resolve({2: [
[
8,
'DemoUser <demo-user@example.com>',
@@ -2567,10 +2552,10 @@ QUnit.test('chatter: suggested partner auto-follow on message post', function (a
model: 'partner',
res_id: 2,
});
- return $.when(messageID);
+ return Promise.resolve(messageID);
}
if (route === '/mail/read_followers') {
- return $.when({
+ return Promise.resolve({
followers: followers,
});
}
@@ -2596,7 +2581,7 @@ QUnit.test('chatter: suggested partner auto-follow on message post', function (a
"should have 'Admin' as follower");
// open composer
- testUtils.dom.click(form.$('.o_chatter_button_new_message'));
+ await testUtils.dom.click(form.$('.o_chatter_button_new_message'));
assert.isVisible($('.oe_chatter .o_thread_composer'), "chatter should be opened");
assert.strictEqual($('.o_composer_suggested_partners').length, 1,
"should display suggested partners");
@@ -2613,7 +2598,7 @@ QUnit.test('chatter: suggested partner auto-follow on message post', function (a
// send message
form.$('.oe_chatter .o_composer_text_field:first()').val("My first message");
- testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
+ await testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send'));
assert.strictEqual(form.$('.o_followers_count').text(), "2",
"should have a two followers (widget counter)");
@@ -2630,7 +2615,7 @@ QUnit.test('chatter: suggested partner auto-follow on message post', function (a
form.destroy();
});
-QUnit.test('chatter: mention prefetched partners (followers & employees)', function (assert) {
+QUnit.test('chatter: mention prefetched partners (followers & employees)', async function (assert) {
// Note: employees are in prefeteched partner for mentions in chatter when
// the module hr is installed.
assert.expect(10);
@@ -2663,7 +2648,7 @@ QUnit.test('chatter: mention prefetched partners (followers & employees)', funct
mention_partner_suggestions: [followerSuggestions.concat(nonFollowerSuggestions)],
};
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -2680,7 +2665,7 @@ QUnit.test('chatter: mention prefetched partners (followers & employees)', funct
res_id: 2,
mockRPC: function (route, args) {
if (route === '/mail/read_followers') {
- return $.when({
+ return Promise.resolve({
followers: [{
id: 10,
name: 'FollowerUser1',
@@ -2698,7 +2683,7 @@ QUnit.test('chatter: mention prefetched partners (followers & employees)', funct
});
}
if (args.method === 'message_get_suggested_recipients') {
- return $.when({2: []});
+ return Promise.resolve({2: []});
}
if (args.method === 'get_mention_suggestions') {
throw new Error('should not fetch partners for mentions');
@@ -2716,14 +2701,14 @@ QUnit.test('chatter: mention prefetched partners (followers & employees)', funct
assert.strictEqual(form.$('.o_composer_mention_dropdown').length, 0,
"should not show the mention suggestion dropdown");
- form.$('.o_chatter_button_new_message').click();
+ await testUtils.dom.click(form.$('.o_chatter_button_new_message'));
var $input = form.$('.oe_chatter .o_composer_text_field:first()');
$input.val('@');
// the cursor position must be set for the mention manager to detect that we are mentionning
$input[0].selectionStart = 1;
$input[0].selectionEnd = 1;
$input.trigger('keyup');
-
+ await testUtils.nextTick();
assert.strictEqual(form.$('.o_composer_mention_dropdown').length, 1,
"should show the mention suggestion dropdown");
@@ -2783,7 +2768,7 @@ QUnit.test('fieldmany2many tags email', function (assert) {
this.data.partner.records[0].timmy = [12, 14];
// the modals need to be closed before the form view rendering
- createAsyncView({
+ createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -2799,7 +2784,7 @@ QUnit.test('fieldmany2many tags email', function (assert) {
},
mockRPC: function (route, args) {
if (args.method ==='read' && args.model === 'partner_type') {
- assert.step(args.args[0]);
+ assert.step(JSON.stringify(args.args[0]));
assert.deepEqual(args.args[1] , ['display_name', 'email'], "should read the email");
}
return this._super.apply(this, arguments);
@@ -2807,9 +2792,10 @@ QUnit.test('fieldmany2many tags email', function (assert) {
archs: {
'partner_type,false,form': '<form string="Types"><field name="display_name"/><field name="email"/></form>',
},
- }).then(function (form) {
+ }).then(async function (form) {
// should read it 3 times (1 with the form view, one with the form dialog and one after save)
- assert.verifySteps([[12, 14], [14], [14]]);
+ assert.verifySteps(['[12,14]', '[14]', '[14]']);
+ await testUtils.nextTick();
assert.containsN(form, '.o_field_many2manytags[name="timmy"] .badge.o_tag_color_0', 2,
"two tags should be present");
var firstTag = form.$('.o_field_many2manytags[name="timmy"] .badge.o_tag_color_0').first();
@@ -2820,25 +2806,27 @@ QUnit.test('fieldmany2many tags email', function (assert) {
form.destroy();
done();
});
+ testUtils.nextTick().then(function() {
+ assert.strictEqual($('.modal-body.o_act_window').length, 1,
+ "there should be one modal opened to edit the empty email");
+ assert.strictEqual($('.modal-body.o_act_window input[name="display_name"]').val(), "silver",
+ "the opened modal should be a form view dialog with the partner_type 14");
+ assert.strictEqual($('.modal-body.o_act_window input[name="email"]').length, 1,
+ "there should be an email field in the modal");
+
+ // set the email and save the modal (will render the form view)
+ testUtils.fields.editInput($('.modal-body.o_act_window input[name="email"]'), 'coucou@petite.perruche');
+ testUtils.dom.click($('.modal-footer .btn-primary'));
+ });
- assert.strictEqual($('.modal-body.o_act_window').length, 1,
- "there should be one modal opened to edit the empty email");
- assert.strictEqual($('.modal-body.o_act_window input[name="display_name"]').val(), "silver",
- "the opened modal should be a form view dialog with the partner_type 14");
- assert.strictEqual($('.modal-body.o_act_window input[name="email"]').length, 1,
- "there should be an email field in the modal");
-
- // set the email and save the modal (will render the form view)
- testUtils.fields.editInput($('.modal-body.o_act_window input[name="email"]'), 'coucou@petite.perruche');
- testUtils.dom.click($('.modal-footer .btn-primary'));
});
-QUnit.test('fieldmany2many tags email (edition)', function (assert) {
+QUnit.test('fieldmany2many tags email (edition)', async function (assert) {
assert.expect(15);
this.data.partner.records[0].timmy = [12];
- var form = createView({
+ var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -2854,7 +2842,7 @@ QUnit.test('fieldmany2many tags email (edition)', function (assert) {
},
mockRPC: function (route, args) {
if (args.method ==='read' && args.model === 'partner_type') {
- assert.step(args.args[0]);
+ assert.step(JSON.stringify(args.args[0]));
assert.deepEqual(args.args[1] , ['display_name', 'email'], "should read the email");
}
return this._super.apply(this, arguments);
@@ -2864,13 +2852,13 @@ QUnit.test('fieldmany2many tags email (edition)', function (assert) {
},
});
- assert.verifySteps([[12]]);
+ assert.verifySteps(['[12]']);
assert.containsOnce(form, '.o_field_many2manytags[name="timmy"] .badge.o_tag_color_0',
"should contain one tag");
// add an other existing tag
- testUtils.fields.many2one.clickOpenDropdown('timmy');
- testUtils.fields.many2one.clickHighlightedItem('timmy');
+ await testUtils.fields.many2one.clickOpenDropdown('timmy');
+ await testUtils.fields.many2one.clickHighlightedItem('timmy');
assert.strictEqual($('.modal-body.o_act_window').length, 1,
"there should be one modal opened to edit the empty email");
@@ -2880,14 +2868,14 @@ QUnit.test('fieldmany2many tags email (edition)', function (assert) {
"there should be an email field in the modal");
// set the email and save the modal (will rerender the form view)
- testUtils.fields.editInput($('.modal-body.o_act_window input[name="email"]'), 'coucou@petite.perruche');
- testUtils.dom.click($('.modal-footer .btn-primary'));
+ await testUtils.fields.editInput($('.modal-body.o_act_window input[name="email"]'), 'coucou@petite.perruche');
+ await testUtils.dom.click($('.modal-footer .btn-primary'));
assert.containsN(form, '.o_field_many2manytags[name="timmy"] .badge.o_tag_color_0', 2,
"should contain the second tag");
// should have read [14] three times: when opening the dropdown, when opening the modal, and
// after the save
- assert.verifySteps([[12], [14], [14], [14]]);
+ assert.verifySteps(['[14]', '[14]', '[14]']);
form.destroy();
});
diff --git a/addons/mail/static/tests/discuss_mobile_tests.js b/addons/mail/static/tests/discuss_mobile_tests.js
index 19e4c8bdd7f..84fd155522c 100644
--- a/addons/mail/static/tests/discuss_mobile_tests.js
+++ b/addons/mail/static/tests/discuss_mobile_tests.js
@@ -20,68 +20,64 @@ QUnit.module('Discuss in mobile', {
},
});
-QUnit.test('mobile basic rendering', function (assert) {
+QUnit.test('mobile basic rendering', async function (assert) {
// This is a very basic first test for the client action. However, with
// the chat_service, it is hard to override RPCs (for instance, the
// /mail/client_action route is always called when the test suite is
// launched), and we must wait for this RPC to be done before starting to
// test the interface. This should be refactored to facilitate the testing.
assert.expect(16);
- var done = assert.async();
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
data: this.data,
services: this.services,
- debug: true,
- }).then(function (discuss) {
- // test basic rendering in mobile
- assert.containsOnce(discuss, '.o_mail_discuss_content .o_mail_no_content',
- "should display the no content message");
- assert.containsOnce(discuss, '.o_mail_mobile_tabs',
- "should have rendered the tabs");
- assert.hasClass(discuss.$('.o_mail_mobile_tab[data-type=mailbox_inbox]'),'active',
- "should be in inbox tab");
- assert.containsOnce(discuss, '.o_mail_discuss_mobile_mailboxes_buttons:visible',
- "inbox/starred buttons should be visible");
- assert.hasClass(discuss.$('.o_mail_discuss_mobile_mailboxes_buttons .o_mailbox_inbox_item[data-type=mailbox_inbox]'),'btn-primary',
- "should be in inbox");
- assert.hasClass($('.o_mail_discuss_button_dm_chat'),'d-none',
- "should have invisible button 'New Message'");
- assert.hasClass($('.o_mail_discuss_button_multi_user_channel'),'d-none',
- "should have invisible button 'New Channel'");
+ });
+ // test basic rendering in mobile
+ assert.containsOnce(discuss, '.o_mail_discuss_content .o_mail_no_content',
+ "should display the no content message");
+ assert.containsOnce(discuss, '.o_mail_mobile_tabs',
+ "should have rendered the tabs");
+ assert.hasClass(discuss.$('.o_mail_mobile_tab[data-type=mailbox_inbox]'),'active',
+ "should be in inbox tab");
+ assert.containsOnce(discuss, '.o_mail_discuss_mobile_mailboxes_buttons:visible',
+ "inbox/starred buttons should be visible");
+ assert.hasClass(discuss.$('.o_mail_discuss_mobile_mailboxes_buttons .o_mailbox_inbox_item[data-type=mailbox_inbox]'),'btn-primary',
+ "should be in inbox");
+ assert.hasClass($('.o_mail_discuss_button_dm_chat'),'d-none',
+ "should have invisible button 'New Message'");
+ assert.hasClass($('.o_mail_discuss_button_multi_user_channel'),'d-none',
+ "should have invisible button 'New Channel'");
- // move to 'Chat' tab
- testUtils.dom.click(discuss.$('.o_mail_mobile_tab[data-type=dm_chat]'));
- assert.hasClass(discuss.$('.o_mail_mobile_tab[data-type=dm_chat]'),'active',
- "should be in 'Chat' tab");
- assert.containsNone(discuss, '.o_mail_discuss_content .o_mail_no_content',
- "should display the no content message");
- assert.strictEqual($('.o_mail_discuss_button_dm_chat').length, 1,
- "should have a button to open DM chat in 'Chat' tab");
- assert.doesNotHaveClass($('.o_mail_discuss_button_dm_chat'), 'd-none',
- "should be visible in 'Chat' tab");
- assert.hasClass($('.o_mail_discuss_button_multi_user_channel'),'d-none',
- "should have invisible button 'New Channel' in 'Chat' tab");
- testUtils.dom.click($('.o_mail_discuss_button_dm_chat'));
- assert.containsOnce(discuss, '.o_mail_add_thread input:visible',
- "should display the input to add a channel");
+ // move to 'Chat' tab
+ await testUtils.dom.click(discuss.$('.o_mail_mobile_tab[data-type=dm_chat]'));
+ assert.hasClass(discuss.$('.o_mail_mobile_tab[data-type=dm_chat]'),'active',
+ "should be in 'Chat' tab");
+ assert.containsNone(discuss, '.o_mail_discuss_content .o_mail_no_content',
+ "should display the no content message");
+ assert.strictEqual($('.o_mail_discuss_button_dm_chat').length, 1,
+ "should have a button to open DM chat in 'Chat' tab");
+ assert.doesNotHaveClass($('.o_mail_discuss_button_dm_chat'), 'd-none',
+ "should be visible in 'Chat' tab");
+ assert.hasClass($('.o_mail_discuss_button_multi_user_channel'),'d-none',
+ "should have invisible button 'New Channel' in 'Chat' tab");
+ await testUtils.dom.click($('.o_mail_discuss_button_dm_chat'));
+ assert.containsOnce(discuss, '.o_mail_add_thread input:visible',
+ "should display the input to add a channel");
- // move to 'Channels' tab
- testUtils.dom.click(discuss.$('.o_mail_mobile_tab[data-type=multi_user_channel]'));
- assert.hasClass($('.o_mail_discuss_button_dm_chat'),'d-none',
- "should have invisible button 'New Message' in 'Channels' tab");
- assert.doesNotHaveClass($('.o_mail_discuss_button_multi_user_channel'), 'd-none',
- "should have visible button 'New Channel' in 'Channels' tab");
- testUtils.dom.click($('.o_mail_discuss_button_multi_user_channel'));
- assert.containsOnce(discuss, '.o_mail_add_thread input:visible',
- "should display the input to add a channel");
+ // move to 'Channels' tab
+ await testUtils.dom.click(discuss.$('.o_mail_mobile_tab[data-type=multi_user_channel]'));
+ assert.hasClass($('.o_mail_discuss_button_dm_chat'),'d-none',
+ "should have invisible button 'New Message' in 'Channels' tab");
+ assert.doesNotHaveClass($('.o_mail_discuss_button_multi_user_channel'), 'd-none',
+ "should have visible button 'New Channel' in 'Channels' tab");
+ await testUtils.dom.click($('.o_mail_discuss_button_multi_user_channel') );
+ assert.containsOnce(discuss, '.o_mail_add_thread input:visible',
+ "should display the input to add a channel");
- discuss.destroy();
- done();
- });
+ discuss.destroy();
});
QUnit.test('on_{attach/detach}_callback', function (assert) {
diff --git a/addons/mail/static/tests/discuss_moderation_tests.js b/addons/mail/static/tests/discuss_moderation_tests.js
index 9c3807527ce..8b50aae0b53 100644
--- a/addons/mail/static/tests/discuss_moderation_tests.js
+++ b/addons/mail/static/tests/discuss_moderation_tests.js
@@ -145,7 +145,7 @@ QUnit.test('moderator: moderated channel with pending moderation message', funct
data: this.data,
services: this.services,
})
- .then(function (discuss) {
+ .then(async function (discuss) {
var $moderationBox = discuss.$(
'.o_mail_discuss_item' +
'[data-thread-id="mailbox_moderation"]');
@@ -156,7 +156,7 @@ QUnit.test('moderator: moderated channel with pending moderation message', funct
"the mailbox counter of the moderation mailbox should display '1'");
// 1. go to moderation mailbox
- testUtils.dom.click($moderationBox);
+ await testUtils.dom.click($moderationBox);
var $message = discuss.$('.o_thread_message');
// check message
assert.strictEqual($message.length, 1,
@@ -210,7 +210,7 @@ QUnit.test('moderator: moderated channel with pending moderation message', funct
'the moderate button "Discard" should be invisible by default');
// click on message moderation checkbox
- testUtils.dom.click($message.find('.moderation_checkbox'));
+ await testUtils.dom.click($message.find('.moderation_checkbox'));
assert.ok($message.find('.moderation_checkbox').prop('checked'),
"the moderation checkbox should become checked after click");
// check select all (disabled) / unselect all buttons (enabled)
@@ -227,7 +227,7 @@ QUnit.test('moderator: moderated channel with pending moderation message', funct
'the moderate button "Discard" should become visible');
// 2. go to channel 'general'
- testUtils.dom.click(discuss.$('.o_mail_discuss_item[data-thread-id="1"]'));
+ await testUtils.dom.click(discuss.$('.o_mail_discuss_item[data-thread-id="1"]'));
$message = discuss.$('.o_thread_message');
// check correct message
assert.strictEqual($message.length, 1,
@@ -289,12 +289,12 @@ QUnit.test('moderator: accept pending moderation message', function (assert) {
return this._super.apply(this, arguments);
},
})
- .then(function (discuss) {
+ .then(async function (discuss) {
// 1. go to moderation box
var $moderationBox = discuss.$(
'.o_mail_discuss_item' +
'[data-thread-id="mailbox_moderation"]');
- testUtils.dom.click($moderationBox);
+ await testUtils.dom.click($moderationBox);
// check there is a message to moderate
var $message = discuss.$('.o_thread_message');
assert.strictEqual($message.length, 1,
@@ -304,7 +304,7 @@ QUnit.test('moderator: accept pending moderation message', function (assert) {
assert.strictEqual($message.find('.moderation_checkbox').length, 1,
"the message should have a moderation checkbox");
// accept the message pending moderation
- testUtils.dom.click(discuss.$('.o_thread_message_moderation[data-decision="accept"]'));
+ await testUtils.dom.click(discuss.$('.o_thread_message_moderation[data-decision="accept"]'));
assert.verifySteps(['moderate']);
// stop the fadeout animation and immediately remove the element
@@ -313,7 +313,7 @@ QUnit.test('moderator: accept pending moderation message', function (assert) {
"should now have no message displayed in moderation box");
// 2. go to channel 'general'
- testUtils.dom.click(discuss.$('.o_mail_discuss_item[data-thread-id="1"]'));
+ await testUtils.dom.click(discuss.$('.o_mail_discuss_item[data-thread-id="1"]'));
$message = discuss.$('.o_thread_message');
// check message is there and has no moderate checkbox
assert.strictEqual($message.length, 1,
@@ -379,12 +379,12 @@ QUnit.test('moderator: reject pending moderation message (reject with explanatio
return this._super.apply(this, arguments);
},
})
- .then(function (discuss) {
+ .then(async function (discuss) {
// 1. go to moderation box
var $moderationBox = discuss.$(
'.o_mail_discuss_item' +
'[data-thread-id="mailbox_moderation"]');
- testUtils.dom.click($moderationBox);
+ await testUtils.dom.click($moderationBox);
// check there is a message to moderate
var $message = discuss.$('.o_thread_message');
assert.strictEqual($message.length, 1,
@@ -394,7 +394,7 @@ QUnit.test('moderator: reject pending moderation message (reject with explanatio
assert.strictEqual($message.find('.moderation_checkbox').length, 1,
"the message should have a moderation checkbox");
// reject the message pending moderation
- testUtils.dom.click(discuss.$('.o_thread_message_moderation[data-decision="reject"]'));
+ await testUtils.dom.click(discuss.$('.o_thread_message_moderation[data-decision="reject"]'));
// check reject dialog prompt
assert.strictEqual($('.modal-dialog').length, 1,
@@ -419,7 +419,7 @@ QUnit.test('moderator: reject pending moderation message (reject with explanatio
"should have a send button on the reject dialog");
// send mesage
- testUtils.dom.click($('.modal-footer button'));
+ await testUtils.dom.click($('.modal-footer button'));
assert.verifySteps(['moderate']);
// // stop the fadeout animation and immediately remove the element
@@ -428,7 +428,7 @@ QUnit.test('moderator: reject pending moderation message (reject with explanatio
"should now have no message displayed in moderation box");
// 2. go to channel 'general'
- testUtils.dom.click(discuss.$('.o_mail_discuss_item[data-thread-id="1"]'));
+ await testUtils.dom.click(discuss.$('.o_mail_discuss_item[data-thread-id="1"]'));
assert.containsNone(discuss, '.o_thread_message')
discuss.destroy();
@@ -482,12 +482,12 @@ QUnit.test('moderator: discard pending moderation message (reject without explan
return this._super.apply(this, arguments);
},
})
- .then(function (discuss) {
+ .then(async function (discuss) {
// 1. go to moderation box
var $moderationBox = discuss.$(
'.o_mail_discuss_item' +
'[data-thread-id="mailbox_moderation"]');
- testUtils.dom.click($moderationBox);
+ await testUtils.dom.click($moderationBox);
// check there is a message to moderate
var $message = discuss.$('.o_thread_message');
assert.strictEqual($message.length, 1,
@@ -497,7 +497,7 @@ QUnit.test('moderator: discard pending moderation message (reject without explan
assert.strictEqual($message.find('.moderation_checkbox').length, 1,
"the message should have a moderation checkbox");
// discard the message pending moderation
- testUtils.dom.click(discuss.$('.o_thread_message_moderation[data-decision="discard"]'));
+ await testUtils.dom.click(discuss.$('.o_thread_message_moderation[data-decision="discard"]'));
// check discard dialog prompt
assert.strictEqual($('.modal-dialog').length, 1,
@@ -513,7 +513,7 @@ QUnit.test('moderator: discard pending moderation message (reject without explan
"should have a cancel button in the dialog for discard");
// discard mesage
- testUtils.dom.click($('.modal-footer button.btn-primary'));
+ await testUtils.dom.click($('.modal-footer button.btn-primary'));
assert.verifySteps(['moderate']);
// stop the fadeout animation and immediately remove the element
@@ -522,7 +522,7 @@ QUnit.test('moderator: discard pending moderation message (reject without explan
"should now have no message displayed in moderation box");
// 2. go to channel 'general'
- testUtils.dom.click(discuss.$('.o_mail_discuss_item[data-thread-id="1"]'));
+ await testUtils.dom.click(discuss.$('.o_mail_discuss_item[data-thread-id="1"]'));
assert.containsNone(discuss, '.o_thread_message')
discuss.destroy();
@@ -534,7 +534,7 @@ QUnit.test('author: send message in moderated channel', function (assert) {
assert.expect(4);
var done = assert.async();
- var messagePostDef = $.Deferred();
+ var messagePostDef = testUtils.makeTestPromise();
this.data.initMessaging = {
channel_slots: {
@@ -554,7 +554,7 @@ QUnit.test('author: send message in moderated channel', function (assert) {
params: {},
data: this.data,
services: this.services,
- mockRPC: function (route, args) {
+ mockRPC: async function (route, args) {
if (args.method === 'message_post') {
var message = {
id: 100,
@@ -572,9 +572,10 @@ QUnit.test('author: send message in moderated channel', function (assert) {
};
var notification = [metaData, notifData];
objectDiscuss.call('bus_service', 'trigger', 'notification', [notification]);
+ await testUtils.nextTick();
messagePostDef.resolve();
- return $.when(message.id);
+ return Promise.resolve(message.id);
}
return this._super.apply(this, arguments);
},
@@ -582,14 +583,14 @@ QUnit.test('author: send message in moderated channel', function (assert) {
partner_id: 2,
},
})
- .then(function (discuss) {
+ .then(async function (discuss) {
objectDiscuss = discuss;
// go to channel 'general'
- testUtils.dom.click(discuss.$('.o_mail_discuss_item[data-thread-id="1"]'));
+ await testUtils.dom.click(discuss.$('.o_mail_discuss_item[data-thread-id="1"]'));
// post a message
discuss.$('.o_composer_input textarea').first().val("some text");
- testUtils.dom.click(discuss.$('.o_composer_send button'));
+ await testUtils.dom.click(discuss.$('.o_composer_send button'));
messagePostDef
.then(function () {
@@ -646,10 +647,10 @@ QUnit.test('author: sent message accepted in moderated channel', function (asser
partner_id: 2,
},
})
- .then(function (discuss) {
+ .then(async function (discuss) {
// go to channel 'general'
- testUtils.dom.click(discuss.$('.o_mail_discuss_item[data-thread-id="1"]'));
+ await testUtils.dom.click(discuss.$('.o_mail_discuss_item[data-thread-id="1"]'));
// check message is pending
var $message = discuss.$('.o_thread_message');
assert.strictEqual($message.length, 1,
@@ -674,7 +675,7 @@ QUnit.test('author: sent message accepted in moderated channel', function (asser
var metaData = [dbName, 'mail.channel'];
var notification = [metaData, messageData];
discuss.call('bus_service', 'trigger', 'notification', [notification]);
-
+ await testUtils.nextTick();
// check message is accepted
$message = discuss.$('.o_thread_message');
assert.strictEqual($message.length, 1,
@@ -727,10 +728,10 @@ QUnit.test('author: sent message rejected in moderated channel', function (asser
partner_id: 2,
},
})
- .then(function (discuss) {
+ .then(async function (discuss) {
// go to channel 'general'
- testUtils.dom.click(discuss.$('.o_mail_discuss_item[data-thread-id="1"]'));
+ await testUtils.dom.click(discuss.$('.o_mail_discuss_item[data-thread-id="1"]'));
// check message is pending
var $message = discuss.$('.o_thread_message');
assert.strictEqual($message.length, 1,
@@ -751,7 +752,7 @@ QUnit.test('author: sent message rejected in moderated channel', function (asser
var metaData = [dbName, 'res.partner'];
var notification = [metaData, notifData];
discuss.call('bus_service', 'trigger', 'notification', [notification]);
-
+ await testUtils.nextTick();
// // check no message
assert.containsNone(discuss, '.o_thread_message',
"message should be removed from channel after reject");
@@ -761,12 +762,11 @@ QUnit.test('author: sent message rejected in moderated channel', function (asser
});
});
-QUnit.test('no crash when load-more fetching "accepted" message twice', function (assert) {
+QUnit.test('no crash when load-more fetching "accepted" message twice', async function (assert) {
// This tests requires discuss not loading more messages due to having less
// messages to fetch than available height. This justifies we simply do not
// patch FETCH_LIMIT to 1, as it would detect that more messages could fit
// the empty space (it behaviour is linked to "auto load more").
- var done = assert.async();
assert.expect(2);
var FETCH_LIMIT = Thread.prototype._FETCH_LIMIT;
@@ -799,7 +799,7 @@ QUnit.test('no crash when load-more fetching "accepted" message twice', function
};
var count = 0;
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -811,33 +811,32 @@ QUnit.test('no crash when load-more fetching "accepted" message twice', function
count++;
if (count === 1) {
// inbox message_fetch
- return $.when([]);
+ return Promise.resolve([]);
}
// general message_fetch
- return $.when(messageData);
+ return Promise.resolve(messageData);
}
return this._super.apply(this, arguments);
},
- })
- .then(function (discuss) {
- var $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- assert.strictEqual($general.length, 1,
- "should have the channel item with id 1");
- assert.strictEqual($general.attr('title'), 'general',
- "should have the title 'general'");
+ });
- // click on general
- $general.click();
+ var $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ assert.strictEqual($general.length, 1,
+ "should have the channel item with id 1");
+ assert.strictEqual($general.attr('title'), 'general',
+ "should have the title 'general'");
- // simulate search
- discuss.trigger_up('search', {
- domains: [['author_id', '=', 100]],
- });
+ // click on general
+ await testUtils.dom.click($general);
- discuss.destroy();
- done();
+ // simulate search
+ discuss.trigger_up('search', {
+ domains: [['author_id', '=', 100]],
});
+ await testUtils.nextTick();
+
+ discuss.destroy();
});
});
diff --git a/addons/mail/static/tests/discuss_seen_indicator_tests.js b/addons/mail/static/tests/discuss_seen_indicator_tests.js
index 4db61a56ed1..46f5e0b5723 100644
--- a/addons/mail/static/tests/discuss_seen_indicator_tests.js
+++ b/addons/mail/static/tests/discuss_seen_indicator_tests.js
@@ -72,13 +72,13 @@ QUnit.module('Discuss (Seen Indicator)', {
};
var notification = [[false, 'mail.channel', params.channelID], data];
params.widget.call('bus_service', 'trigger', 'notification', [notification]);
+ return testUtils.nextTick();
};
},
});
-QUnit.test('2 members: 1 myself message not received initially', function (assert) {
+QUnit.test('2 members: 1 myself message not received initially', async function (assert) {
assert.expect(2);
- var done = assert.async();
var dmChat = {
id: 1,
@@ -123,30 +123,27 @@ QUnit.test('2 members: 1 myself message not received initially', function (asser
res_id: 1,
}];
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
data: this.data,
services: this.services,
session: { partner_id: 3 },
- }).then(function (discuss) {
- // click on DM chat
- var $dmChat = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- testUtils.dom.click($dmChat);
+ });
+ // click on general
+ var $dmChat = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ await testUtils.dom.click($dmChat);
- assert.isVisible(discuss.$('.o_thread_message[data-message-id=100]'));
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
+ assert.isVisible(discuss.$('.o_thread_message[data-message-id=100]'));
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
- discuss.destroy();
- done();
- });
+ discuss.destroy();
});
-QUnit.test('2 members: 1 myself message received by everyone initially', function (assert) {
+QUnit.test('2 members: 1 myself message received by everyone initially', async function (assert) {
assert.expect(4);
- var done = assert.async();
var dmChat = {
id: 1,
@@ -191,35 +188,32 @@ QUnit.test('2 members: 1 myself message received by everyone initially', functio
res_id: 1,
}];
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
data: this.data,
services: this.services,
session: { partner_id: 3 },
- }).then(function (discuss) {
- // click on DM chat
- var $dmChat = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- testUtils.dom.click($dmChat);
- var $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
- assert.isVisible($seenIcon, "should display seen icon on message");
- assert.containsOnce($seenIcon, '.fa-check', "should display a single check");
-
- testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
- var $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
- assert.isVisible($seenIconContent, "should display content on seen icon mouseover");
- assert.strictEqual($seenIconContent.text().trim(), "Received by Everyone");
-
- discuss.destroy();
- done();
});
+ // click on DM chat
+ var $dmChat = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ await testUtils.dom.click($dmChat);
+ var $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
+ assert.isVisible($seenIcon, "should display seen icon on message");
+ assert.containsOnce($seenIcon, '.fa-check', "should display a single check");
+
+ await testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
+ var $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
+ assert.isVisible($seenIconContent, "should display content on seen icon mouseover");
+ assert.strictEqual($seenIconContent.text().trim(), "Received by Everyone");
+
+ discuss.destroy();
});
-QUnit.test('2 members: 1 myself message seen by everyone initially', function (assert) {
+QUnit.test('2 members: 1 myself message seen by everyone initially', async function (assert) {
assert.expect(4);
- var done = assert.async();
var dmChat = {
id: 1,
@@ -264,37 +258,33 @@ QUnit.test('2 members: 1 myself message seen by everyone initially', function (a
res_id: 1,
}];
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
data: this.data,
services: this.services,
session: { partner_id: 3 },
- }).then(function (discuss) {
- // click on DM chat
- var $dmChat = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- testUtils.dom.click($dmChat);
- var $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
- assert.isVisible($seenIcon, "should display seen icon on message");
- assert.containsN($seenIcon, '.fa-check', 2, "should display 2 checks");
-
- testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
- var $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
- assert.isVisible($seenIconContent, "should display content on seen icon mouseover");
- assert.strictEqual($seenIconContent.text().trim(), "Seen by Everyone");
-
- discuss.destroy();
- done();
});
+ // click on DM chat
+ var $dmChat = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ await testUtils.dom.click($dmChat);
+ var $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
+ assert.isVisible($seenIcon, "should display seen icon on message");
+ assert.containsN($seenIcon, '.fa-check', 2, "should display 2 checks");
+
+ await testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
+ var $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
+ assert.isVisible($seenIconContent, "should display content on seen icon mouseover");
+ assert.strictEqual($seenIconContent.text().trim(), "Seen by Everyone");
+
+ discuss.destroy();
});
-QUnit.test('2 members: 1 myself message received by everyone (initially not received)', function (assert) {
+QUnit.test('2 members: 1 myself message received by everyone (initially not received)', async function (assert) {
assert.expect(6);
- var done = assert.async();
- var self = this;
var dmChat = {
id: 1,
channel_type: "chat",
@@ -338,49 +328,45 @@ QUnit.test('2 members: 1 myself message received by everyone (initially not rece
res_id: 1,
}];
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
data: this.data,
services: this.services,
session: { partner_id: 3 },
- }).then(function (discuss) {
- // click on DM chat
- var $dmChat = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- testUtils.dom.click($dmChat);
-
- assert.isVisible(discuss.$('.o_thread_message[data-message-id=100]'));
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
-
- self.simulate({
- action: 'received',
- channelID: 1,
- partnerID: 2,
- lastMessageID: 100,
- widget: discuss,
- });
-
- var $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
- assert.isVisible($seenIcon, "should display seen icon on message");
- assert.containsOnce($seenIcon, '.fa-check', "should display a single check");
-
- testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
- var $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
- assert.isVisible($seenIconContent, "should display content on seen icon mouseover");
- assert.strictEqual($seenIconContent.text().trim(), "Received by Everyone");
-
- discuss.destroy();
- done();
});
+ // click on DM chat
+ var $dmChat = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ await testUtils.dom.click($dmChat);
+
+ assert.isVisible(discuss.$('.o_thread_message[data-message-id=100]'));
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
+
+ await this.simulate({
+ action: 'received',
+ channelID: 1,
+ partnerID: 2,
+ lastMessageID: 100,
+ widget: discuss,
+ });
+
+ var $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
+ assert.isVisible($seenIcon, "should display seen icon on message");
+ assert.containsOnce($seenIcon, '.fa-check', "should display a single check");
+
+ await testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
+ var $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
+ assert.isVisible($seenIconContent, "should display content on seen icon mouseover");
+ assert.strictEqual($seenIconContent.text().trim(), "Received by Everyone");
+
+ discuss.destroy();
});
-QUnit.test('2 members: 1 myself message seen by everyone (initially not received)', function (assert) {
+QUnit.test('2 members: 1 myself message seen by everyone (initially not received)', async function (assert) {
assert.expect(6);
- var done = assert.async();
- var self = this;
var dmChat = {
id: 1,
channel_type: "chat",
@@ -424,49 +410,45 @@ QUnit.test('2 members: 1 myself message seen by everyone (initially not received
res_id: 1,
}];
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
data: this.data,
services: this.services,
session: { partner_id: 3 },
- }).then(function (discuss) {
- // click on DM chat
- var $dmChat = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- testUtils.dom.click($dmChat);
-
- assert.isVisible(discuss.$('.o_thread_message[data-message-id=100]'));
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
-
- self.simulate({
- action: 'seen',
- channelID: 1,
- partnerID: 2,
- lastMessageID: 100,
- widget: discuss,
- });
-
- var $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
- assert.isVisible($seenIcon, "should display seen icon on message");
- assert.containsN($seenIcon, '.fa-check', 2, "should display 2 checks");
-
- testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
- var $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
- assert.isVisible($seenIconContent, "should display content on seen icon mouseover");
- assert.strictEqual($seenIconContent.text().trim(), "Seen by Everyone");
-
- discuss.destroy();
- done();
});
+ // click on DM chat
+ var $dmChat = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ await testUtils.dom.click($dmChat);
+
+ assert.isVisible(discuss.$('.o_thread_message[data-message-id=100]'));
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
+
+ await this.simulate({
+ action: 'seen',
+ channelID: 1,
+ partnerID: 2,
+ lastMessageID: 100,
+ widget: discuss,
+ });
+
+ var $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
+ assert.isVisible($seenIcon, "should display seen icon on message");
+ assert.containsN($seenIcon, '.fa-check', 2, "should display 2 checks");
+
+ await testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
+ var $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
+ assert.isVisible($seenIconContent, "should display content on seen icon mouseover");
+ assert.strictEqual($seenIconContent.text().trim(), "Seen by Everyone");
+
+ discuss.destroy();
});
-QUnit.test('2 members: 1 other message seen by me (initially not received)', function (assert) {
+QUnit.test('2 members: 1 other message seen by me (initially not received)', async function (assert) {
assert.expect(3);
- var done = assert.async();
- var self = this;
var dmChat = {
id: 1,
channel_type: "chat",
@@ -510,44 +492,41 @@ QUnit.test('2 members: 1 other message seen by me (initially not received)', fun
res_id: 1,
}];
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
data: this.data,
services: this.services,
session: { partner_id: 3 },
- }).then(function (discuss) {
- // click on DM chat
- var $dmChat = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- testUtils.dom.click($dmChat);
-
- assert.isVisible(discuss.$('.o_thread_message[data-message-id=100]'));
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
-
- self.simulate({
- action: 'seen',
- channelID: 1,
- partnerID: 3,
- lastMessageID: 100,
- widget: discuss,
- });
-
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
-
- discuss.destroy();
- done();
});
+ // click on DM chat
+ var $dmChat = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ await testUtils.dom.click($dmChat);
+
+ assert.isVisible(discuss.$('.o_thread_message[data-message-id=100]'));
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
+
+ await this.simulate({
+ action: 'seen',
+ channelID: 1,
+ partnerID: 3,
+ lastMessageID: 100,
+ widget: discuss,
+ });
+
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
+
+ discuss.destroy();
});
-QUnit.skip('3 members: 1 myself message received by some initially', function (assert) {
+QUnit.skip('3 members: 1 myself message received by some initially', async function (assert) {
// IMPORTANT: This test make sense if this feature is on multi user channels,
// which was the case in case at some point. It has been disabled for
// performance reasons. We are unsure if this will come back in the future,
// so we keep to tests in 'skip' mode in the mean time.
assert.expect(4);
- var done = assert.async();
var members = [{
id: 2,
@@ -601,7 +580,7 @@ QUnit.skip('3 members: 1 myself message received by some initially', function (a
res_id: 1,
}];
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -610,31 +589,29 @@ QUnit.skip('3 members: 1 myself message received by some initially', function (a
session: { partner_id: 3 },
mockRPC: function (route, args) {
if (args.method === 'channel_fetch_listeners') {
- return $.when(members);
+ return Promise.resolve(members);
}
return this._super.apply(this, arguments);
},
- }).then(function (discuss) {
- // click on general
- var $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- testUtils.dom.click($general);
- var $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
- assert.isVisible($seenIcon, "should display seen icon on message");
- assert.containsOnce($seenIcon, '.fa-check', "should display a single check");
-
- testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
- var $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
- assert.isVisible($seenIconContent, "should display content on seen icon mouseover");
- assert.strictEqual($seenIconContent.text().replace(/\s/g, ""),
- "Receivedby:Someone(someone@example.com)");
-
- discuss.destroy();
- done();
});
+ // click on general
+ var $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ await testUtils.dom.click($general);
+ var $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
+ assert.isVisible($seenIcon, "should display seen icon on message");
+ assert.containsOnce($seenIcon, '.fa-check', "should display a single check");
+
+ await testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
+ var $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
+ assert.isVisible($seenIconContent, "should display content on seen icon mouseover");
+ assert.strictEqual($seenIconContent.text().replace(/\s/g, ""),
+ "Receivedby:Someone(someone@example.com)");
+
+ discuss.destroy();
});
-QUnit.skip('several members: 1 myself message seen by everyone (initially not received)', function (assert) {
+QUnit.skip('several members: 1 myself message seen by everyone (initially not received)', async function (assert) {
// IMPORTANT: This test make sense if this feature is on multi user channels,
// which was the case in case at some point. It has been disabled for
// performance reasons. We are unsure if this will come back in the future,
@@ -643,9 +620,7 @@ QUnit.skip('several members: 1 myself message seen by everyone (initially not re
// seen icon and content should change for my messages based on other users
// actions (received and/or seen the message)
assert.expect(26);
- var done = assert.async();
- var self = this;
var members = [{
id: 2,
name: "Someone",
@@ -706,7 +681,7 @@ QUnit.skip('several members: 1 myself message seen by everyone (initially not re
res_id: 1,
}];
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -715,133 +690,131 @@ QUnit.skip('several members: 1 myself message seen by everyone (initially not re
session: { partner_id: 3 },
mockRPC: function (route, args) {
if (args.method === 'channel_fetch_listeners') {
- return $.when(members);
+ return Promise.resolve(members);
}
return this._super.apply(this, arguments);
},
- }).then(function (discuss) {
- // click on general
- var $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- testUtils.dom.click($general);
-
- assert.isVisible(discuss.$('.o_thread_message[data-message-id=100]'));
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
-
- self.simulate({
- action: 'received',
- channelID: 1,
- partnerID: 2,
- lastMessageID: 100,
- widget: discuss,
- });
-
- var $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
- assert.isVisible($seenIcon, "should display seen icon on message");
- assert.containsOnce($seenIcon, '.fa-check', "should display a single check");
-
- testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
- var $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
- assert.isVisible($seenIconContent, "should display content on seen icon mouseover");
- assert.strictEqual($seenIconContent.text().replace(/\s/g, ""),
- "Receivedby:Someone(someone@example.com)");
-
- self.simulate({
- action: 'received',
- channelID: 1,
- partnerID: 4,
- lastMessageID: 100,
- widget: discuss,
- });
-
- $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
- assert.isVisible($seenIcon, "should still display seen icon on message");
- assert.containsOnce($seenIcon, '.fa-check', "should still display a single check");
-
- testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
- $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
- assert.isVisible($seenIconContent, "should still display content on seen icon mouseover");
- assert.strictEqual($seenIconContent.text().replace(/\s/g, ""),
- "Receivedby:Someone(someone@example.com)Other(other@example.com)");
-
- self.simulate({
- action: 'seen',
- channelID: 1,
- partnerID: 2,
- lastMessageID: 100,
- widget: discuss,
- });
-
- $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
- assert.isVisible($seenIcon, "should still display seen icon on message");
- assert.containsN($seenIcon, '.fa-check', 2, "should now display 2 checks");
-
- testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
- $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
- assert.isVisible($seenIconContent, "should still display content on seen icon mouseover");
- assert.strictEqual($seenIconContent.text().replace(/\s/g, ""),
- "Seenby:Someone(someone@example.com)Receivedby:Other(other@example.com)");
-
- self.simulate({
- action: 'seen',
- channelID: 1,
- partnerID: 4,
- lastMessageID: 100,
- widget: discuss,
- });
-
- $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
- assert.isVisible($seenIcon, "should still display seen icon on message");
- assert.containsN($seenIcon, '.fa-check', 2, "should still display 2 checks");
-
- testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
- $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
- assert.isVisible($seenIconContent, "should still display content on seen icon mouseover");
- assert.strictEqual($seenIconContent.text().replace(/\s/g, ""),
- "Seenby:Someone(someone@example.com)Other(other@example.com)");
-
- self.simulate({
- action: 'received',
- channelID: 1,
- partnerID: 5,
- lastMessageID: 100,
- widget: discuss,
- });
-
- $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
- assert.isVisible($seenIcon, "should still display seen icon on message");
- assert.containsN($seenIcon, '.fa-check', 2, "should still display 2 checks");
-
- testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
- $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
- assert.isVisible($seenIconContent, "should still display content on seen icon mouseover");
- assert.strictEqual($seenIconContent.text().replace(/\s/g, ""),
- "Seenby:Someone(someone@example.com)Other(other@example.com)ReceivedbyEveryone");
-
- self.simulate({
- action: 'seen',
- channelID: 1,
- partnerID: 5,
- lastMessageID: 100,
- widget: discuss,
- });
-
- $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
- assert.isVisible($seenIcon, "should still display seen icon on message");
- assert.containsN($seenIcon, '.fa-check', 2, "should still display 2 checks");
-
- testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
- $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
- assert.isVisible($seenIconContent, "should still display content on seen icon mouseover");
- assert.strictEqual($seenIconContent.text().trim(),
- "Seen by Everyone");
-
- discuss.destroy();
- done();
});
+ // click on general
+ var $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ await testUtils.dom.click($general);
+
+ assert.isVisible(discuss.$('.o_thread_message[data-message-id=100]'));
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
+
+ await this.simulate({
+ action: 'received',
+ channelID: 1,
+ partnerID: 2,
+ lastMessageID: 100,
+ widget: discuss,
+ });
+
+ var $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
+ assert.isVisible($seenIcon, "should display seen icon on message");
+ assert.containsOnce($seenIcon, '.fa-check', "should display a single check");
+
+ await testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
+ var $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
+ assert.isVisible($seenIconContent, "should display content on seen icon mouseover");
+ assert.strictEqual($seenIconContent.text().replace(/\s/g, ""),
+ "Receivedby:Someone(someone@example.com)");
+
+ await this.simulate({
+ action: 'received',
+ channelID: 1,
+ partnerID: 4,
+ lastMessageID: 100,
+ widget: discuss,
+ });
+
+ $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
+ assert.isVisible($seenIcon, "should still display seen icon on message");
+ assert.containsOnce($seenIcon, '.fa-check', "should still display a single check");
+
+ await testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
+ $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
+ assert.isVisible($seenIconContent, "should still display content on seen icon mouseover");
+ assert.strictEqual($seenIconContent.text().replace(/\s/g, ""),
+ "Receivedby:Someone(someone@example.com)Other(other@example.com)");
+
+ await this.simulate({
+ action: 'seen',
+ channelID: 1,
+ partnerID: 2,
+ lastMessageID: 100,
+ widget: discuss,
+ });
+
+ $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
+ assert.isVisible($seenIcon, "should still display seen icon on message");
+ assert.containsN($seenIcon, '.fa-check', 2, "should now display 2 checks");
+
+ await testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
+ $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
+ assert.isVisible($seenIconContent, "should still display content on seen icon mouseover");
+ assert.strictEqual($seenIconContent.text().replace(/\s/g, ""),
+ "Seenby:Someone(someone@example.com)Receivedby:Other(other@example.com)");
+
+ await this.simulate({
+ action: 'seen',
+ channelID: 1,
+ partnerID: 4,
+ lastMessageID: 100,
+ widget: discuss,
+ });
+
+ $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
+ assert.isVisible($seenIcon, "should still display seen icon on message");
+ assert.containsN($seenIcon, '.fa-check', 2, "should still display 2 checks");
+
+ await testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
+ $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
+ assert.isVisible($seenIconContent, "should still display content on seen icon mouseover");
+ assert.strictEqual($seenIconContent.text().replace(/\s/g, ""),
+ "Seenby:Someone(someone@example.com)Other(other@example.com)");
+
+ await this.simulate({
+ action: 'received',
+ channelID: 1,
+ partnerID: 5,
+ lastMessageID: 100,
+ widget: discuss,
+ });
+
+ $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
+ assert.isVisible($seenIcon, "should still display seen icon on message");
+ assert.containsN($seenIcon, '.fa-check', 2, "should still display 2 checks");
+
+ await testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
+ $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
+ assert.isVisible($seenIconContent, "should still display content on seen icon mouseover");
+ assert.strictEqual($seenIconContent.text().replace(/\s/g, ""),
+ "Seenby:Someone(someone@example.com)Other(other@example.com)ReceivedbyEveryone");
+
+ await this.simulate({
+ action: 'seen',
+ channelID: 1,
+ partnerID: 5,
+ lastMessageID: 100,
+ widget: discuss,
+ });
+
+ $seenIcon = discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]');
+ assert.isVisible($seenIcon, "should still display seen icon on message");
+ assert.containsN($seenIcon, '.fa-check', 2, "should still display 2 checks");
+
+ await testUtils.dom.triggerMouseEvent($seenIcon, 'mouseover');
+ $seenIconContent = $('.o_mail_thread_message_seen_icon_content');
+ assert.isVisible($seenIconContent, "should still display content on seen icon mouseover");
+ assert.strictEqual($seenIconContent.text().trim(),
+ "Seen by Everyone");
+
+ discuss.destroy();
});
-QUnit.skip('several members: other message seen by everyone (initially not received)', function (assert) {
+QUnit.skip('several members: other message seen by everyone (initially not received)', async function (assert) {
// IMPORTANT: This test make sense if this feature is on multi user channels,
// which was the case in case at some point. It has been disabled for
// performance reasons. We are unsure if this will come back in the future,
@@ -849,9 +822,7 @@ QUnit.skip('several members: other message seen by everyone (initially not recei
// seen icon should never be visible for message of others
assert.expect(9);
- var done = assert.async();
- var self = this;
var members = [{
id: 2,
name: "Someone",
@@ -912,7 +883,7 @@ QUnit.skip('several members: other message seen by everyone (initially not recei
res_id: 1,
}];
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -921,103 +892,99 @@ QUnit.skip('several members: other message seen by everyone (initially not recei
session: { partner_id: 3 },
mockRPC: function (route, args) {
if (args.method === 'channel_fetch_listeners') {
- return $.when(members);
+ return Promise.resolve(members);
}
return this._super.apply(this, arguments);
},
- }).then(function (discuss) {
- // click on general
- var $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- testUtils.dom.click($general);
-
- assert.isVisible(discuss.$('.o_thread_message[data-message-id=100]'));
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
-
- self.simulate({
- action: 'received',
- channelID: 1,
- partnerID: 3,
- lastMessageID: 100,
- widget: discuss,
- });
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'),
- "should not display seen icon on message of other users");
-
- self.simulate({
- action: 'seen',
- channelID: 1,
- partnerID: 3,
- lastMessageID: 100,
- widget: discuss,
- });
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'),
- "should not display seen icon on message of other users");
-
- self.simulate({
- action: 'received',
- channelID: 1,
- partnerID: 4,
- lastMessageID: 100,
- widget: discuss,
- });
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'),
- "should not display seen icon on message of other users");
-
- self.simulate({
- action: 'seen',
- channelID: 1,
- partnerID: 2,
- lastMessageID: 100,
- widget: discuss,
- });
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'),
- "should not display seen icon on message of other users");
-
- self.simulate({
- action: 'seen',
- channelID: 1,
- partnerID: 4,
- lastMessageID: 100,
- widget: discuss,
- });
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'),
- "should not display seen icon on message of other users");
-
- self.simulate({
- action: 'received',
- channelID: 1,
- partnerID: 5,
- lastMessageID: 100,
- widget: discuss,
- });
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'),
- "should not display seen icon on message of other users");
-
- self.simulate({
- action: 'seen',
- channelID: 1,
- partnerID: 5,
- lastMessageID: 100,
- widget: discuss,
- });
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'),
- "should not display seen icon on message of other users");
-
- discuss.destroy();
- done();
});
+ // click on general
+ var $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ await testUtils.dom.click($general);
+
+ assert.isVisible(discuss.$('.o_thread_message[data-message-id=100]'));
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
+
+ await this.simulate({
+ action: 'received',
+ channelID: 1,
+ partnerID: 3,
+ lastMessageID: 100,
+ widget: discuss,
+ });
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'),
+ "should not display seen icon on message of other users");
+
+ await this.simulate({
+ action: 'seen',
+ channelID: 1,
+ partnerID: 3,
+ lastMessageID: 100,
+ widget: discuss,
+ });
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'),
+ "should not display seen icon on message of other users");
+
+ await this.simulate({
+ action: 'received',
+ channelID: 1,
+ partnerID: 4,
+ lastMessageID: 100,
+ widget: discuss,
+ });
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'),
+ "should not display seen icon on message of other users");
+
+ await this.simulate({
+ action: 'seen',
+ channelID: 1,
+ partnerID: 2,
+ lastMessageID: 100,
+ widget: discuss,
+ });
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'),
+ "should not display seen icon on message of other users");
+
+ await this.simulate({
+ action: 'seen',
+ channelID: 1,
+ partnerID: 4,
+ lastMessageID: 100,
+ widget: discuss,
+ });
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'),
+ "should not display seen icon on message of other users");
+
+ await this.simulate({
+ action: 'received',
+ channelID: 1,
+ partnerID: 5,
+ lastMessageID: 100,
+ widget: discuss,
+ });
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'),
+ "should not display seen icon on message of other users");
+
+ await this.simulate({
+ action: 'seen',
+ channelID: 1,
+ partnerID: 5,
+ lastMessageID: 100,
+ widget: discuss,
+ });
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'),
+ "should not display seen icon on message of other users");
+
+ discuss.destroy();
});
-QUnit.skip('several members: only show seen icons from last message seen by everyone', function (assert) {
+QUnit.skip('several members: only show seen icons from last message seen by everyone', async function (assert) {
// IMPORTANT: This test make sense if this feature is on multi user channels,
// which was the case in case at some point. It has been disabled for
// performance reasons. We are unsure if this will come back in the future,
// so we keep to tests in 'skip' mode in the mean time.
assert.expect(12);
- var done = assert.async();
- var self = this;
var members = [{
id: 2,
name: "Someone",
@@ -1092,7 +1059,7 @@ QUnit.skip('several members: only show seen icons from last message seen by ever
res_id: 1,
}];
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -1101,55 +1068,53 @@ QUnit.skip('several members: only show seen icons from last message seen by ever
session: { partner_id: 3 },
mockRPC: function (route, args) {
if (args.method === 'channel_fetch_listeners') {
- return $.when(members);
+ return Promise.resolve(members);
}
return this._super.apply(this, arguments);
},
- }).then(function (discuss) {
- // click on general
- var $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- testUtils.dom.click($general);
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=98]'));
- assert.isVisible(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=99]'));
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
-
- self.simulate({
- action: 'seen',
- channelID: 1,
- partnerID: 2,
- lastMessageID: 100,
- widget: discuss,
- });
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=98]'));
- assert.isVisible(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=99]'));
- assert.isVisible(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
-
- self.simulate({
- action: 'seen',
- channelID: 1,
- partnerID: 4,
- lastMessageID: 100,
- widget: discuss,
- });
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=98]'));
- assert.isVisible(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=99]'));
- assert.isVisible(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
-
- self.simulate({
- action: 'seen',
- channelID: 1,
- partnerID: 5,
- lastMessageID: 100,
- widget: discuss,
- });
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=98]'));
- assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=99]'));
- assert.isVisible(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
-
- discuss.destroy();
- done();
});
+ // click on general
+ var $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ await testUtils.dom.click($general);
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=98]'));
+ assert.isVisible(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=99]'));
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
+
+ await this.simulate({
+ action: 'seen',
+ channelID: 1,
+ partnerID: 2,
+ lastMessageID: 100,
+ widget: discuss,
+ });
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=98]'));
+ assert.isVisible(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=99]'));
+ assert.isVisible(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
+
+ await this.simulate({
+ action: 'seen',
+ channelID: 1,
+ partnerID: 4,
+ lastMessageID: 100,
+ widget: discuss,
+ });
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=98]'));
+ assert.isVisible(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=99]'));
+ assert.isVisible(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
+
+ await this.simulate({
+ action: 'seen',
+ channelID: 1,
+ partnerID: 5,
+ lastMessageID: 100,
+ widget: discuss,
+ });
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=98]'));
+ assert.containsNone(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=99]'));
+ assert.isVisible(discuss.$('.o_mail_thread_message_seen_icon[data-message-id=100]'));
+
+ discuss.destroy();
});
});
diff --git a/addons/mail/static/tests/discuss_tests.js b/addons/mail/static/tests/discuss_tests.js
index 02cb977b246..7dc8be4320c 100644
--- a/addons/mail/static/tests/discuss_tests.js
+++ b/addons/mail/static/tests/discuss_tests.js
@@ -83,73 +83,66 @@ QUnit.module('Discuss', {
}
});
-QUnit.test('basic rendering', function (assert) {
+QUnit.test('basic rendering', async function (assert) {
assert.expect(5);
- var done = assert.async();
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
data: this.data,
services: this.services,
- })
- .then(function (discuss) {
- // test basic rendering
- var $sidebar = discuss.$('.o_mail_discuss_sidebar');
- assert.strictEqual($sidebar.length, 1,
- "should have rendered a sidebar");
-
- assert.containsOnce(discuss, '.o_mail_discuss_content',
- "should have rendered the content");
- assert.containsOnce(discuss, '.o_mail_no_content',
- "should display no content message");
-
- var $inbox = $sidebar.find('.o_mail_discuss_item[data-thread-id=mailbox_inbox]');
- assert.strictEqual($inbox.length, 1,
- "should have the channel item 'mailbox_inbox' in the sidebar");
-
- var $starred = $sidebar.find('.o_mail_discuss_item[data-thread-id=mailbox_starred]');
- assert.strictEqual($starred.length, 1,
- "should have the channel item 'mailbox_starred' in the sidebar");
- discuss.destroy();
- done();
});
+
+ // test basic rendering
+ var $sidebar = discuss.$('.o_mail_discuss_sidebar');
+ assert.strictEqual($sidebar.length, 1,
+ "should have rendered a sidebar");
+
+ assert.containsOnce(discuss, '.o_mail_discuss_content',
+ "should have rendered the content");
+ assert.containsOnce(discuss, '.o_mail_no_content',
+ "should display no content message");
+
+ var $inbox = $sidebar.find('.o_mail_discuss_item[data-thread-id=mailbox_inbox]');
+ assert.strictEqual($inbox.length, 1,
+ "should have the channel item 'mailbox_inbox' in the sidebar");
+
+ var $starred = $sidebar.find('.o_mail_discuss_item[data-thread-id=mailbox_starred]');
+ assert.strictEqual($starred.length, 1,
+ "should have the channel item 'mailbox_starred' in the sidebar");
+ discuss.destroy();
});
-QUnit.test('searchview options visibility', function (assert) {
+QUnit.test('searchview options visibility', async function (assert) {
assert.expect(5);
- var done = assert.async();
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
data: this.data,
services: this.services,
- })
- .then(function (discuss) {
- assert.containsOnce(discuss, '.o_control_panel .o_search_options',
- "should have search options");
- assert.hasClass(discuss.$('.o_control_panel .o_searchview_more.fa'), 'fa-search-minus',
- "should have a button to toggle search options");
-
- assert.isVisible(discuss.$('.o_control_panel .o_search_options'),
- "search options should be visible by default");
- testUtils.dom.click(discuss.$('.o_control_panel .o_searchview_more.fa'));
- assert.hasClass(discuss.$('.o_control_panel .o_searchview_more.fa'), 'fa-search-plus',
- "should have a button to toggle search options");
- assert.isNotVisible(discuss.$('.o_control_panel .o_search_options'),
- "search options should be hidden after clicking on search option toggler");
-
- discuss.destroy();
- done();
});
+
+ assert.containsOnce(discuss, '.o_control_panel .o_search_options',
+ "should have search options");
+ assert.hasClass(discuss.$('.o_control_panel .o_searchview_more.fa'), 'fa-search-minus',
+ "should have a button to toggle search options");
+
+ assert.isVisible(discuss.$('.o_control_panel .o_search_options'),
+ "search options should be visible by default");
+ await testUtils.dom.click(discuss.$('.o_control_panel .o_searchview_more.fa'));
+ assert.hasClass(discuss.$('.o_control_panel .o_searchview_more.fa'), 'fa-search-plus',
+ "should have a button to toggle search options");
+ assert.isNotVisible(discuss.$('.o_control_panel .o_search_options'),
+ "search options should be hidden after clicking on search option toggler");
+
+ discuss.destroy();
});
-QUnit.test('searchview filter messages', function (assert) {
+QUnit.test('searchview filter messages', async function (assert) {
assert.expect(10);
- var done = assert.async();
this.data['mail.message'].records = [{
author_id: [5, 'Demo User'],
@@ -165,7 +158,7 @@ QUnit.test('searchview filter messages', function (assert) {
needaction_partner_ids: [3],
}];
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -180,8 +173,7 @@ QUnit.test('searchview filter messages', function (assert) {
'<field name="body"/>' +
'</search>',
},
- })
- .then(function (discuss) {
+ });
assert.containsN(discuss, '.o_thread_message', 2,
"there should be two messages in the inbox mailbox");
assert.strictEqual($('.o_searchview_input').length, 1,
@@ -191,8 +183,9 @@ QUnit.test('searchview filter messages', function (assert) {
// interact with searchview so that there is only once message
$('.o_searchview_input').val("ab").trigger('keyup');
+ await testUtils.nextTick();
$('.o_searchview_input').trigger($.Event('keydown', { which: $.ui.keyCode.ENTER }));
-
+ await testUtils.nextTick();
assert.strictEqual($('.o_searchview_facet').length, 1,
"the searchview should have a facet");
assert.strictEqual($('.o_facet_values').text().trim(), 'ab',
@@ -201,9 +194,11 @@ QUnit.test('searchview filter messages', function (assert) {
"there should be a single message after filter");
// interact with search view so that there are no matching messages
- testUtils.dom.click($('.o_facet_remove'));
+ await testUtils.dom.click($('.o_facet_remove'));
$('.o_searchview_input').val("abcd").trigger('keyup');
+ await testUtils.nextTick();
$('.o_searchview_input').trigger($.Event('keydown', { which: $.ui.keyCode.ENTER }));
+ await testUtils.nextTick();
assert.strictEqual($('.o_searchview_facet').length, 1,
"the searchview should have a facet");
@@ -216,17 +211,15 @@ QUnit.test('searchview filter messages', function (assert) {
"should display that there are no matching messages");
discuss.destroy();
- done();
- });
+
});
-QUnit.test('unescape channel name in the sidebar', function (assert) {
+QUnit.test('unescape channel name in the sidebar', async function (assert) {
// When the user creates a channel, the channel's name is escaped, this in
// order to prevent XSS attacks. However, the user should see visually the
// unescaped name of the channel. For instance, when the user creates a
// channel named "R&D", he should see "R&D" and not "R&amp;D".
assert.expect(2);
- var done = assert.async();
this.data.initMessaging = {
channel_slots: {
@@ -238,34 +231,31 @@ QUnit.test('unescape channel name in the sidebar', function (assert) {
},
};
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
data: this.data,
services: this.services,
- })
- .then(function (discuss) {
- var $sidebar = discuss.$('.o_mail_discuss_sidebar');
+ });
- var $channel = $sidebar.find('.o_mail_discuss_item[data-thread-id=1]');
- assert.strictEqual($channel.length, 1,
- "should have the channel item for channel 1 in the sidebar");
- assert.strictEqual($channel.find('.o_thread_name').text().replace(/\s/g, ''),
- "#R&D",
- "should have unescaped channel name in the sidebar");
+ var $sidebar = discuss.$('.o_mail_discuss_sidebar');
- discuss.destroy();
- done();
- });
+ var $channel = $sidebar.find('.o_mail_discuss_item[data-thread-id=1]');
+ assert.strictEqual($channel.length, 1,
+ "should have the channel item for channel 1 in the sidebar");
+ assert.strictEqual($channel.find('.o_thread_name').text().replace(/\s/g, ''),
+ "#R&D",
+ "should have unescaped channel name in the sidebar");
+
+ discuss.destroy();
});
-QUnit.test('@ mention in channel', function (assert) {
+QUnit.test('@ mention in channel', async function (assert) {
assert.expect(34);
- var done = assert.async();
- var fetchListenersDef = $.Deferred();
- var receiveMessageDef = $.Deferred();
+ var fetchListenersDef = testUtils.makeTestPromise();
+ var receiveMessageDef = testUtils.makeTestPromise();
this.data.initMessaging = {
channel_slots: {
@@ -276,9 +266,8 @@ QUnit.test('@ mention in channel', function (assert) {
}],
},
};
-
var objectDiscuss;
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -287,7 +276,7 @@ QUnit.test('@ mention in channel', function (assert) {
mockRPC: function (route, args) {
if (args.method === 'channel_fetch_listeners') {
fetchListenersDef.resolve();
- return $.when([
+ return Promise.resolve([
{id: 1, name: 'Admin'},
{id: 2, name: 'TestUser'},
{id: 3, name: 'DemoUser'}
@@ -302,142 +291,133 @@ QUnit.test('@ mention in channel', function (assert) {
var notification = [[false, 'mail.channel', 1], data];
objectDiscuss.call('bus_service', 'trigger', 'notification', [notification]);
receiveMessageDef.resolve();
- return $.when(42);
+ return Promise.resolve(42);
}
return this._super.apply(this, arguments);
},
- })
- .then(function (discuss) {
- objectDiscuss = discuss;
-
- var $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- assert.strictEqual($general.length, 1,
- "should have the channel item with id 1");
- assert.hasAttrValue($general, 'title', 'general',
- "should have the title 'general'");
-
- // click on general
- testUtils.dom.click($general);
- var $input = discuss.$('textarea.o_composer_text_field').first();
- assert.ok($input.length, "should display a composer input");
-
- // Note: focus is needed in order to trigger rpc 'channel_fetch_listeners'
- $input.focus();
- $input.val("@");
- $input.trigger('keyup');
-
- fetchListenersDef
- .then(concurrency.delay.bind(concurrency, 0))
- .then(function () {
- assert.containsOnce(discuss, '.dropup.o_composer_mention_dropdown.show',
- "dropup menu for partner mentions should be open");
-
- var $mentionPropositions = discuss.$('.o_mention_proposition');
- assert.strictEqual($mentionPropositions.length, 3,
- "should display 3 partner mention propositions");
-
- var $mention1 = $mentionPropositions.first();
- var $mention2 = $mentionPropositions.first().next();
- var $mention3 = $mentionPropositions.first().next().next();
-
- // correct 1st mention proposition
- assert.hasClass($mention1,'active',
- "first partner mention should be active");
- assert.strictEqual($mention1.data('id'), 1,
- "first partner mention should link to the correct partner id");
- assert.strictEqual($mention1.find('.o_mention_name').text(), "Admin",
- "first partner mention should display the correct partner name");
- // correct 2nd mention proposition
- assert.doesNotHaveClass($mention2, 'active',
- "second partner mention should not be active");
- assert.strictEqual($mention2.data('id'), 2,
- "second partner mention should link to the correct partner id");
- assert.strictEqual($mention2.find('.o_mention_name').text(), "TestUser",
- "second partner mention should display the correct partner name");
- // correct 3rd mention proposition
- assert.doesNotHaveClass($mention3, 'active',
- "third partner mention should not be active");
- assert.strictEqual($mention3.data('id'), 3,
- "third partner mention should link to the correct partner id");
- assert.strictEqual($mention3.find('.o_mention_name').text(), "DemoUser",
- "third partner mention should display the correct partner name");
-
- // check DOWN event
- $input.trigger($.Event('keyup', {which: $.ui.keyCode.DOWN}));
- assert.doesNotHaveClass($mention1, 'active',
- "first partner mention should not be active");
- assert.hasClass($mention2,'active',
- "second partner mention should be active");
- assert.doesNotHaveClass($mention3, 'active',
- "third partner mention should not be active");
-
- // check UP event
- $input.trigger($.Event('keyup', {which: $.ui.keyCode.UP}));
- assert.hasClass($mention1,'active',
- "first partner mention should be active");
- assert.doesNotHaveClass($mention2, 'active',
- "second partner mention should not be active");
- assert.doesNotHaveClass($mention3, 'active',
- "third partner mention should not be active");
-
- // check TAB event (full cycle, hence 3 TABs)
- $input.trigger($.Event('keyup', {which: $.ui.keyCode.TAB}));
- assert.doesNotHaveClass($mention1, 'active',
- "first partner mention should not be active");
- assert.hasClass($mention2,'active',
- "second partner mention should be active");
- assert.doesNotHaveClass($mention3, 'active',
- "third partner mention should not be active");
-
- $input.trigger($.Event('keyup', {which: $.ui.keyCode.TAB}));
- assert.doesNotHaveClass($mention1, 'active',
- "first partner mention should not be active");
- assert.doesNotHaveClass($mention2, 'active',
- "second partner mention should not be active");
- assert.hasClass($mention3,'active',
- "third partner mention should be active");
-
- $input.trigger($.Event('keyup', {which: $.ui.keyCode.TAB}));
- assert.hasClass($mention1,'active',
- "first partner mention should be active");
- assert.doesNotHaveClass($mention2, 'active',
- "second partner mention should not be active");
- assert.doesNotHaveClass($mention3, 'active',
- "third partner mention should not be active");
-
-// testUtils.dom.click( equivalent to $mentionPropositions.find('active'));
- $input.trigger($.Event('keyup', {which: $.ui.keyCode.ENTER}));
- assert.containsNone(discuss, '.o_mention_proposition',
- "should not have any partner mention proposition after ENTER");
- assert.strictEqual($input.val().trim() , "@Admin",
- "should have the correct mention link in the composer input");
-
- // send message
- $input.trigger($.Event('keydown', {which: $.ui.keyCode.ENTER}));
-
- receiveMessageDef
- .then(concurrency.delay.bind(concurrency, 0))
- .then(function () {
- assert.containsOnce(discuss, '.o_thread_message_content',
- "should display one message with some content");
- assert.containsOnce(discuss, '.o_thread_message_content a',
- "should contain a link in the message content");
- assert.strictEqual(discuss.$('.o_thread_message_content a').text(),
- "@Admin", "should have correct mention link in the message content");
-
- discuss.destroy();
- done();
- });
- });
});
+ objectDiscuss = discuss;
+ var $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ assert.strictEqual($general.length, 1,
+ "should have the channel item with id 1");
+ assert.hasAttrValue($general, 'title', 'general',
+ "should have the title 'general'");
+
+ // click on general
+ await testUtils.dom.click($general);
+ var $input = discuss.$('textarea.o_composer_text_field').first();
+ assert.ok($input.length, "should display a composer input");
+
+ // Note: focus is needed in order to trigger rpc 'channel_fetch_listeners'
+ $input.focus();
+ $input.val("@");
+ $input.trigger('keyup');
+
+ fetchListenersDef;
+ await testUtils.nextTick();
+ assert.containsOnce(discuss, '.dropup.o_composer_mention_dropdown.show',
+ "dropup menu for partner mentions should be open");
+
+ var $mentionPropositions = discuss.$('.o_mention_proposition');
+ assert.strictEqual($mentionPropositions.length, 3,
+ "should display 3 partner mention propositions");
+
+ var $mention1 = $mentionPropositions.first();
+ var $mention2 = $mentionPropositions.first().next();
+ var $mention3 = $mentionPropositions.first().next().next();
+
+ // correct 1st mention proposition
+ assert.hasClass($mention1,'active',
+ "first partner mention should be active");
+ assert.strictEqual($mention1.data('id'), 1,
+ "first partner mention should link to the correct partner id");
+ assert.strictEqual($mention1.find('.o_mention_name').text(), "Admin",
+ "first partner mention should display the correct partner name");
+ // correct 2nd mention proposition
+ assert.doesNotHaveClass($mention2, 'active',
+ "second partner mention should not be active");
+ assert.strictEqual($mention2.data('id'), 2,
+ "second partner mention should link to the correct partner id");
+ assert.strictEqual($mention2.find('.o_mention_name').text(), "TestUser",
+ "second partner mention should display the correct partner name");
+ // correct 3rd mention proposition
+ assert.doesNotHaveClass($mention3, 'active',
+ "third partner mention should not be active");
+ assert.strictEqual($mention3.data('id'), 3,
+ "third partner mention should link to the correct partner id");
+ assert.strictEqual($mention3.find('.o_mention_name').text(), "DemoUser",
+ "third partner mention should display the correct partner name");
+
+ // check DOWN event
+ await testUtils.fields.triggerKey('up', $input, 'down');
+ assert.doesNotHaveClass($mention1, 'active',
+ "first partner mention should not be active");
+ assert.hasClass($mention2,'active',
+ "second partner mention should be active");
+ assert.doesNotHaveClass($mention3, 'active',
+ "third partner mention should not be active");
+
+ // check UP event
+ await testUtils.fields.triggerKey('up', $input, 'up');
+ assert.hasClass($mention1,'active',
+ "first partner mention should be active");
+ assert.doesNotHaveClass($mention2, 'active',
+ "second partner mention should not be active");
+ assert.doesNotHaveClass($mention3, 'active',
+ "third partner mention should not be active");
+
+ // check TAB event (full cycle, hence 3 TABs)
+ await testUtils.fields.triggerKey('up', $input, 'tab');
+ assert.doesNotHaveClass($mention1, 'active',
+ "first partner mention should not be active");
+ assert.hasClass($mention2,'active',
+ "second partner mention should be active");
+ assert.doesNotHaveClass($mention3, 'active',
+ "third partner mention should not be active");
+
+ await testUtils.fields.triggerKey('up', $input, 'tab');
+ assert.doesNotHaveClass($mention1, 'active',
+ "first partner mention should not be active");
+ assert.doesNotHaveClass($mention2, 'active',
+ "second partner mention should not be active");
+ assert.hasClass($mention3,'active',
+ "third partner mention should be active");
+
+ await testUtils.fields.triggerKey('up', $input, 'tab');
+ assert.hasClass($mention1,'active',
+ "first partner mention should be active");
+ assert.doesNotHaveClass($mention2, 'active',
+ "second partner mention should not be active");
+ assert.doesNotHaveClass($mention3, 'active',
+ "third partner mention should not be active");
+
+ await testUtils.fields.triggerKey('up', $input, 'enter');
+ assert.containsNone(discuss, '.o_mention_proposition',
+ "should not have any partner mention proposition after ENTER");
+ assert.strictEqual($input.val().trim() , "@Admin",
+ "should have the correct mention link in the composer input");
+
+ // send message
+ await testUtils.fields.triggerKeydown($input, 'enter');
+
+ await receiveMessageDef;
+ await testUtils.nextTick();
+
+ assert.containsOnce(discuss, '.o_thread_message_content',
+ "should display one message with some content");
+ assert.containsOnce(discuss, '.o_thread_message_content a',
+ "should contain a link in the message content");
+ assert.strictEqual(discuss.$('.o_thread_message_content a').text(),
+ "@Admin", "should have correct mention link in the message content");
+
+ discuss.destroy();
});
-QUnit.test('@ mention with special chars', function (assert) {
+QUnit.test('@ mention with special chars', async function (assert) {
assert.expect(11);
- var done = assert.async();
- var fetchListenersDef = $.Deferred();
- var receiveMessageDef = $.Deferred();
+ var fetchListenersDef = testUtils.makeTestPromise();
+ var receiveMessageDef = testUtils.makeTestPromise();
this.data.initMessaging = {
channel_slots: {
channel_channel: [{
@@ -448,7 +428,7 @@ QUnit.test('@ mention with special chars', function (assert) {
},
};
var objectDiscuss;
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -457,7 +437,7 @@ QUnit.test('@ mention with special chars', function (assert) {
mockRPC: function (route, args) {
if (args.method === 'channel_fetch_listeners') {
fetchListenersDef.resolve();
- return $.when([
+ return Promise.resolve([
{id: 1, name: '\u0405pëciãlUser<&>"`\' \u30C4'},
]);
}
@@ -473,70 +453,64 @@ QUnit.test('@ mention with special chars', function (assert) {
var notification = [[false, 'mail.channel', 1], data];
objectDiscuss.call('bus_service', 'trigger', 'notification', [notification]);
receiveMessageDef.resolve();
- return $.when(42);
+ return Promise.resolve(42);
}
return this._super.apply(this, arguments);
},
- })
- .then(function (discuss) {
- objectDiscuss = discuss;
- var $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- // click on general
- $general.click();
- var $input = discuss.$('textarea.o_composer_text_field').first();
- assert.ok($input.length, "should display a composer input");
- // Note: focus is needed in order to trigger rpc 'channel_fetch_listeners'
- $input.focus();
- $input.val("@");
- $input.trigger('keyup');
- fetchListenersDef
- .then(concurrency.delay.bind(concurrency, 0))
- .then(function () {
- var $mention = discuss.$('.o_mention_proposition');
- // correct mention proposition
- assert.ok($mention.hasClass('active'),
- "first partner mention should be active");
- assert.strictEqual($mention.data('id'), 1,
- "first partner mention should link to the correct partner id");
- assert.strictEqual($mention.find('.o_mention_name').text(), '\u0405pëciãlUser<&>"`\' \u30C4',
- "first partner mention should display the correct partner name");
- // equivalent to $mentionPropositions.find('active').click();
- $input.trigger($.Event('keyup', {which: $.ui.keyCode.ENTER}));
- assert.strictEqual(discuss.$('.o_mention_proposition').length, 0,
- "should not have any partner mention proposition after ENTER");
- assert.strictEqual($input.val().trim() , "@\u0405pëciãlUser<&>\"`'\u00A0\u30C4",
- "should have the correct mention link in the composer input");
- // send message
- $input.trigger($.Event('keydown', {which: $.ui.keyCode.ENTER}));
- receiveMessageDef
- .then(concurrency.delay.bind(concurrency, 0))
- .then(function () {
- assert.strictEqual(discuss.$('.o_thread_message_content').length, 1,
- "should display one message with some content");
- assert.strictEqual(discuss.$('.o_thread_message_content a').length, 1,
- "should contain a link in the message content");
- assert.strictEqual(discuss.$('.o_thread_message_content a').text(),
- "@\u0405pëciãlUser<&>\"`' \u30C4",
- "should have correct mention link in the message content");
- $input.val("@");
- $input.trigger('keyup');
- var $mention = discuss.$('.o_mention_proposition');
- assert.strictEqual($mention.find('.o_mention_name').text(),
- '\u0405pëciãlUser<&>"`\' \u30C4',
- "first partner mention should still display the correct partner name");
- discuss.destroy();
- done();
- });
- });
});
+ objectDiscuss = discuss;
+ var $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ // click on general
+ $general.click();
+ await testUtils.nextTick();
+ var $input = discuss.$('textarea.o_composer_text_field').first();
+ assert.ok($input.length, "should display a composer input");
+ // Note: focus is needed in order to trigger rpc 'channel_fetch_listeners'
+ $input.focus();
+ $input.val("@");
+ $input.trigger('keyup');
+ await fetchListenersDef;
+ await testUtils.nextTick();
+ var $mention = discuss.$('.o_mention_proposition');
+ // correct mention proposition
+ assert.ok($mention.hasClass('active'),
+ "first partner mention should be active");
+ assert.strictEqual($mention.data('id'), 1,
+ "first partner mention should link to the correct partner id");
+ assert.strictEqual($mention.find('.o_mention_name').text(), '\u0405pëciãlUser<&>"`\' \u30C4',
+ "first partner mention should display the correct partner name");
+ // equivalent to $mentionPropositions.find('active').click();
+ await testUtils.fields.triggerKey('up', $input, 'enter');
+ assert.strictEqual(discuss.$('.o_mention_proposition').length, 0,
+ "should not have any partner mention proposition after ENTER");
+ assert.strictEqual($input.val().trim() , "@\u0405pëciãlUser<&>\"`'\u00A0\u30C4",
+ "should have the correct mention link in the composer input");
+ // send message
+ await testUtils.fields.triggerKeydown($input, 'enter');
+ await receiveMessageDef;
+ await testUtils.nextTick();
+ assert.strictEqual(discuss.$('.o_thread_message_content').length, 1,
+ "should display one message with some content");
+ assert.strictEqual(discuss.$('.o_thread_message_content a').length, 1,
+ "should contain a link in the message content");
+ assert.strictEqual(discuss.$('.o_thread_message_content a').text(),
+ "@\u0405pëciãlUser<&>\"`' \u30C4",
+ "should have correct mention link in the message content");
+ $input.val("@");
+ $input.trigger('keyup');
+ await testUtils.nextTick();
+ var $mention = discuss.$('.o_mention_proposition');
+ assert.strictEqual($mention.find('.o_mention_name').text(),
+ '\u0405pëciãlUser<&>"`\' \u30C4',
+ "first partner mention should still display the correct partner name");
+ discuss.destroy();
});
-QUnit.test('@ mention in mailing channel', function (assert) {
+QUnit.test('@ mention in mailing channel', async function (assert) {
assert.expect(8);
- var done = assert.async();
- var fetchListenersDef = $.Deferred();
+ var fetchListenersDef = testUtils.makeTestPromise();
this.data.initMessaging = {
channel_slots: {
@@ -549,7 +523,7 @@ QUnit.test('@ mention in mailing channel', function (assert) {
},
};
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -558,62 +532,58 @@ QUnit.test('@ mention in mailing channel', function (assert) {
mockRPC: function (route, args) {
if (args.method === 'channel_fetch_listeners') {
fetchListenersDef.resolve();
- return $.when([
+ return Promise.resolve([
{id: 1, name: 'Admin'},
]);
}
return this._super.apply(this, arguments);
},
- })
- .then(function (discuss) {
- var $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
-
- // click on general
- $general.click();
- // 1st composer: basic composer (hidden), 2nd composer: extended (shown)
- var $input = discuss.$('textarea.o_composer_text_field').eq(1);
- assert.ok($input.length, "should display a composer input");
-
- // Simulate '@' typed by user with mocked Window.getSelection
- // Note: focus is needed in order to trigger rpc 'channel_fetch_listeners'
- $input.focus();
- $input.val("@");
- $input.trigger('keyup');
-
- fetchListenersDef
- .then(concurrency.delay.bind(concurrency, 0))
- .then(function () {
- assert.strictEqual(discuss.$('.dropup.o_composer_mention_dropdown.show').length, 1,
- "dropup menu for partner mentions should be open");
-
- var $mention = discuss.$('.o_mention_proposition');
- assert.strictEqual($mention.length, 1,
- "should display 1 partner mention proposition");
-
- // correct mention proposition
- assert.ok($mention.hasClass('active'),
- "partner mention should be active");
- assert.strictEqual($mention.data('id'), 1,
- "partner mention should link to the correct partner id");
- assert.strictEqual($mention.find('.o_mention_name').text(), "Admin",
- "partner mention should display the correct partner name");
-
- // equivalent to $mentionPropositions.find('active').click();
- $input.trigger($.Event('keyup', {which: $.ui.keyCode.ENTER}));
-
- assert.ok($input.is(':focus'), "composer body should have focus");
- assert.notOk(discuss.$('.o_composer_subject').is(':focus'));
-
- discuss.destroy();
- done();
- });
});
+ var $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+
+ // click on general
+ $general.click();
+ await testUtils.nextTick();
+ // 1st composer: basic composer (hidden), 2nd composer: extended (shown)
+ var $input = discuss.$('textarea.o_composer_text_field').eq(1);
+ assert.ok($input.length, "should display a composer input");
+
+ // Simulate '@' typed by user with mocked Window.getSelection
+ // Note: focus is needed in order to trigger rpc 'channel_fetch_listeners'
+ $input.focus();
+ $input.val("@");
+ $input.trigger('keyup');
+
+ await fetchListenersDef;
+ await testUtils.nextTick();
+
+ assert.strictEqual(discuss.$('.dropup.o_composer_mention_dropdown.show').length, 1,
+ "dropup menu for partner mentions should be open");
+
+ var $mention = discuss.$('.o_mention_proposition');
+ assert.strictEqual($mention.length, 1,
+ "should display 1 partner mention proposition");
+
+ // correct mention proposition
+ assert.ok($mention.hasClass('active'),
+ "partner mention should be active");
+ assert.strictEqual($mention.data('id'), 1,
+ "partner mention should link to the correct partner id");
+ assert.strictEqual($mention.find('.o_mention_name').text(), "Admin",
+ "partner mention should display the correct partner name");
+
+ // equivalent to $mentionPropositions.find('active').click();
+ await testUtils.fields.triggerKey('up', $input, 'enter');
+
+ assert.ok($input.is(':focus'), "composer body should have focus");
+ assert.notOk(discuss.$('.o_composer_subject').is(':focus'));
+
+ discuss.destroy();
});
-QUnit.test('no crash focusout emoji button', function (assert) {
+QUnit.test('no crash focusout emoji button', async function (assert) {
assert.expect(3);
- var done = assert.async();
this.data.initMessaging = {
channel_slots: {
@@ -625,40 +595,37 @@ QUnit.test('no crash focusout emoji button', function (assert) {
},
};
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
data: this.data,
services: this.services,
})
- .then(function (discuss) {
- var $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- assert.strictEqual($general.length, 1,
- "should have the channel item with id 1");
- assert.hasAttrValue($general, 'title', 'general',
- "should have the title 'general'");
-
- // click on general
- testUtils.dom.click($general);
- discuss.$('.o_composer_button_emoji').focus();
- try {
- discuss.$('.o_composer_button_emoji').focusout();
- assert.ok(true, "should not crash on focusout of emoji button");
- } finally {
- discuss.destroy();
- done();
- }
- });
+
+ var $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ assert.strictEqual($general.length, 1,
+ "should have the channel item with id 1");
+ assert.hasAttrValue($general, 'title', 'general',
+ "should have the title 'general'");
+
+ // click on general
+ await testUtils.dom.click($general);
+ discuss.$('.o_composer_button_emoji').focus();
+ try {
+ discuss.$('.o_composer_button_emoji').focusout();
+ assert.ok(true, "should not crash on focusout of emoji button");
+ } finally {
+ discuss.destroy();
+ }
});
-QUnit.test('older messages are loaded on scroll', function (assert) {
+QUnit.test('older messages are loaded on scroll', async function (assert) {
assert.expect(10);
- var done = assert.async();
var fetchCount = 0;
- var loadMoreDef = $.Deferred();
+ var loadMoreDef = testUtils.makeTestPromise();
var messageData = [];
for (var i = 0; i < 35; i++) {
messageData.push({
@@ -681,7 +648,7 @@ QUnit.test('older messages are loaded on scroll', function (assert) {
};
this.data['mail.message'].records = messageData;
- createDiscuss({
+ var discuss = await createDiscuss({
context: {},
data: this.data,
params: {},
@@ -703,44 +670,39 @@ QUnit.test('older messages are loaded on scroll', function (assert) {
}
return this._super.apply(this, arguments);
},
- }).then(function (discuss) {
+ });
- assert.verifySteps(['message_fetch'],
- "should fetch messages once for needaction messages (Inbox)");
+ assert.verifySteps(['message_fetch'],
+ "should fetch messages once for needaction messages (Inbox)");
- var $general = discuss.$('.o_mail_discuss_item[data-thread-id=1]');
- assert.strictEqual($general.length, 1,
- "should have a channel item with id 1");
+ var $general = discuss.$('.o_mail_discuss_item[data-thread-id=1]');
+ assert.strictEqual($general.length, 1,
+ "should have a channel item with id 1");
- // switch to 'general'
- testUtils.dom.click($general);
+ // switch to 'general'
+ await testUtils.dom.click($general);
- assert.verifySteps(['message_fetch', 'message_fetch'],
- "should fetch a second time for general channel messages (30 last messages)");
+ assert.verifySteps(['message_fetch'],
+ "should fetch a second time for general channel messages (30 last messages)");
- assert.containsN(discuss, '.o_thread_message', 30,
- "should display the 30 messages");
+ assert.containsN(discuss, '.o_thread_message', 30,
+ "should display the 30 messages");
- // simulate a scroll to top to load more messages
- discuss.$('.o_mail_thread').scrollTop(0);
+ // simulate a scroll to top to load more messages
+ discuss.$('.o_mail_thread').scrollTop(0);
- loadMoreDef
- .then(concurrency.delay.bind(concurrency, 0))
- .then(function () {
- assert.verifySteps(['message_fetch', 'message_fetch', 'message_fetch'],
- "should fetch a third time for general channel messages (5 remaining messages)");
- assert.containsN(discuss, '.o_thread_message', 35,
- "all messages should now be loaded");
+ await loadMoreDef;
+ await testUtils.nextTick();
+ assert.verifySteps(['message_fetch'],
+ "should fetch a third time for general channel messages (5 remaining messages)");
+ assert.containsN(discuss, '.o_thread_message', 35,
+ "all messages should now be loaded");
- discuss.destroy();
- done();
- });
- });
+ discuss.destroy();
});
-QUnit.test('"Unstar all" button should reset the starred counter', function (assert) {
+QUnit.test('"Unstar all" button should reset the starred counter', async function (assert) {
assert.expect(2);
- var done = assert.async();
var messageData = [];
_.each(_.range(1, 41), function (num) {
@@ -768,7 +730,7 @@ QUnit.test('"Unstar all" button should reset the starred counter', function (ass
this.data['mail.message'].records = messageData;
var objectDiscuss;
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -783,37 +745,34 @@ QUnit.test('"Unstar all" button should reset the starred counter', function (ass
};
var notification = [[false, 'res.partner'], data];
objectDiscuss.call('bus_service', 'trigger', 'notification', [notification]);
- return $.when(42);
+ return Promise.resolve(42);
}
return this._super.apply(this, arguments);
},
session: {partner_id: 1},
})
- .then(function (discuss) {
- objectDiscuss = discuss;
- var $starred = discuss.$('.o_mail_discuss_sidebar').find('.o_mail_mailbox_title_starred');
- var $starredCounter = $('.o_mail_mailbox_title_starred > .o_mail_sidebar_needaction');
+ objectDiscuss = discuss;
- // Go to Starred channel
- testUtils.dom.click($starred);
- // Test Initial Value
- assert.strictEqual($starredCounter.text().trim(), "40", "40 messages should be starred");
+ var $starred = discuss.$('.o_mail_discuss_sidebar').find('.o_mail_mailbox_title_starred');
+ var $starredCounter = $('.o_mail_mailbox_title_starred > .o_mail_sidebar_needaction');
- // Unstar all and wait 'update_starred'
- testUtils.dom.click($('.o_control_panel .o_mail_discuss_button_unstar_all'));
- $starredCounter = $('.o_mail_mailbox_title_starred > .o_mail_sidebar_needaction');
- assert.strictEqual($starredCounter.text().trim(), "0",
- "All messages should be unstarred");
+ // Go to Starred channel
+ await testUtils.dom.click($starred);
+ // Test Initial Value
+ assert.strictEqual($starredCounter.text().trim(), "40", "40 messages should be starred");
- discuss.destroy();
- done();
- });
+ // Unstar all and wait 'update_starred'
+ await testUtils.dom.click($('.o_control_panel .o_mail_discuss_button_unstar_all'));
+ $starredCounter = $('.o_mail_mailbox_title_starred > .o_mail_sidebar_needaction');
+ assert.strictEqual($starredCounter.text().trim(), "0",
+ "All messages should be unstarred");
+
+ discuss.destroy();
});
-QUnit.test('confirm dialog when administrator leave (not chat) channel', function (assert) {
+QUnit.test('confirm dialog when administrator leave (not chat) channel', async function (assert) {
assert.expect(2);
- var done = assert.async();
this.data.initMessaging = {
channel_slots: {
@@ -826,7 +785,7 @@ QUnit.test('confirm dialog when administrator leave (not chat) channel', functio
},
};
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -835,30 +794,27 @@ QUnit.test('confirm dialog when administrator leave (not chat) channel', functio
session: {
uid: 3,
},
- })
- .then(function (discuss) {
- // Unsubscribe on MyChannel as administrator
- // The unpin icon is only shown when hovering on sidebar item.
- // helpter dom.click needs the element to be visible, hence the
- // hack on display of this icon.
- discuss.$('.o_mail_partner_unpin').css('display', 'block');
- testUtils.dom.click(discuss.$('.o_mail_partner_unpin'));
-
- assert.strictEqual($('.modal-dialog').length, 1,
- "should display a dialog");
- assert.strictEqual($('.modal-body').text(),
- "You are the administrator of this channel. Are you sure you want to unsubscribe?",
- "Warn user that he will be unsubscribed from channel as admin.");
- discuss.destroy();
- done();
});
+
+ // Unsubscribe on MyChannel as administrator
+ // The unpin icon is only shown when hovering on sidebar item.
+ // helpter dom.click needs the element to be visible, hence the
+ // hack on display of this icon.
+ discuss.$('.o_mail_partner_unpin').css('display', 'block');
+ await testUtils.dom.click(discuss.$('.o_mail_partner_unpin'));
+
+ assert.strictEqual($('.modal-dialog').length, 1,
+ "should display a dialog");
+ assert.strictEqual($('.modal-body').text(),
+ "You are the administrator of this channel. Are you sure you want to unsubscribe?",
+ "Warn user that he will be unsubscribed from channel as admin.");
+ discuss.destroy();
});
-QUnit.test('convert emoji sources to unicodes on message_post', function (assert) {
+QUnit.test('convert emoji sources to unicodes on message_post', async function (assert) {
assert.expect(2);
- var done = assert.async();
- var receiveMessageDef = $.Deferred();
+ var receiveMessageDef = testUtils.makeTestPromise();
this.data.initMessaging = {
channel_slots: {
@@ -871,7 +827,7 @@ QUnit.test('convert emoji sources to unicodes on message_post', function (assert
};
var objectDiscuss;
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -890,40 +846,34 @@ QUnit.test('convert emoji sources to unicodes on message_post', function (assert
var notification = [[false, 'mail.channel', 1], data];
objectDiscuss.call('bus_service', 'trigger', 'notification', [notification]);
receiveMessageDef.resolve();
- return $.when(42);
+ return Promise.resolve(42);
}
return this._super.apply(this, arguments);
},
})
- .then(function (discuss) {
- objectDiscuss= discuss;
- var $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
+ objectDiscuss= discuss;
- // click on general
- testUtils.dom.click($general);
- var $input = discuss.$('textarea.o_composer_text_field').first();
+ var $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
- $input.focus();
- $input.val(":) x'D");
- $input.trigger($.Event('keydown', {which: $.ui.keyCode.ENTER}));
+ // click on general
+ await testUtils.dom.click($general);
+ var $input = discuss.$('textarea.o_composer_text_field').first();
- receiveMessageDef
- .then(concurrency.delay.bind(concurrency, 0))
- .then(function () {
+ $input.focus();
+ $input.val(":) x'D");
+ await testUtils.fields.triggerKeydown($input, 'enter');
- assert.strictEqual(discuss.$('.o_thread_message_content').text().replace(/\s/g, ""),
- "😊😂",
- "New posted message should contain all emojis in their unicode representation");
- discuss.destroy();
- done();
- });
+ await receiveMessageDef.then(function () {
+ assert.strictEqual(discuss.$('.o_thread_message_content').text().replace(/\s/g, ""),
+ "😊😂",
+ "New posted message should contain all emojis in their unicode representation");
+ discuss.destroy();
});
});
-QUnit.test('mark all messages as read from Inbox', function (assert) {
- var done = assert.async();
+QUnit.test('mark all messages as read from Inbox', async function (assert) {
assert.expect(9);
this.data['mail.message'].records = [{
@@ -944,10 +894,10 @@ QUnit.test('mark all messages as read from Inbox', function (assert) {
needaction_inbox_counter: 2,
};
- var markAllReadDef = $.Deferred();
+ var markAllReadDef = testUtils.makeTestPromise();
var objectDiscuss;
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -966,53 +916,50 @@ QUnit.test('mark all messages as read from Inbox', function (assert) {
var notification = [[false, 'res.partner', 3], notificationData];
objectDiscuss.call('bus_service', 'trigger', 'notification', [notification]);
markAllReadDef.resolve();
- return $.when();
+ return Promise.resolve();
}
return this._super.apply(this, arguments);
},
})
- .then(function (discuss) {
- objectDiscuss = discuss;
-
- var $inbox = discuss.$('.o_mail_discuss_item[data-thread-id="mailbox_inbox"]');
- assert.strictEqual($inbox.length, 1,
- "there should be an 'Inbox' item in Discuss sidebar");
- assert.strictEqual($inbox.find('.o_mail_sidebar_needaction').text().trim(), "2",
- "the mailbox counter of 'Inbox' should be 2");
- assert.hasClass($inbox,'o_active',
- "'Inbox' should be the currently active thread");
- assert.containsN(discuss, '.o_thread_message', 2,
- "there should be 2 messages in inbox");
-
- var $markAllReadButton = $('.o_mail_discuss_button_mark_all_read');
- assert.strictEqual($markAllReadButton.length, 1,
- "there should be a 'Mark All As Read' button");
- assert.hasAttrValue($markAllReadButton, 'style',
- 'display: inline-block;',
- "the 'Mark All As Read' button should be visible");
- assert.notOk($markAllReadButton.prop('disabled'),
- "the 'Mark All As Read' button should not be disabled");
-
- testUtils.dom.click($markAllReadButton);
-
- markAllReadDef.then(function () {
- // immediately jump to end of the fadeout animation on messages
- $inbox = discuss.$('.o_mail_discuss_item[data-thread-id="mailbox_inbox"]');
- discuss.$('.o_thread_message').stop(false, true);
- assert.strictEqual($inbox.find('.o_mail_sidebar_needaction').text().trim(), "0",
- "the mailbox counter of 'Inbox' should have reset to 0");
- assert.containsNone(discuss, '.o_thread_message',
- "there should no message in inbox anymore");
-
- discuss.destroy();
- done();
- });
+
+ objectDiscuss = discuss;
+
+ var $inbox = discuss.$('.o_mail_discuss_item[data-thread-id="mailbox_inbox"]');
+ assert.strictEqual($inbox.length, 1,
+ "there should be an 'Inbox' item in Discuss sidebar");
+ assert.strictEqual($inbox.find('.o_mail_sidebar_needaction').text().trim(), "2",
+ "the mailbox counter of 'Inbox' should be 2");
+ assert.hasClass($inbox,'o_active',
+ "'Inbox' should be the currently active thread");
+ assert.containsN(discuss, '.o_thread_message', 2,
+ "there should be 2 messages in inbox");
+
+ var $markAllReadButton = $('.o_mail_discuss_button_mark_all_read');
+ assert.strictEqual($markAllReadButton.length, 1,
+ "there should be a 'Mark All As Read' button");
+ assert.hasAttrValue($markAllReadButton, 'style',
+ 'display: inline-block;',
+ "the 'Mark All As Read' button should be visible");
+ assert.notOk($markAllReadButton.prop('disabled'),
+ "the 'Mark All As Read' button should not be disabled");
+
+ await testUtils.dom.click($markAllReadButton);
+
+ markAllReadDef.then(function () {
+ // immediately jump to end of the fadeout animation on messages
+ $inbox = discuss.$('.o_mail_discuss_item[data-thread-id="mailbox_inbox"]');
+ discuss.$('.o_thread_message').stop(false, true);
+ assert.strictEqual($inbox.find('.o_mail_sidebar_needaction').text().trim(), "0",
+ "the mailbox counter of 'Inbox' should have reset to 0");
+ assert.containsNone(discuss, '.o_thread_message',
+ "there should no message in inbox anymore");
+
+ discuss.destroy();
});
});
-QUnit.test('drag and drop file in composer', function (assert) {
+QUnit.test('drag and drop file in composer [REQUIRE NON-INCOGNITO WINDOW]', async function (assert) {
assert.expect(8);
- var done = assert.async();
this.data.initMessaging = {
channel_slots: {
@@ -1024,60 +971,57 @@ QUnit.test('drag and drop file in composer', function (assert) {
},
};
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
data: this.data,
services: this.services,
})
- .then(function (discuss) {
- var $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
-
- // click on general
- testUtils.dom.click($general);
-
- // first composer is active (basic), 2nd is hidden (extended)
- var $composer = discuss.$('.o_thread_composer').first();
- assert.containsNone($composer, '.o_attachments_list',
- "should not display any attachment on the composer initially");
- assert.containsOnce($composer, '.o_file_drop_zone_container',
- "should have a dropzone to drag-and-drop files");
-
- var $dropZoneContainer = $composer.find('.o_file_drop_zone_container');
- assert.isNotVisible($dropZoneContainer,
- "dropzone should not be visible");
-
- testUtils.file.createFile({
- name: 'text.txt',
- content: 'hello, world',
- contentType: 'text/plain',
- }).then(function (file) {
- testUtils.file.dragoverFile($dropZoneContainer, file);
- assert.isVisible($dropZoneContainer,
- "dropzone should be visible");
-
- testUtils.file.dropFile($dropZoneContainer, file);
- assert.containsOnce($composer, '.o_attachments_list',
- "should display some attachments on the composer");
- assert.containsOnce($composer, '.o_attachment',
- "should display one attachment on the composer");
-
- var filename = $('.o_attachment').find('.caption').first().text().trim();
- assert.strictEqual(filename, 'text.txt',
- "should display the correct filename");
- assert.hasClass($('.o_attachment_uploaded i'), 'fa-check',
- "text file should have been uploaded");
-
- discuss.destroy();
- done();
- });
+
+ var $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+
+ // click on general
+ await testUtils.dom.click($general);
+
+ // first composer is active (basic), 2nd is hidden (extended)
+ var $composer = discuss.$('.o_thread_composer').first();
+ assert.containsNone($composer, '.o_attachments_list',
+ "should not display any attachment on the composer initially");
+ assert.containsOnce($composer, '.o_file_drop_zone_container',
+ "should have a dropzone to drag-and-drop files");
+
+ var $dropZoneContainer = $composer.find('.o_file_drop_zone_container');
+ assert.isNotVisible($dropZoneContainer,
+ "dropzone should not be visible");
+
+ var file = await testUtils.file.createFile({
+ name: 'text.txt',
+ content: 'hello, world',
+ contentType: 'text/plain',
});
+
+ await testUtils.file.dragoverFile($dropZoneContainer, file);
+ assert.isVisible($dropZoneContainer,
+ "dropzone should be visible");
+
+ await testUtils.file.dropFile($dropZoneContainer, file);
+ assert.containsOnce($composer, '.o_attachments_list',
+ "should display some attachments on the composer");
+ assert.containsOnce($composer, '.o_attachment',
+ "should display one attachment on the composer");
+
+ var filename = $('.o_attachment').find('.caption').first().text().trim();
+ assert.strictEqual(filename, 'text.txt',
+ "should display the correct filename");
+ assert.hasClass($('.o_attachment_uploaded i'), 'fa-check',
+ "text file should have been uploaded");
+
+ discuss.destroy();
});
-QUnit.test('reply to message from inbox', function (assert) {
- var done = assert.async();
+QUnit.test('reply to message from inbox', async function (assert) {
assert.expect(11);
var self = this;
@@ -1095,7 +1039,7 @@ QUnit.test('reply to message from inbox', function (assert) {
needaction_inbox_counter: 1,
};
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -1118,45 +1062,41 @@ QUnit.test('reply to message from inbox', function (assert) {
model: 'some.document',
record_name: 'SomeDocument',
});
- return $.when(2);
+ return Promise.resolve(2);
}
return this._super.apply(this, arguments);
},
})
- .then(function (discuss) {
- assert.strictEqual(discuss.$('.o_mail_discuss_item.o_active').data('thread-id'),
- 'mailbox_inbox',
- "Inbox should be selected by default");
- assert.containsOnce(discuss, '.o_thread_message',
- "should display a single message in inbox");
- assert.strictEqual(discuss.$('.o_thread_message').data('message-id'), 1,
- "message should be linked to correct message");
- assert.containsOnce(discuss.$('.o_thread_message'), '.o_thread_message_reply',
- "should display the reply icon for message linked to a document");
-
- testUtils.dom.click(discuss.$('.o_thread_message_reply'));
- var $composer = discuss.$('.o_thread_composer_extended');
- assert.isVisible($composer,
- "extended composer should become visible");
- assert.strictEqual($composer.find('.o_composer_subject input').val(),
- 'Re: SomeDocument',
- "composer should have copied document name as subject of message");
-
- var $textarea = $composer.find('.o_composer_input textarea').first();
- testUtils.fields.editInput($textarea, 'someContent');
- assert.containsOnce($composer, '.o_composer_button_send',
- "should have button to send reply message");
- testUtils.dom.click($composer.find('.o_composer_button_send'));
-
- assert.verifySteps(['message_post']);
-
- discuss.destroy();
- done();
- });
+ assert.strictEqual(discuss.$('.o_mail_discuss_item.o_active').data('thread-id'),
+ 'mailbox_inbox',
+ "Inbox should be selected by default");
+ assert.containsOnce(discuss, '.o_thread_message',
+ "should display a single message in inbox");
+ assert.strictEqual(discuss.$('.o_thread_message').data('message-id'), 1,
+ "message should be linked to correct message");
+ assert.containsOnce(discuss.$('.o_thread_message'), '.o_thread_message_reply',
+ "should display the reply icon for message linked to a document");
+
+ await testUtils.dom.click(discuss.$('.o_thread_message_reply'));
+ var $composer = discuss.$('.o_thread_composer_extended');
+ assert.isVisible($composer,
+ "extended composer should become visible");
+ assert.strictEqual($composer.find('.o_composer_subject input').val(),
+ 'Re: SomeDocument',
+ "composer should have copied document name as subject of message");
+
+ var $textarea = $composer.find('.o_composer_input textarea').first();
+ await testUtils.fields.editInput($textarea, 'someContent');
+ assert.containsOnce($composer, '.o_composer_button_send',
+ "should have button to send reply message");
+ await testUtils.dom.click($composer.find('.o_composer_button_send'));
+
+ assert.verifySteps(['message_post']);
+
+ discuss.destroy();
});
-QUnit.test('discard replying to message from inbox', function (assert) {
- var done = assert.async();
+QUnit.test('discard replying to message from inbox', async function (assert) {
assert.expect(4);
var self = this;
@@ -1174,7 +1114,7 @@ QUnit.test('discard replying to message from inbox', function (assert) {
needaction_inbox_counter: 1,
};
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -1197,34 +1137,31 @@ QUnit.test('discard replying to message from inbox', function (assert) {
model: 'some.document',
record_name: 'SomeDocument',
});
- return $.when(2);
+ return Promise.resolve(2);
}
return this._super.apply(this, arguments);
},
})
- .then(function (discuss) {
- testUtils.dom.click(discuss.$('.o_thread_message_reply'));
- assert.containsOnce(discuss, '.o_thread_selected_message',
- "should have a message selected");
- var $composer = discuss.$('.o_thread_composer_extended');
- assert.containsOnce($composer, '.o_composer_button_discard',
- "should have button to discard replying to message");
+ await testUtils.dom.click(discuss.$('.o_thread_message_reply'));
+ assert.containsOnce(discuss, '.o_thread_selected_message',
+ "should have a message selected");
- testUtils.dom.click($composer.find('.o_composer_button_discard'));
- assert.isNotVisible($composer,
- "extended composer should become hidden on discard");
- assert.containsNone(discuss, '.o_thread_selected_message',
- "should not longer have a message selected");
+ var $composer = discuss.$('.o_thread_composer_extended');
+ assert.containsOnce($composer, '.o_composer_button_discard',
+ "should have button to discard replying to message");
- discuss.destroy();
- done();
- });
+ await testUtils.dom.click($composer.find('.o_composer_button_discard'));
+ assert.isNotVisible($composer,
+ "extended composer should become hidden on discard");
+ assert.containsNone(discuss, '.o_thread_selected_message',
+ "should not longer have a message selected");
+
+ discuss.destroy();
});
-QUnit.test('no quick search channels in the sidebar with less than 20 channels', function (assert) {
+QUnit.test('no quick search channels in the sidebar with less than 20 channels', async function (assert) {
assert.expect(3);
- var done = assert.async();
var channelsData = [];
_.each(_.range(0, 19), function (num) {
@@ -1241,32 +1178,29 @@ QUnit.test('no quick search channels in the sidebar with less than 20 channels',
},
};
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
data: this.data,
services: this.services,
})
- .then(function (discuss) {
- var $sidebar = discuss.$('.o_mail_discuss_sidebar');
- var $channelsSidebar = $sidebar.find('.o_mail_discuss_sidebar_channels');
- assert.strictEqual($channelsSidebar.length, 1,
- "should show channels and dms in sidebar");
- assert.strictEqual($channelsSidebar.find('.o_mail_discuss_item').length, 19,
- "should show 19 channels in sidebar");
- assert.strictEqual(discuss.$('.o_discuss_sidebar_quick_search').length, 0,
- "should not display a quick search");
+ var $sidebar = discuss.$('.o_mail_discuss_sidebar');
- discuss.destroy();
- done();
- });
+ var $channelsSidebar = $sidebar.find('.o_mail_discuss_sidebar_channels');
+ assert.strictEqual($channelsSidebar.length, 1,
+ "should show channels and dms in sidebar");
+ assert.strictEqual($channelsSidebar.find('.o_mail_discuss_item').length, 19,
+ "should show 19 channels in sidebar");
+ assert.strictEqual(discuss.$('.o_discuss_sidebar_quick_search').length, 0,
+ "should not display a quick search");
+
+ discuss.destroy();
});
-QUnit.test('quick search channels in the sidebar with more than 20 channels', function (assert) {
+QUnit.test('quick search channels in the sidebar with more than 20 channels', async function (assert) {
assert.expect(7);
- var done = assert.async();
var channelsData = [];
var channelANum = 15;
@@ -1294,52 +1228,49 @@ QUnit.test('quick search channels in the sidebar with more than 20 channels', fu
},
};
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
data: this.data,
services: this.services,
})
- .then(function (discuss) {
- var $sidebar = discuss.$('.o_mail_discuss_sidebar');
- var $channelsSidebar = $sidebar.find('.o_mail_discuss_sidebar_channels');
- assert.strictEqual($channelsSidebar.length, 1,
- "should show channels in sidebar");
- assert.strictEqual($channelsSidebar.find('.o_mail_discuss_item').length, 20,
- "should show 20 channels in sidebar");
- assert.strictEqual(discuss.$('.o_discuss_sidebar_quick_search').length, 1,
- "should display a quick search");
+ var $sidebar = discuss.$('.o_mail_discuss_sidebar');
- discuss.$('.o_discuss_sidebar_quick_search input').val('channelA').trigger('input');
- $channelsSidebar = $sidebar.find('.o_mail_discuss_sidebar_channels');
- assert.strictEqual($channelsSidebar.find('.o_mail_discuss_item').length, 15,
- "should now show 15 channels in sidebar");
+ var $channelsSidebar = $sidebar.find('.o_mail_discuss_sidebar_channels');
+ assert.strictEqual($channelsSidebar.length, 1,
+ "should show channels in sidebar");
+ assert.strictEqual($channelsSidebar.find('.o_mail_discuss_item').length, 20,
+ "should show 20 channels in sidebar");
+ assert.strictEqual(discuss.$('.o_discuss_sidebar_quick_search').length, 1,
+ "should display a quick search");
- discuss.$('.o_discuss_sidebar_quick_search input').val('channelB').trigger('input');
+ discuss.$('.o_discuss_sidebar_quick_search input').val('channelA').trigger('input');
+ $channelsSidebar = $sidebar.find('.o_mail_discuss_sidebar_channels');
+ assert.strictEqual($channelsSidebar.find('.o_mail_discuss_item').length, 15,
+ "should now show 15 channels in sidebar");
- $channelsSidebar = $sidebar.find('.o_mail_discuss_sidebar_channels');
- assert.strictEqual($channelsSidebar.find('.o_mail_discuss_item').length, 5,
- "should now show 5 channels in sidebar");
+ discuss.$('.o_discuss_sidebar_quick_search input').val('channelB').trigger('input');
- discuss.$('.o_discuss_sidebar_quick_search input').val('channelB4').trigger('input');
+ $channelsSidebar = $sidebar.find('.o_mail_discuss_sidebar_channels');
+ assert.strictEqual($channelsSidebar.find('.o_mail_discuss_item').length, 5,
+ "should now show 5 channels in sidebar");
- $channelsSidebar = $sidebar.find('.o_mail_discuss_sidebar_channels');
- assert.strictEqual($channelsSidebar.find('.o_mail_discuss_item').length, 1,
- "should now show a single channel in sidebar");
- assert.strictEqual($channelsSidebar.find('.o_thread_name').text().replace(/\s/g, ''),
- '#ChannelB4',
- "should have searched the correct channel B4");
+ discuss.$('.o_discuss_sidebar_quick_search input').val('channelB4').trigger('input');
- discuss.destroy();
- done();
- });
+ $channelsSidebar = $sidebar.find('.o_mail_discuss_sidebar_channels');
+ assert.strictEqual($channelsSidebar.find('.o_mail_discuss_item').length, 1,
+ "should now show a single channel in sidebar");
+ assert.strictEqual($channelsSidebar.find('.o_thread_name').text().replace(/\s/g, ''),
+ '#ChannelB4',
+ "should have searched the correct channel B4");
+
+ discuss.destroy();
});
-QUnit.test('select emoji replaces cursor position', function (assert) {
+QUnit.test('select emoji replaces cursor position', async function (assert) {
assert.expect(5);
- var done = assert.async();
this.data.initMessaging = {
channel_slots: {
@@ -1351,55 +1282,51 @@ QUnit.test('select emoji replaces cursor position', function (assert) {
},
};
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
data: this.data,
services: this.services,
- })
- .then(function (discuss) {
- var $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- assert.strictEqual($general.length, 1,
- "should have the channel item with id 1");
- assert.hasAttrValue($general, 'title', 'general',
- "should have the title 'general'");
+ });
+ var $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ assert.strictEqual($general.length, 1,
+ "should have the channel item with id 1");
+ assert.hasAttrValue($general, 'title', 'general',
+ "should have the title 'general'");
- // click on general
- testUtils.dom.click($general);
+ // click on general
+ await testUtils.dom.click($general);
- // general uses basic composer, so this is the 1st composer
- // (2nd composer is hidden)
- var $composer = discuss.$('.o_composer_text_field').first();
+ // general uses basic composer, so this is the 1st composer
+ // (2nd composer is hidden)
+ var $composer = discuss.$('.o_composer_text_field').first();
- testUtils.fields.editInput($composer, 'abcdefgh');
+ await testUtils.fields.editInput($composer, 'abcdefgh');
- assert.strictEqual($composer.val(), "abcdefgh");
+ assert.strictEqual($composer.val(), "abcdefgh");
- // cursor position: ab|cd|efgh (selecting c and d)
- $composer[0].setSelectionRange(2, 4);
+ // cursor position: ab|cd|efgh (selecting c and d)
+ $composer[0].setSelectionRange(2, 4);
- testUtils.dom.click(discuss.$('.o_composer_button_emoji'));
- testUtils.dom.triggerMouseEvent(discuss.$('.o_mail_emoji[data-emoji=":)"]'), 'mousedown');
+ await testUtils.dom.click(discuss.$('.o_composer_button_emoji'));
+ await testUtils.dom.triggerMouseEvent(discuss.$('.o_mail_emoji[data-emoji=":)"]'), 'mousedown');
- assert.strictEqual($composer.val(), "ab :) efgh",
- "should have inserted emoji ");
+ assert.strictEqual($composer.val(), "ab :) efgh",
+ "should have inserted emoji ");
- testUtils.dom.click(discuss.$('.o_composer_button_emoji'));
- testUtils.dom.triggerMouseEvent(discuss.$('.o_mail_emoji[data-emoji=":)"]'), 'mousedown');
+ await testUtils.dom.click(discuss.$('.o_composer_button_emoji'));
+ await testUtils.dom.triggerMouseEvent(discuss.$('.o_mail_emoji[data-emoji=":)"]'), 'mousedown');
- assert.strictEqual($composer.val(), "ab :) :) efgh",
- "should have inserted emoji after previously inserted emoji");
+ assert.strictEqual($composer.val(), "ab :) :) efgh",
+ "should have inserted emoji after previously inserted emoji");
- discuss.destroy();
- done();
- });
+ discuss.destroy();
});
-QUnit.test('rename DM conversation', function (assert) {
+QUnit.test('rename DM conversation', async function (assert) {
assert.expect(11);
- var done = assert.async();
this.data.initMessaging = {
channel_slots: {
@@ -1416,7 +1343,7 @@ QUnit.test('rename DM conversation', function (assert) {
},
};
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -1428,41 +1355,38 @@ QUnit.test('rename DM conversation', function (assert) {
assert.step(args.method);
assert.strictEqual(args.args[0], 1);
assert.strictEqual(args.kwargs.name, "Demo");
- return $.when("Demo");
+ return Promise.resolve("Demo");
}
return this._super.apply(this, arguments);
},
- })
- .then(function (discuss) {
- var $dm = discuss.$('.o_mail_discuss_item[data-thread-id=1]');
- assert.isVisible($dm, "should display DM in the discuss sidebar");
- assert.strictEqual($dm.find('.o_thread_name').text().trim(), "Demo User");
-
- // The settings icon is only shown when hovering on sidebar item.
- // helpter dom.click needs the element to be visible, hence the
- // hack on display of this icon.
- discuss.$('.o_mail_channel_settings').css('display', 'block');
- testUtils.dom.click(discuss.$('.o_mail_channel_settings'));
-
- assert.isVisible($('.modal-dialog'));
- assert.strictEqual($('.modal-title').text(), "Rename conversation");
- assert.isVisible($('.o_mail_discuss_rename_channel_input'));
- assert.strictEqual($('.o_mail_discuss_rename_channel_input').val(), "Demo User");
-
- testUtils.fields.editInput($('.o_mail_discuss_rename_channel_input'), "Demo");
- testUtils.dom.click($('.o_mail_conversation_rename'));
- $dm = discuss.$('.o_mail_discuss_item[data-thread-id=1]');
- assert.verifySteps(['channel_set_custom_name']);
- assert.strictEqual($dm.find('.o_thread_name').text().trim(), "Demo");
-
- discuss.destroy();
- done();
});
+
+ var $dm = discuss.$('.o_mail_discuss_item[data-thread-id=1]');
+ assert.isVisible($dm, "should display DM in the discuss sidebar");
+ assert.strictEqual($dm.find('.o_thread_name').text().trim(), "Demo User");
+
+ // The settings icon is only shown when hovering on sidebar item.
+ // helpter dom.click needs the element to be visible, hence the
+ // hack on display of this icon.
+ discuss.$('.o_mail_channel_settings').css('display', 'block');
+ await testUtils.dom.click(discuss.$('.o_mail_channel_settings'));
+
+ assert.isVisible($('.modal-dialog'));
+ assert.strictEqual($('.modal-title').text(), "Rename conversation");
+ assert.isVisible($('.o_mail_discuss_rename_channel_input'));
+ assert.strictEqual($('.o_mail_discuss_rename_channel_input').val(), "Demo User");
+
+ await testUtils.fields.editInput($('.o_mail_discuss_rename_channel_input'), "Demo");
+ await testUtils.dom.click($('.o_mail_conversation_rename'));
+ $dm = discuss.$('.o_mail_discuss_item[data-thread-id=1]');
+ assert.verifySteps(['channel_set_custom_name']);
+ assert.strictEqual($dm.find('.o_thread_name').text().trim(), "Demo");
+
+ discuss.destroy();
});
-QUnit.test('custom-named DM conversation', function (assert) {
+QUnit.test('custom-named DM conversation', async function (assert) {
assert.expect(2);
- var done = assert.async();
this.data.initMessaging = {
channel_slots: {
@@ -1480,7 +1404,7 @@ QUnit.test('custom-named DM conversation', function (assert) {
},
};
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -1488,14 +1412,12 @@ QUnit.test('custom-named DM conversation', function (assert) {
services: this.services,
session: { partner_id: 3 },
})
- .then(function (discuss) {
- var $dm = discuss.$('.o_mail_discuss_item[data-thread-id=1]');
- assert.isVisible($dm, "should display DM in the discuss sidebar");
- assert.strictEqual($dm.find('.o_thread_name').text().trim(), "My Buddy");
- discuss.destroy();
- done();
- });
+ var $dm = discuss.$('.o_mail_discuss_item[data-thread-id=1]');
+ assert.isVisible($dm, "should display DM in the discuss sidebar");
+ assert.strictEqual($dm.find('.o_thread_name').text().trim(), "My Buddy");
+
+ discuss.destroy();
});
});
diff --git a/addons/mail/static/tests/discuss_typing_notification_tests.js b/addons/mail/static/tests/discuss_typing_notification_tests.js
index 2d1eb679c65..d77d32b9f1f 100644
--- a/addons/mail/static/tests/discuss_typing_notification_tests.js
+++ b/addons/mail/static/tests/discuss_typing_notification_tests.js
@@ -153,15 +153,14 @@ QUnit.module('Discuss (Typing Notifications)', {
}
});
-QUnit.test('notify is typing', function (assert) {
+QUnit.test('notify is typing', async function (assert) {
assert.expect(11);
- var done = assert.async();
// this is to track the step that we are testing in the `notify_typing`
// mocked RPC
var step = 1;
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -188,44 +187,42 @@ QUnit.test('notify is typing', function (assert) {
return this._super.apply(this, arguments);
},
session: { partner_id: this.myPartnerID },
- }).then(function (discuss) {
+ });
- var $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- assert.strictEqual($general.length, 1,
- "should have the channel item with id 1");
- assert.hasAttrValue($general, 'title', 'general',
- "should have the title 'general'");
+ var $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ assert.strictEqual($general.length, 1,
+ "should have the channel item with id 1");
+ assert.hasAttrValue($general, 'title', 'general',
+ "should have the title 'general'");
- // click on general
- testUtils.dom.click($general);
+ // click on general
+ await testUtils.dom.click($general);
- var $input = discuss.$('textarea.o_composer_text_field').first();
- assert.ok($input.length, "should display a composer input");
+ var $input = discuss.$('textarea.o_composer_text_field').first();
+ assert.ok($input.length, "should display a composer input");
- // STEP 1: current user is typing something
- step = 1;
- $input.focus();
- testUtils.fields.editInput($input, '1');
+ // STEP 1: current user is typing something
+ step = 1;
+ $input.focus();
+ testUtils.fields.editInput($input, '1');
- assert.verifySteps(['notify_typing']);
+ assert.verifySteps(['notify_typing']);
- // STEP 2: current user clears input
- step = 2;
- testUtils.fields.editInput($input, '');
+ // STEP 2: current user clears input
+ step = 2;
+ testUtils.fields.editInput($input, '');
- assert.verifySteps(['notify_typing', 'notify_typing']);
+ assert.verifySteps(['notify_typing']);
- discuss.destroy();
- done();
- });
+ discuss.destroy();
});
-QUnit.test('receive is typing notification', function (assert) {
+QUnit.test('receive is typing notification', async function (assert) {
assert.expect(10);
var self = this;
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -235,7 +232,7 @@ QUnit.test('receive is typing notification', function (assert) {
// when receiving an 'is typing' notification, fetch the list of
// members of this channel if we haven't done yet.
if (args.method === 'channel_fetch_listeners') {
- return $.when([
+ return Promise.resolve([
{ id: self.myPartnerID, name: self.myName },
{ id: 42, name: "Someone" },
]);
@@ -243,67 +240,68 @@ QUnit.test('receive is typing notification', function (assert) {
return this._super.apply(this, arguments);
},
session: { partner_id: this.myPartnerID },
- }).then(function (discuss) {
- var $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- assert.strictEqual($general.length, 1,
- "should have the channel item with id 1");
- assert.hasAttrValue($general, 'title', 'general',
- "should have the title 'general'");
-
- // pick 1st composer (basic), not 2nd composer (extended, hidden)
- var $composer = discuss.$('.o_thread_composer').first();
-
- // click on general
- testUtils.dom.click($general);
- assert.containsNone($general, '.o_mail_thread_typing_icon',
- "should no longer show someone is typing in sidebar of discuss");
- assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(), "",
- "should no longer show someone is typing on the composer of active thread");
-
- self.simulateIsTyping({
- channelID: 1,
- isTyping: true,
- partnerID: 42,
- widget: discuss,
- });
-
- $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- assert.containsOnce($general, '.o_mail_thread_typing_icon',
- "should have a thread typing icon next to general icon in the sidebar");
- assert.hasAttrValue($general.find('.o_mail_thread_typing_icon'), 'title',
- "Someone is typing...",
- "should show who is typing on hover on this thread typing icon");
- assert.containsOnce($composer, '.o_composer_thread_typing',
- "should show typing info on the composer of active thread");
- assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(),
- "Someone is typing...",
- "should show who is typing on the composer of active thread");
-
- self.simulateIsTyping({
- channelID: 1,
- isTyping: false,
- partnerID: 42,
- widget: discuss,
- });
-
- $general = discuss.$('.o_mail_discuss_sidebar')
+ });
+ var $general = discuss.$('.o_mail_discuss_sidebar')
.find('.o_mail_discuss_item[data-thread-id=1]');
- assert.containsNone($general, '.o_mail_thread_typing_icon',
- "should no longer show someone is typing in sidebar of discuss");
- assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(), "",
- "should no longer show someone is typing on the composer of active thread");
-
- discuss.destroy();
+ assert.strictEqual($general.length, 1,
+ "should have the channel item with id 1");
+ assert.hasAttrValue($general, 'title', 'general',
+ "should have the title 'general'");
+
+ // pick 1st composer (basic), not 2nd composer (extended, hidden)
+ var $composer = discuss.$('.o_thread_composer').first();
+
+ // click on general
+ await testUtils.dom.click($general);
+ assert.containsNone($general, '.o_mail_thread_typing_icon',
+ "should no longer show someone is typing in sidebar of discuss");
+ assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(), "",
+ "should no longer show someone is typing on the composer of active thread");
+
+ self.simulateIsTyping({
+ channelID: 1,
+ isTyping: true,
+ partnerID: 42,
+ widget: discuss,
});
+ await testUtils.nextMicrotaskTick();
+
+ $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ assert.containsOnce($general, '.o_mail_thread_typing_icon',
+ "should have a thread typing icon next to general icon in the sidebar");
+ assert.hasAttrValue($general.find('.o_mail_thread_typing_icon'), 'title',
+ "Someone is typing...",
+ "should show who is typing on hover on this thread typing icon");
+ assert.containsOnce($composer, '.o_composer_thread_typing',
+ "should show typing info on the composer of active thread");
+ assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(),
+ "Someone is typing...",
+ "should show who is typing on the composer of active thread");
+
+ self.simulateIsTyping({
+ channelID: 1,
+ isTyping: false,
+ partnerID: 42,
+ widget: discuss,
+ });
+ await testUtils.nextMicrotaskTick();
+
+ $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ assert.containsNone($general, '.o_mail_thread_typing_icon',
+ "should no longer show someone is typing in sidebar of discuss");
+ assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(), "",
+ "should no longer show someone is typing on the composer of active thread");
+
+ discuss.destroy();
});
-QUnit.test('receive message of someone that was typing something', function (assert) {
+QUnit.test('receive message of someone that was typing something', async function (assert) {
assert.expect(6);
var self = this;
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -313,7 +311,7 @@ QUnit.test('receive message of someone that was typing something', function (ass
// when receiving an 'is typing' notification, fetch the list of
// members of this channel if we haven't done yet.
if (args.method === 'channel_fetch_listeners') {
- return $.when([
+ return Promise.resolve([
{ id: self.myPartnerID, name: self.myName },
{ id: 42, name: "Someone" },
]);
@@ -321,62 +319,63 @@ QUnit.test('receive message of someone that was typing something', function (ass
return this._super.apply(this, arguments);
},
session: { partner_id: this.myPartnerID },
- }).then(function (discuss) {
- // click on general channel
- var $general = discuss.$('.o_mail_discuss_sidebar .o_mail_discuss_item[data-thread-id=1]');
- testUtils.dom.click($general);
-
- // pick 1st composer (basic), not 2nd composer (extended, hidden)
- var $composer = discuss.$('.o_thread_composer').first();
-
- self.simulateIsTyping({
- channelID: 1,
- isTyping: true,
- partnerID: 42,
- widget: discuss,
- });
-
- $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- assert.containsOnce($general, '.o_mail_thread_typing_icon',
- "should have a thread typing icon next to general icon in the sidebar");
- assert.hasAttrValue($general.find('.o_mail_thread_typing_icon'), 'title',
- "Someone is typing...",
- "should show who is typing on hover on this thread typing icon");
- assert.containsOnce($composer, '.o_composer_thread_typing',
- "should show typing info on the composer of active thread");
- assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(),
- "Someone is typing...",
- "should show who is typing on the composer of active thread");
-
- // Simulate receive message from the person typing something
- var messageData = {
- author_id: [42, 'Someone'],
- body: "<p>test</p>",
- channel_ids: [1],
- id: 101,
- model: 'mail.channel',
- res_id: 1,
- };
- var notification = [[false, 'mail.channel', 1], messageData];
- discuss.call('bus_service', 'trigger', 'notification', [notification]);
+ });
+ // click on general channel
+ var $general = discuss.$('.o_mail_discuss_sidebar .o_mail_discuss_item[data-thread-id=1]');
+ await testUtils.dom.click($general);
+
+ // pick 1st composer (basic), not 2nd composer (extended, hidden)
+ var $composer = discuss.$('.o_thread_composer').first();
+
+ self.simulateIsTyping({
+ channelID: 1,
+ isTyping: true,
+ partnerID: 42,
+ widget: discuss,
+ });
+ await testUtils.nextMicrotaskTick();
- $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- assert.containsNone($general, '.o_mail_thread_typing_icon',
- "should no longer show someone is typing in sidebar of discuss, after receiving message");
- assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(), "",
- "should no longer show someone is typing on the composer of active thread, after receiving message");
+ $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ assert.containsOnce($general, '.o_mail_thread_typing_icon',
+ "should have a thread typing icon next to general icon in the sidebar");
+ assert.hasAttrValue($general.find('.o_mail_thread_typing_icon'), 'title',
+ "Someone is typing...",
+ "should show who is typing on hover on this thread typing icon");
+ assert.containsOnce($composer, '.o_composer_thread_typing',
+ "should show typing info on the composer of active thread");
+ assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(),
+ "Someone is typing...",
+ "should show who is typing on the composer of active thread");
+
+ // Simulate receive message from the person typing something
+ var messageData = {
+ author_id: [42, 'Someone'],
+ body: "<p>test</p>",
+ channel_ids: [1],
+ id: 101,
+ model: 'mail.channel',
+ res_id: 1,
+ };
+ var notification = [[false, 'mail.channel', 1], messageData];
+ await discuss.call('bus_service', 'trigger', 'notification', [notification]);
+ await testUtils.nextTick();
+
+ $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ assert.containsNone($general, '.o_mail_thread_typing_icon',
+ "should no longer show someone is typing in sidebar of discuss, after receiving message");
+ assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(), "",
+ "should no longer show someone is typing on the composer of active thread, after receiving message");
- discuss.destroy();
- });
+ discuss.destroy();
});
-QUnit.test('do not display myself as typing', function (assert) {
+QUnit.test('do not display myself as typing', async function (assert) {
assert.expect(2);
var self = this;
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -386,40 +385,39 @@ QUnit.test('do not display myself as typing', function (assert) {
// when receiving an 'is typing' notification, fetch the list of
// members of this channel if we haven't done yet.
if (args.method === 'channel_fetch_listeners') {
- return $.when([
+ return Promise.resolve([
{ id: self.myPartnerID, name: self.myName },
]);
}
return this._super.apply(this, arguments);
},
session: { partner_id: this.myPartnerID },
- }).then(function (discuss) {
- // click on general channel
- var $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- testUtils.dom.click($general);
- // pick 1st composer (basic), not 2nd composer (extended, hidden)
- var $composer = discuss.$('.o_thread_composer').first();
-
- self.simulateIsTyping({
- channelID: 1,
- isTyping: true,
- partnerID: self.myPartnerID,
- widget: discuss,
- });
-
- $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- assert.containsNone($general, '.o_mail_thread_typing_icon',
- "should not show current user is typing in sidebar of discuss");
- assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(), "",
- "should not show current user is typing on the composer of active thread");
-
- discuss.destroy();
});
+ // click on general channel
+ var $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ await testUtils.dom.click($general);
+ // pick 1st composer (basic), not 2nd composer (extended, hidden)
+ var $composer = discuss.$('.o_thread_composer').first();
+
+ self.simulateIsTyping({
+ channelID: 1,
+ isTyping: true,
+ partnerID: self.myPartnerID,
+ widget: discuss,
+ });
+
+ $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ assert.containsNone($general, '.o_mail_thread_typing_icon',
+ "should not show current user is typing in sidebar of discuss");
+ assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(), "",
+ "should not show current user is typing on the composer of active thread");
+
+ discuss.destroy();
});
-QUnit.test('several users typing something at the same time', function (assert) {
+QUnit.test('several users typing something at the same time', async function (assert) {
// The order to display several typing partners name is not random:
// it shows at most 2 typing partners, which are the typing partners that
// have been typing something for the longest time.
@@ -428,7 +426,7 @@ QUnit.test('several users typing something at the same time', function (assert)
assert.expect(10);
var self = this;
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -438,7 +436,7 @@ QUnit.test('several users typing something at the same time', function (assert)
// when receiving an 'is typing' notification, fetch the list of
// members of this channel if we haven't done yet.
if (args.method === 'channel_fetch_listeners') {
- return $.when([
+ return Promise.resolve([
{ id: self.myPartnerID, name: self.myName },
{ id: 42, name: "Someone" },
{ id: 43, name: "Anonymous" },
@@ -448,98 +446,101 @@ QUnit.test('several users typing something at the same time', function (assert)
return this._super.apply(this, arguments);
},
session: { partner_id: this.myPartnerID },
- }).then(function (discuss) {
- // click on general channel
- var $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
-
- // click on general
- testUtils.dom.click($general);
-
- // pick 1st composer (basic), not 2nd composer (extended, hidden)
- var $composer = discuss.$('.o_thread_composer').first();
-
- self.simulateIsTyping({
- channelID: 1,
- isTyping: true,
- partnerID: 42,
- widget: discuss,
- });
-
- $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- assert.containsOnce($general, '.o_mail_thread_typing_icon',
- "should have a thread typing icon next to general icon in the sidebar");
- assert.hasAttrValue($general.find('.o_mail_thread_typing_icon'), 'title',
- "Someone is typing...",
- "should show someone is typing on hover on this thread typing icon");
- assert.containsOnce($composer, '.o_composer_thread_typing',
- "should show typing info on the composer of active thread");
- assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(),
- "Someone is typing...",
- "should show someone is typing on the composer of active thread");
-
- self.simulateIsTyping({
- channelID: 1,
- isTyping: true,
- partnerID: 43,
- widget: discuss,
- });
-
- $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- assert.hasAttrValue($general.find('.o_mail_thread_typing_icon'), 'title',
- "Someone and Anonymous are typing...",
- "should show someone and anonymous are simultaneously typing on hover on this thread typing icon");
- assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(),
- "Someone and Anonymous are typing...",
- "should show someone and anonymous are simultaneously typing on the composer of active thread");
-
- self.simulateIsTyping({
- channelID: 1,
- isTyping: true,
- partnerID: 44,
- widget: discuss,
- });
-
- $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- assert.hasAttrValue($general.find('.o_mail_thread_typing_icon'), 'title',
- "Someone, Anonymous and more are typing...",
- "should show 2 and more users are simultaneously typing on hover on this thread typing icon");
- assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(),
- "Someone, Anonymous and more are typing...",
- "should show 2 and more users are simultaneously typing on the composer of active thread");
-
- self.simulateIsTyping({
- channelID: 1,
- isTyping: false,
- partnerID: 42,
- widget: discuss,
- });
-
- $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- assert.hasAttrValue($general.find('.o_mail_thread_typing_icon'), 'title',
- "Anonymous and Shy Guy are typing...",
- "should no longer show than someone is typing on hover on this thread typing icon");
- assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(),
- "Anonymous and Shy Guy are typing...",
- "should no longer show than someone is typing on the composer of active thread");
-
- discuss.destroy();
});
+ // click on general channel
+ var $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+
+ // click on general
+ await testUtils.dom.click($general);
+
+ // pick 1st composer (basic), not 2nd composer (extended, hidden)
+ var $composer = discuss.$('.o_thread_composer').first();
+
+ self.simulateIsTyping({
+ channelID: 1,
+ isTyping: true,
+ partnerID: 42,
+ widget: discuss,
+ });
+ await testUtils.nextMicrotaskTick();
+
+ $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ assert.containsOnce($general, '.o_mail_thread_typing_icon',
+ "should have a thread typing icon next to general icon in the sidebar");
+ assert.hasAttrValue($general.find('.o_mail_thread_typing_icon'), 'title',
+ "Someone is typing...",
+ "should show someone is typing on hover on this thread typing icon");
+ assert.containsOnce($composer, '.o_composer_thread_typing',
+ "should show typing info on the composer of active thread");
+ assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(),
+ "Someone is typing...",
+ "should show someone is typing on the composer of active thread");
+
+ self.simulateIsTyping({
+ channelID: 1,
+ isTyping: true,
+ partnerID: 43,
+ widget: discuss,
+ });
+ await testUtils.nextMicrotaskTick();
+
+ $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ assert.hasAttrValue($general.find('.o_mail_thread_typing_icon'), 'title',
+ "Someone and Anonymous are typing...",
+ "should show someone and anonymous are simultaneously typing on hover on this thread typing icon");
+ assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(),
+ "Someone and Anonymous are typing...",
+ "should show someone and anonymous are simultaneously typing on the composer of active thread");
+
+ self.simulateIsTyping({
+ channelID: 1,
+ isTyping: true,
+ partnerID: 44,
+ widget: discuss,
+ });
+ await testUtils.nextMicrotaskTick();
+
+ $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ assert.hasAttrValue($general.find('.o_mail_thread_typing_icon'), 'title',
+ "Someone, Anonymous and more are typing...",
+ "should show 2 and more users are simultaneously typing on hover on this thread typing icon");
+ assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(),
+ "Someone, Anonymous and more are typing...",
+ "should show 2 and more users are simultaneously typing on the composer of active thread");
+
+ self.simulateIsTyping({
+ channelID: 1,
+ isTyping: false,
+ partnerID: 42,
+ widget: discuss,
+ });
+ await testUtils.nextMicrotaskTick();
+
+ $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ assert.hasAttrValue($general.find('.o_mail_thread_typing_icon'), 'title',
+ "Anonymous and Shy Guy are typing...",
+ "should no longer show than someone is typing on hover on this thread typing icon");
+ assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(),
+ "Anonymous and Shy Guy are typing...",
+ "should no longer show than someone is typing on the composer of active thread");
+
+ discuss.destroy();
});
-QUnit.test('long typing partner A and in-between short typing partner B', function (assert) {
+QUnit.test('long typing partner A and in-between short typing partner B', async function (assert) {
// Let's suppose that A is typing a very long message. If B types a short
// and sends it, it should display that B is typing, remove B from display
// when receiving the message, but still keep A in the typing notification.
assert.expect(8);
var self = this;
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -549,7 +550,7 @@ QUnit.test('long typing partner A and in-between short typing partner B', functi
// when receiving an 'is typing' notification, fetch the list of
// members of this channel if we haven't done yet.
if (args.method === 'channel_fetch_listeners') {
- return $.when([
+ return Promise.resolve([
{ id: self.myPartnerID, name: self.myName },
{ id: 42, name: "A" },
{ id: 43, name: "B" },
@@ -558,76 +559,78 @@ QUnit.test('long typing partner A and in-between short typing partner B', functi
return this._super.apply(this, arguments);
},
session: { partner_id: this.myPartnerID },
- }).then(function (discuss) {
- // click on general channel
- var $general = discuss.$('.o_mail_discuss_sidebar .o_mail_discuss_item[data-thread-id=1]');
- testUtils.dom.click($general);
- // pick 1st composer (basic), not 2nd composer (extended, hidden)
- var $composer = discuss.$('.o_thread_composer').first();
-
- self.simulateIsTyping({
- channelID: 1,
- isTyping: true,
- partnerID: 42,
- widget: discuss,
- });
-
- $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- assert.containsOnce($general, '.o_mail_thread_typing_icon',
- "should have a thread typing icon next to general icon in the sidebar");
- assert.hasAttrValue($general.find('.o_mail_thread_typing_icon'), 'title',
- "A is typing...",
- "should show A is typing on hover on this thread typing icon");
- assert.containsOnce($composer, '.o_composer_thread_typing',
- "should show typing info on the composer of active thread");
- assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(),
- "A is typing...",
- "should show A is typing on the composer of active thread");
-
- self.simulateIsTyping({
- channelID: 1,
- isTyping: true,
- partnerID: 43,
- widget: discuss,
- });
-
- // B comes after A in the display, because A is oldest typing partner.
- $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- assert.hasAttrValue($general.find('.o_mail_thread_typing_icon'), 'title',
- "A and B are typing...",
- "should show A and B are typing on hover on this thread typing icon");
- assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(),
- "A and B are typing...",
- "should show A and B are typing on the composer of active thread");
-
- // Simulate receive message from B
- var messageData = {
- author_id: [43, 'Someone'],
- body: "<p>test</p>",
- channel_ids: [1],
- id: 101,
- model: 'mail.channel',
- res_id: 1,
- };
- var notification = [[false, 'mail.channel', 1], messageData];
- discuss.call('bus_service', 'trigger', 'notification', [notification]);
-
- $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- assert.hasAttrValue($general.find('.o_mail_thread_typing_icon'), 'title',
- "A is typing...",
- "should show A is still typing on hover on this thread typing icon");
- assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(),
- "A is typing...",
- "should show A is still typing on the composer of active thread");
-
- discuss.destroy();
});
+ // click on general channel
+ var $general = discuss.$('.o_mail_discuss_sidebar .o_mail_discuss_item[data-thread-id=1]');
+ await testUtils.dom.click($general);
+ // pick 1st composer (basic), not 2nd composer (extended, hidden)
+ var $composer = discuss.$('.o_thread_composer').first();
+
+ self.simulateIsTyping({
+ channelID: 1,
+ isTyping: true,
+ partnerID: 42,
+ widget: discuss,
+ });
+ await testUtils.nextMicrotaskTick();
+
+ $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ assert.containsOnce($general, '.o_mail_thread_typing_icon',
+ "should have a thread typing icon next to general icon in the sidebar");
+ assert.hasAttrValue($general.find('.o_mail_thread_typing_icon'), 'title',
+ "A is typing...",
+ "should show A is typing on hover on this thread typing icon");
+ assert.containsOnce($composer, '.o_composer_thread_typing',
+ "should show typing info on the composer of active thread");
+ assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(),
+ "A is typing...",
+ "should show A is typing on the composer of active thread");
+
+ self.simulateIsTyping({
+ channelID: 1,
+ isTyping: true,
+ partnerID: 43,
+ widget: discuss,
+ });
+ await testUtils.nextMicrotaskTick();
+
+ // B comes after A in the display, because A is oldest typing partner.
+ $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ assert.hasAttrValue($general.find('.o_mail_thread_typing_icon'), 'title',
+ "A and B are typing...",
+ "should show A and B are typing on hover on this thread typing icon");
+ assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(),
+ "A and B are typing...",
+ "should show A and B are typing on the composer of active thread");
+
+ // Simulate receive message from B
+ var messageData = {
+ author_id: [43, 'Someone'],
+ body: "<p>test</p>",
+ channel_ids: [1],
+ id: 101,
+ model: 'mail.channel',
+ res_id: 1,
+ };
+ var notification = [[false, 'mail.channel', 1], messageData];
+ await discuss.call('bus_service', 'trigger', 'notification', [notification]);
+ await testUtils.nextTick();
+
+ $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ assert.hasAttrValue($general.find('.o_mail_thread_typing_icon'), 'title',
+ "A is typing...",
+ "should show A is still typing on hover on this thread typing icon");
+ assert.strictEqual($composer.find('.o_composer_thread_typing').text().trim(),
+ "A is typing...",
+ "should show A is still typing on the composer of active thread");
+
+ discuss.destroy();
});
-QUnit.test('receive is typing notification from unselected thread', function (assert) {
+QUnit.test('receive is typing notification from unselected thread', async function (assert) {
assert.expect(7);
this.data.initMessaging.channel_slots.channel_channel.push({
@@ -637,7 +640,7 @@ QUnit.test('receive is typing notification from unselected thread', function (as
});
var self = this;
- createDiscuss({
+ var discuss = await createDiscuss({
id: 1,
context: {},
params: {},
@@ -647,7 +650,7 @@ QUnit.test('receive is typing notification from unselected thread', function (as
// when receiving an 'is typing' notification, fetch the list of
// members of this channel if we haven't done yet.
if (args.method === 'channel_fetch_listeners') {
- return $.when([
+ return Promise.resolve([
{ id: self.myPartnerID, name: self.myName },
{ id: 42, name: "Someone" },
]);
@@ -655,44 +658,44 @@ QUnit.test('receive is typing notification from unselected thread', function (as
return this._super.apply(this, arguments);
},
session: { partner_id: this.myPartnerID },
- }).then(function (discuss) {
- var $general = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=1]');
- var $other = discuss.$('.o_mail_discuss_sidebar')
- .find('.o_mail_discuss_item[data-thread-id=2]');
- assert.strictEqual($general.length, 1,
- "should have the channel item with id 1");
- assert.hasAttrValue($general, 'title', 'general',
- "should have the title 'general'");
- assert.strictEqual($other.length, 1,
- "should have the channel item with id 2");
- assert.hasAttrValue($other, 'title', 'other',
- "should have the title 'other'");
-
- // click on general
- testUtils.dom.click($general);
-
- assert.containsNone($general, '.o_mail_thread_typing_icon',
- "should no longer show someone is typing in sidebar of discuss");
-
- self.simulateIsTyping({
- channelID: 2,
- isTyping: true,
- partnerID: 42,
- widget: discuss,
- });
-
- $general = discuss.$('.o_mail_discuss_sidebar')
+ });
+ var $general = discuss.$('.o_mail_discuss_sidebar')
.find('.o_mail_discuss_item[data-thread-id=1]');
- $other = discuss.$('.o_mail_discuss_sidebar')
+ var $other = discuss.$('.o_mail_discuss_sidebar')
.find('.o_mail_discuss_item[data-thread-id=2]');
- assert.containsNone($general, '.o_mail_thread_typing_icon',
- "should not have a thread typing icon next to general icon in the sidebar");
- assert.containsOnce($other, '.o_mail_thread_typing_icon',
- "should have a thread typing icon next to other icon in the sidebar");
-
- discuss.destroy();
+ assert.strictEqual($general.length, 1,
+ "should have the channel item with id 1");
+ assert.hasAttrValue($general, 'title', 'general',
+ "should have the title 'general'");
+ assert.strictEqual($other.length, 1,
+ "should have the channel item with id 2");
+ assert.hasAttrValue($other, 'title', 'other',
+ "should have the title 'other'");
+
+ // click on general
+ await testUtils.dom.click($general);
+
+ assert.containsNone($general, '.o_mail_thread_typing_icon',
+ "should no longer show someone is typing in sidebar of discuss");
+
+ self.simulateIsTyping({
+ channelID: 2,
+ isTyping: true,
+ partnerID: 42,
+ widget: discuss,
});
+ await testUtils.nextMicrotaskTick();
+
+ $general = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=1]');
+ $other = discuss.$('.o_mail_discuss_sidebar')
+ .find('.o_mail_discuss_item[data-thread-id=2]');
+ assert.containsNone($general, '.o_mail_thread_typing_icon',
+ "should not have a thread typing icon next to general icon in the sidebar");
+ assert.containsOnce($other, '.o_mail_thread_typing_icon',
+ "should have a thread typing icon next to other icon in the sidebar");
+
+ discuss.destroy();
});
});
diff --git a/addons/mail/static/tests/document_thread_window_tests.js b/addons/mail/static/tests/document_thread_window_tests.js
index 93095362306..51daf3a23b1 100644
--- a/addons/mail/static/tests/document_thread_window_tests.js
+++ b/addons/mail/static/tests/document_thread_window_tests.js
@@ -87,7 +87,7 @@ QUnit.module('Document Thread', {
},
});
-QUnit.test('open a document thread in a thread window', function (assert) {
+QUnit.test('open a document thread in a thread window', async function (assert) {
assert.expect(6);
var messagingMenu = new MessagingMenu();
@@ -107,13 +107,13 @@ QUnit.test('open a document thread in a thread window', function (assert) {
return this._super.apply(this, arguments);
},
});
- messagingMenu.appendTo($('#qunit-fixture'));
+ await messagingMenu.appendTo($('#qunit-fixture'));
// toggle the messaging menu and open the documentThread
- testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.containsOnce(messagingMenu, '.o_mail_preview',
"should display one preview");
- testUtils.dom.click(messagingMenu.$('.o_mail_preview'));
+ await testUtils.dom.click(messagingMenu.$('.o_mail_preview'));
assert.strictEqual($('.o_thread_window').length, 1,
"should have open the DocumentThread in a thread window");
@@ -125,7 +125,7 @@ QUnit.test('open a document thread in a thread window', function (assert) {
messagingMenu.destroy();
});
-QUnit.test('expand a document thread window', function (assert) {
+QUnit.test('expand a document thread window', async function (assert) {
assert.expect(4);
var messagingMenu = new MessagingMenu();
@@ -144,13 +144,13 @@ QUnit.test('expand a document thread window', function (assert) {
},
},
});
- messagingMenu.appendTo($('#qunit-fixture'));
+ await messagingMenu.appendTo($('#qunit-fixture'));
// toggle the messaging menu and open the documentThread
- testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.containsOnce(messagingMenu, '.o_mail_preview',
"should display one preview");
- testUtils.dom.click(messagingMenu.$('.o_mail_preview'));
+ await testUtils.dom.click(messagingMenu.$('.o_mail_preview'));
assert.strictEqual($('.o_thread_window').length, 1,
"should have open the DocumentThread in a thread window");
@@ -158,12 +158,12 @@ QUnit.test('expand a document thread window', function (assert) {
'Open document', "button should have correct title");
// click to expand
- testUtils.dom.click($('.o_thread_window .o_thread_window_expand'));
+ await testUtils.dom.click($('.o_thread_window .o_thread_window_expand'));
messagingMenu.destroy();
});
-QUnit.test('post messages in a document thread window', function (assert) {
+QUnit.test('post messages in a document thread window', async function (assert) {
assert.expect(8);
var newMessageBody = 'Some message';
@@ -193,7 +193,7 @@ QUnit.test('post messages in a document thread window', function (assert) {
// add the message to the fake DB
this.data['mail.message'].records.push(newMessage);
this.data['some.res.model'].records[0].message_ids.push(6783);
- return $.when(6783);
+ return Promise.resolve(6783);
}
return this._super.apply(this, arguments);
},
@@ -205,73 +205,74 @@ QUnit.test('post messages in a document thread window', function (assert) {
"should write sent message in local storage, to share info with other tabs");
}
}, true);
- messagingMenu.appendTo($('#qunit-fixture'));
+ await messagingMenu.appendTo($('#qunit-fixture'));
// toggle the messaging menu and open the documentThread
- testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.containsOnce(messagingMenu, '.o_mail_preview',
"should display one preview");
- testUtils.dom.click(messagingMenu.$('.o_mail_preview'));
+ await testUtils.dom.click(messagingMenu.$('.o_mail_preview'));
assert.strictEqual($('.o_thread_window').length, 1,
"should have open the DocumentThread in a thread window");
assert.strictEqual($('.o_thread_window .o_thread_message').length, 2,
"should display 2 messages in the thread window");
// post a message
- $('.o_thread_window .o_composer_text_field')
- .val(newMessageBody)
- .trigger($.Event('keydown', {which: $.ui.keyCode.ENTER}));
-
+ await testUtils.fields.editAndTrigger($('.o_thread_window .o_composer_text_field'), newMessageBody,
+ [$.Event('keydown', {which: $.ui.keyCode.ENTER})]);
assert.strictEqual($('.o_thread_window .o_thread_message').length, 3,
"should display 3 messages in the thread window");
messagingMenu.destroy();
});
-QUnit.test('open, fold, unfold and close a document thread window', function (assert) {
+QUnit.test('open, fold, unfold and close a document thread window', async function (assert) {
assert.expect(8);
-
var messagingMenu = new MessagingMenu();
testUtils.mock.addMockEnvironment(messagingMenu, {
services: this.services,
data: this.data,
session: this.session,
});
+ await testUtils.nextTick();
testUtils.mock.intercept(messagingMenu, 'call_service', function (ev) {
if (ev.data.service === 'local_storage' && ev.data.method === 'setItem') {
- assert.step(ev.data.args);
+ assert.step(JSON.stringify(ev.data.args));
}
}, true);
- messagingMenu.appendTo($('#qunit-fixture'));
+ await messagingMenu.appendTo($('#qunit-fixture'));
// toggle the messaging menu and open the documentThread
- testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.containsOnce(messagingMenu, '.o_mail_preview',
"should display one preview");
- testUtils.dom.click(messagingMenu.$('.o_mail_preview'));
+ await testUtils.dom.click(messagingMenu.$('.o_mail_preview'));
assert.strictEqual($('.o_thread_window').length, 1,
"should have open the DocumentThread in a thread window");
assert.strictEqual($('.o_thread_window .o_thread_message').length, 2,
"should display 2 messages in the thread window");
// fold and unfold thread window
- testUtils.dom.click($('.o_thread_window .o_thread_window_title'));
- testUtils.dom.click($('.o_thread_window .o_thread_window_title'));
+ await testUtils.dom.click($('.o_thread_window .o_thread_window_title'));
+ await testUtils.nextTick();
+ await testUtils.dom.click($('.o_thread_window .o_thread_window_title'));
+ await testUtils.nextTick();
// close thread window
- testUtils.dom.click($('.o_thread_window .o_thread_window_close'));
+ await testUtils.dom.click($('.o_thread_window .o_thread_window_close'));
+ await testUtils.nextTick();
assert.verifySteps([
- ['mail.document_threads_state', {"some.res.model_1": {"name": "Some Record", "windowState": "open"}}],
- ['mail.document_threads_state', {"some.res.model_1": {"name": "Some Record", "windowState": "folded"}}],
- ['mail.document_threads_state', {"some.res.model_1": {"name": "Some Record", "windowState": "open"}}],
- ['mail.document_threads_state', {"some.res.model_1": {"name": "Some Record", "windowState": "closed"}}],
+ '["mail.document_threads_state",{"some.res.model_1":{"name":"Some Record","windowState":"open"}}]',
+ '["mail.document_threads_state",{"some.res.model_1":{"name":"Some Record","windowState":"folded"}}]',
+ '["mail.document_threads_state",{"some.res.model_1":{"name":"Some Record","windowState":"open"}}]',
+ '["mail.document_threads_state",{"some.res.model_1":{"name":"Some Record","windowState":"closed"}}]',
]);
messagingMenu.destroy();
});
-QUnit.test('do not open thread window on fetch message failure', function (assert) {
+QUnit.test('do not open thread window on fetch message failure', async function (assert) {
// this may happen when the user receives a notification from a document
// that he does not have access rights at the moment.
assert.expect(4);
@@ -284,17 +285,17 @@ QUnit.test('do not open thread window on fetch message failure', function (asser
mockRPC: function (route, args) {
if (args.method === 'read' && args.model === 'some.res.model' && args.args[0][0] === 1) {
assert.step('some.res.model/1/read');
- return $.Deferred().reject(); // simulate failure
+ return Promise.reject(); // simulate failure
}
return this._super.apply(this, arguments);
},
});
- messagingMenu.appendTo($('#qunit-fixture'));
+ await messagingMenu.appendTo($('#qunit-fixture'));
- testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.containsOnce(messagingMenu, '.o_mail_preview');
- testUtils.dom.click(messagingMenu.$('.o_mail_preview'));
+ await testUtils.dom.click(messagingMenu.$('.o_mail_preview'));
assert.verifySteps(['some.res.model/1/read']);
assert.strictEqual($('.o_thread_window').length, 0,
"should not have open the DocumentThread in a thread window on fetch messages failure");
diff --git a/addons/mail/static/tests/document_viewer_tests.js b/addons/mail/static/tests/document_viewer_tests.js
index 87fa2dbed94..5d3dcf7069f 100644
--- a/addons/mail/static/tests/document_viewer_tests.js
+++ b/addons/mail/static/tests/document_viewer_tests.js
@@ -20,16 +20,16 @@ var createViewer = function (params) {
var mockRPC = function (route) {
if (route === '/web/static/lib/pdfjs/web/viewer.html?file=/web/content/1?model%3Dir.attachment') {
- return $.when();
+ return Promise.resolve();
}
if (route === 'https://www.youtube.com/embed/FYqW0Gdwbzk') {
- return $.when();
+ return Promise.resolve();
}
if (route === '/web/content/4?model%3Dir.attachment') {
- return $.when();
+ return Promise.resolve();
}
if (route === '/web/image/6?unique=1&signature=999&model=ir.attachment') {
- return $.when();
+ return Promise.resolve();
}
};
testUtils.mock.addMockEnvironment(parent, {
@@ -51,14 +51,15 @@ var createViewer = function (params) {
$target = $('body');
$target.addClass('debug');
}
- viewer.appendTo($target);
// actually destroy the parent when the viewer is destroyed
viewer.destroy = function () {
delete viewer.destroy;
parent.destroy();
};
- return viewer;
+ return viewer.appendTo($target).then(function() {
+ return viewer;
+ });
};
QUnit.module('DocumentViewer', {
@@ -74,10 +75,10 @@ QUnit.module('DocumentViewer', {
},
}, function () {
- QUnit.test('basic rendering', function (assert) {
+ QUnit.test('basic rendering', async function (assert) {
assert.expect(7);
- var viewer = createViewer({
+ var viewer = await createViewer({
attachmentID: 1,
attachments: this.attachments,
});
@@ -100,11 +101,11 @@ QUnit.module('DocumentViewer', {
viewer.destroy();
});
- QUnit.test('Document Viewer Youtube', function (assert) {
+ QUnit.test('Document Viewer Youtube', async function (assert) {
assert.expect(3);
var youtubeURL = 'https://www.youtube.com/embed/FYqW0Gdwbzk';
- var viewer = createViewer({
+ var viewer = await createViewer({
attachmentID: 2,
attachments: this.attachments,
mockRPC: function (route) {
@@ -123,10 +124,10 @@ QUnit.module('DocumentViewer', {
viewer.destroy();
});
- QUnit.test('Document Viewer html/(txt)', function (assert) {
+ QUnit.test('Document Viewer html/(txt)', async function (assert) {
assert.expect(2);
- var viewer = createViewer({
+ var viewer = await createViewer({
attachmentID: 4,
attachments: this.attachments,
});
@@ -139,10 +140,10 @@ QUnit.module('DocumentViewer', {
viewer.destroy();
});
- QUnit.test('Document Viewer mp4', function (assert) {
+ QUnit.test('Document Viewer mp4', async function (assert) {
assert.expect(2);
- var viewer = createViewer({
+ var viewer = await createViewer({
attachmentID: 5,
attachments: this.attachments,
});
@@ -155,10 +156,10 @@ QUnit.module('DocumentViewer', {
viewer.destroy();
});
- QUnit.test('Document Viewer jpg', function (assert) {
+ QUnit.test('Document Viewer jpg', async function (assert) {
assert.expect(2);
- var viewer = createViewer({
+ var viewer = await createViewer({
attachmentID: 6,
attachments: this.attachments,
});
@@ -171,10 +172,10 @@ QUnit.module('DocumentViewer', {
viewer.destroy();
});
- QUnit.test('is closable by button', function (assert) {
+ QUnit.test('is closable by button', async function (assert) {
assert.expect(3);
- var viewer = createViewer({
+ var viewer = await createViewer({
attachmentID: 6,
attachments: this.attachments,
});
@@ -184,15 +185,15 @@ QUnit.module('DocumentViewer', {
assert.containsOnce(viewer, '.o_close_btn',
"should have a close button");
- testUtils.dom.click(viewer.$('.o_close_btn'));
+ await testUtils.dom.click(viewer.$('.o_close_btn'));
assert.ok(viewer.isDestroyed(), 'viewer should be destroyed');
});
- QUnit.test('is closable by clicking on the wrapper', function (assert) {
+ QUnit.test('is closable by clicking on the wrapper', async function (assert) {
assert.expect(3);
- var viewer = createViewer({
+ var viewer = await createViewer({
attachmentID: 6,
attachments: this.attachments,
});
@@ -202,7 +203,7 @@ QUnit.module('DocumentViewer', {
assert.containsOnce(viewer, '.o_viewer_img_wrapper',
"should have a wrapper");
- testUtils.dom.click(viewer.$('.o_viewer_img_wrapper'));
+ await testUtils.dom.click(viewer.$('.o_viewer_img_wrapper'));
assert.ok(viewer.isDestroyed(), 'viewer should be destroyed');
});
diff --git a/addons/mail/static/tests/helpers/mock_server.js b/addons/mail/static/tests/helpers/mock_server.js
index 54ceae92ce3..32203db5dfb 100644
--- a/addons/mail/static/tests/helpers/mock_server.js
+++ b/addons/mail/static/tests/helpers/mock_server.js
@@ -183,29 +183,29 @@ MockServer.include({
_performRpc: function (route, args) {
// routes
if (route === '/mail/init_messaging') {
- return $.when(this._mockInitMessaging(args));
+ return Promise.resolve(this._mockInitMessaging(args));
}
// methods
if (args.method === 'channel_fetch_listeners') {
- return $.when([]);
+ return Promise.resolve([]);
}
if (args.method === 'channel_fetch_preview') {
- return $.when(this._mockChannelFetchPreview(args));
+ return Promise.resolve(this._mockChannelFetchPreview(args));
}
if (args.method === 'channel_minimize') {
- return $.when();
+ return Promise.resolve();
}
if (args.method === 'channel_seen') {
- return $.when();
+ return Promise.resolve();
}
if (args.method === 'channel_fetched') {
- return $.when();
+ return Promise.resolve();
}
if (args.method === 'message_fetch') {
- return $.when(this._mockMessageFetch(args));
+ return Promise.resolve(this._mockMessageFetch(args));
}
if (args.method === 'message_format') {
- return $.when(this._mockMessageFormat(args));
+ return Promise.resolve(this._mockMessageFormat(args));
}
if (args.method === 'activity_format') {
var res = this._mockRead(args.model, args.args, args.kwargs);
@@ -217,19 +217,19 @@ MockServer.include({
}
return record;
});
- return $.when(res);
+ return Promise.resolve(res);
}
if (args.method === 'set_message_done') {
- return $.when(this._mockSetMessageDone(args));
+ return Promise.resolve(this._mockSetMessageDone(args));
}
if (args.method === 'moderate') {
- return $.when(this._mockModerate(args));
+ return Promise.resolve(this._mockModerate(args));
}
if (args.method === 'notify_typing') {
- return $.when();
+ return Promise.resolve();
}
if (args.method === 'set_message_done') {
- return $.when();
+ return Promise.resolve();
}
return this._super(route, args);
},
diff --git a/addons/mail/static/tests/helpers/test_utils.js b/addons/mail/static/tests/helpers/test_utils.js
index 063e3a9eb03..af86d3c2e45 100644
--- a/addons/mail/static/tests/helpers/test_utils.js
+++ b/addons/mail/static/tests/helpers/test_utils.js
@@ -26,9 +26,9 @@ var Widget = require('web.Widget');
* This is async due to mail_manager/mail_service that needs to be ready.
*
* @param {Object} params
- * @return {$.Promise} resolved with the discuss widget
+ * @return {Promise} resolved with the discuss widget
*/
-function createDiscuss(params) {
+async function createDiscuss(params) {
var Parent = Widget.extend({
do_push_state: function () {},
});
@@ -49,7 +49,7 @@ function createDiscuss(params) {
parent.destroy();
};
- return discuss.appendTo($(selector)).then(function () {
+ return discuss.appendTo($(selector)).then(function () {
return discuss;
});
}
diff --git a/addons/mail/static/tests/mail_status_manager_tests.js b/addons/mail/static/tests/mail_status_manager_tests.js
index a1ae329c9dc..be769e8d0b0 100644
--- a/addons/mail/static/tests/mail_status_manager_tests.js
+++ b/addons/mail/static/tests/mail_status_manager_tests.js
@@ -38,7 +38,7 @@ QUnit.test('simple set im_status', function (assert) {
parent.destroy();
});
-QUnit.test('multi get_im_status', function (assert) {
+QUnit.test('multi get_im_status', async function (assert) {
assert.expect(9);
var readCount = 0;
var parent = testUtils.createParent({
@@ -52,7 +52,7 @@ QUnit.test('multi get_im_status', function (assert) {
assert.deepEqual(args.args[0], [2,3]);
assert.deepEqual(args.args[1], ['id', 'im_status']);
readCount++;
- return $.when([
+ return Promise.resolve([
{id: 2, im_status: 'away'},
{id: 3, im_status: 'im_partner'}
]);
@@ -64,22 +64,27 @@ QUnit.test('multi get_im_status', function (assert) {
id: 1,
im_status: 'online',
}]);
+ await testUtils.nextTick();
assert.strictEqual(parent.call('mail_service', 'getImStatus', { partnerID: 1 }), 'online');
assert.strictEqual(parent.call('mail_service', 'getImStatus', { partnerID: 2 }), undefined);
assert.strictEqual(parent.call('mail_service', 'getImStatus', { partnerID: 3 }), undefined);
this.timeoutMock.runPendingTimeouts();
+ await testUtils.nextTick();
+
assert.strictEqual(parent.call('mail_service', 'getImStatus', { partnerID: 1 }), 'online');
assert.strictEqual(parent.call('mail_service', 'getImStatus', { partnerID: 2 }), 'away');
assert.strictEqual(parent.call('mail_service', 'getImStatus', { partnerID: 3 }), 'im_partner');
this.timeoutMock.runPendingTimeouts();
+ await testUtils.nextTick();
+
assert.strictEqual(readCount, 1, 'Only one read on partner should have been performed');
parent.destroy();
});
-QUnit.test('update loop', function (assert) {
+QUnit.test('update loop', async function (assert) {
assert.expect(12);
var readCount = 0;
var parent = testUtils.createParent({
@@ -92,7 +97,7 @@ QUnit.test('update loop', function (assert) {
assert.deepEqual(args.args[0], [1, 2]);
assert.deepEqual(args.args[1], ['id', 'im_status']);
readCount++;
- return $.when([
+ return Promise.resolve([
{"id": 1, "im_status": "online"},
{"id": 2, "im_status": "away"}
]);
@@ -106,11 +111,14 @@ QUnit.test('update loop', function (assert) {
{ id: 2, im_status: 'offline' },
{ id: 3, im_status: 'im_partner' }, //shouldn't be updated !!!!
]);
+ await testUtils.nextTick();
//_updateImStatusLoop should be running at one second per iteration, lets make a minute pass.
assert.strictEqual(readCount, 0);
this.timeoutMock.addTime(50*1000);
+ await testUtils.nextTick();
assert.strictEqual(readCount, 0);
this.timeoutMock.addTime(1000);
+ await testUtils.nextTick();
assert.strictEqual(readCount, 1, 'one call should have been made after 50 seconds' );
assert.strictEqual(parent.call('mail_service', 'getImStatus', { partnerID: 1 }), 'online');
assert.strictEqual(parent.call('mail_service', 'getImStatus', { partnerID: 2 }), 'away');
@@ -118,21 +126,27 @@ QUnit.test('update loop', function (assert) {
//simulate change of focus
//original listener: $(window).on("blur", this._onWindowFocusChange.bind(this, false); + unload, ...
parent.call('mail_service', '_onWindowFocusChange', false); // remove focus from tab
+ await testUtils.nextTick();
this.timeoutMock.addTime(5*60*1000); // x minutes without focus, no rpc should be done during this time
+ await testUtils.nextTick();
assert.strictEqual(readCount, 1, 'No more call should have been performed');
//simulate change of focus
//original listener: $(window).on("focus", this._onWindowFocusChange.bind(this, true);
parent.call('mail_service', '_onWindowFocusChange', true); // give focus to tab
+ await testUtils.nextTick();
var nextUpdateDelay = this.timeoutMock.getNextTimeoutDelay();
+ await testUtils.nextTick();
assert.strictEqual(nextUpdateDelay, 1000, "next update should be done in maximum one second");
this.timeoutMock.addTime(nextUpdateDelay); // one second should be enough
+ await testUtils.nextTick();
assert.strictEqual(readCount, 2, 'One more call should have been done once tab focused');
this.timeoutMock.runPendingTimeouts();
+ await testUtils.nextTick();
parent.destroy();
});
-QUnit.test('update status', function (assert) {
+QUnit.test('update status', async function (assert) {
// the current solution to look for updatable im_status in dom is not perfect, but waiting for
// ability to include widgets in views, this is the most simple solution
assert.expect(2);
@@ -159,7 +173,7 @@ QUnit.test('update status', function (assert) {
throw new Error(_.str.sprintf('No rpc call should be performed: %s, %s \n %s', args.model, args.method, route));
},
});
- statusWidget.appendTo($('#qunit-fixture'));
+ await statusWidget.appendTo($('#qunit-fixture'));
//Render unknow im_status:
// set initial status
assert.ok(statusWidget.$('.o_updatable_im_status i').hasClass('o_user_online'));
@@ -167,6 +181,7 @@ QUnit.test('update status', function (assert) {
statusWidget.call('mail_service', 'updateImStatus', [
{ id: 1, im_status: 'offline' },
]);
+ await testUtils.nextTick();
assert.notOk(statusWidget.$('.o_updatable_im_status i').hasClass('o_user_online'));
this.timeoutMock.runPendingTimeouts();
statusWidget.destroy();
diff --git a/addons/mail/static/tests/models/cc_throttle_function_tests.js b/addons/mail/static/tests/models/cc_throttle_function_tests.js
index f5deb6c1f3c..5ab00ef6048 100644
--- a/addons/mail/static/tests/models/cc_throttle_function_tests.js
+++ b/addons/mail/static/tests/models/cc_throttle_function_tests.js
@@ -10,7 +10,7 @@ QUnit.module('mail', {
beforeEach: function () {
var self = this;
- this.timeoutCDDef = $.Deferred();
+ this.timeoutCDDef = testUtils.makeTestPromise();
this.patch = function () {
self.ORIGINAL_CCTFO_ON_CD_TIMEOUT = CCThrottleFunctionObject.prototype._onCooldownTimeout;
@@ -36,7 +36,7 @@ QUnit.test('cancel()', function (assert) {
assert.expect(3);
var self = this;
- var def = $.Deferred();
+ var def = testUtils.makeTestPromise();
var step = 1;
var widget = testUtils.createParent({
@@ -52,7 +52,7 @@ QUnit.test('cancel()', function (assert) {
}
step++;
- return $.when();
+ return Promise.resolve();
}
return this._super.apply(this, arguments);
},
@@ -80,7 +80,7 @@ QUnit.test('cancel()', function (assert) {
self.timeoutCDDef.resolve();
});
this.timeoutCDDef.then(function () {
- assert.verifySteps(['__rpc__1'],
+ assert.verifySteps([],
"function should still have been called once after 2nd function call cancelled");
widget.destroy();
done();
@@ -92,8 +92,8 @@ QUnit.test('clear()', function (assert) {
assert.expect(5);
var self = this;
- var def1 = $.Deferred();
- var def2 = $.Deferred();
+ var def1 = testUtils.makeTestPromise();
+ var def2 = testUtils.makeTestPromise();
var step = 1;
var widget = testUtils.createParent({
@@ -110,7 +110,7 @@ QUnit.test('clear()', function (assert) {
}
step++;
- return $.when();
+ return Promise.resolve();
}
return this._super.apply(this, arguments);
},
@@ -135,14 +135,14 @@ QUnit.test('clear()', function (assert) {
}).then(function () {
cctFunc(2);
}).then(function () {
- assert.verifySteps(['__rpc__1'],
+ assert.verifySteps([],
"function should still have been called once (due to long throttle)");
cctFunc.clear();
self.timeoutCDDef.resolve();
def2.resolve();
});
- $.when(self.timeoutCDDef, def2).then(function () {
- assert.verifySteps(['__rpc__1', '__rpc__2'],
+ Promise.all([self.timeoutCDDef, def2]).then(function () {
+ assert.verifySteps(['__rpc__2'],
"function should have been called twice after 'clear' (buffered 2nd function call)");
widget.destroy();
done();
diff --git a/addons/mail/static/tests/models/timer_tests.js b/addons/mail/static/tests/models/timer_tests.js
index 535c5649ec9..9a66e80ad22 100644
--- a/addons/mail/static/tests/models/timer_tests.js
+++ b/addons/mail/static/tests/models/timer_tests.js
@@ -1,31 +1,27 @@
odoo.define('mail.model.TimerTests', function (require) {
"use strict";
+var testUtils = require("web.test_utils");
var Timer = require('mail.model.Timer');
QUnit.module('mail', {}, function () {
QUnit.module('model', {}, function () {
QUnit.module('Timer');
-QUnit.test('start()', function (assert) {
- var done = assert.async();
+QUnit.test('start()', async function (assert) {
assert.expect(2);
- var def = $.Deferred();
- var func = function () {
- def.resolve();
- };
+ var prom = testUtils.makeTestPromise();
var t = new Timer({
duration: 0,
- onTimeout: func,
+ onTimeout: prom.resolve,
});
assert.verifySteps([], "should not have called the function");
t.start();
- def.then(function () {
+ await prom.then(function () {
assert.ok(true, "should have called the function");
- done();
});
});
@@ -51,11 +47,10 @@ QUnit.test('clear()', function (assert) {
}, 0);
});
-QUnit.test('reset()', function (assert) {
- var done = assert.async();
+QUnit.test('reset()', async function (assert) {
assert.expect(4);
- var def = $.Deferred();
+ var prom = testUtils.makeTestPromise();
var func = function () {
assert.step('function_called');
};
@@ -67,19 +62,17 @@ QUnit.test('reset()', function (assert) {
t.start();
// Called after 1st timer timeout
+ await testUtils.nextTick();
+ assert.verifySteps(['function_called'], "should have called the function once");
+ t.reset();
+ // Called after 2nd timer timeout
setTimeout(function () {
- assert.verifySteps(['function_called'], "should have called the function once");
- t.reset();
- // Called after 2nd timer timeout
- setTimeout(function () {
- def.resolve();
- }, 0);
+ prom.resolve();
}, 0);
- def.then(function () {
- assert.verifySteps(['function_called', 'function_called'],
+ await prom.then(function () {
+ assert.verifySteps(['function_called'],
"should have called the function twice (2nd time from reset)");
- done();
});
});
diff --git a/addons/mail/static/tests/systray/systray_activity_menu_tests.js b/addons/mail/static/tests/systray/systray_activity_menu_tests.js
index abf4dc6daf7..b2f76feb832 100644
--- a/addons/mail/static/tests/systray/systray_activity_menu_tests.js
+++ b/addons/mail/static/tests/systray/systray_activity_menu_tests.js
@@ -76,7 +76,7 @@ QUnit.module('ActivityMenu', {
}
});
-QUnit.test('activity menu widget: menu with no records', function (assert) {
+QUnit.test('activity menu widget: menu with no records', async function (assert) {
assert.expect(1);
var activityMenu = new ActivityMenu();
@@ -84,17 +84,18 @@ QUnit.test('activity menu widget: menu with no records', function (assert) {
services: this.services,
mockRPC: function (route, args) {
if (args.method === 'systray_get_activities') {
- return $.when([]);
+ return Promise.resolve([]);
}
return this._super(route, args);
},
});
- activityMenu.appendTo($('#qunit-fixture'));
- assert.hasClass(activityMenu.$('.o_no_activity'),'o_no_activity', "should not have instance of widget");
+ await activityMenu.appendTo($('#qunit-fixture'));
+ await testUtils.nextTick();
+ assert.containsOnce(activityMenu, '.o_no_activity');
activityMenu.destroy();
});
-QUnit.test('activity menu widget: activity menu with 3 records', function (assert) {
+QUnit.test('activity menu widget: activity menu with 3 records', async function (assert) {
assert.expect(10);
var self = this;
var activityMenu = new ActivityMenu();
@@ -102,12 +103,13 @@ QUnit.test('activity menu widget: activity menu with 3 records', function (asser
services: this.services,
mockRPC: function (route, args) {
if (args.method === 'systray_get_activities') {
- return $.when(self.data['mail.activity.menu']['records']);
+ return Promise.resolve(self.data['mail.activity.menu']['records']);
}
return this._super(route, args);
},
});
- activityMenu.appendTo($('#qunit-fixture'));
+ await activityMenu.appendTo($('#qunit-fixture'));
+ await testUtils.nextTick();
assert.hasClass(activityMenu.$el, 'o_mail_systray_item', 'should be the instance of widget');
// the assertion below has not been replace because there are includes of ActivityMenu that modify the length.
assert.ok(activityMenu.$('.o_mail_preview').length);
@@ -123,34 +125,34 @@ QUnit.test('activity menu widget: activity menu with 3 records', function (asser
context = {
search_default_activities_overdue: 1,
};
- testUtils.dom.click(activityMenu.$('.dropdown-toggle'));
+ await testUtils.dom.click(activityMenu.$('.dropdown-toggle'));
assert.hasClass(activityMenu.$el, 'show', 'ActivityMenu should be open');
- testUtils.dom.click(activityMenu.$(".o_activity_filter_button[data-model_name='Issue'][data-filter='overdue']"));
+ await testUtils.dom.click(activityMenu.$(".o_activity_filter_button[data-model_name='Issue'][data-filter='overdue']"));
assert.doesNotHaveClass(activityMenu.$el, 'show', 'ActivityMenu should be closed');
// case 2: click on "today"
context = {
search_default_activities_today: 1,
};
- testUtils.dom.click(activityMenu.$('.dropdown-toggle'));
- testUtils.dom.click(activityMenu.$(".o_activity_filter_button[data-model_name='Issue'][data-filter='today']"));
+ await testUtils.dom.click(activityMenu.$('.dropdown-toggle'));
+ await testUtils.dom.click(activityMenu.$(".o_activity_filter_button[data-model_name='Issue'][data-filter='today']"));
// case 3: click on "future"
context = {
search_default_activities_upcoming_all: 1,
};
- testUtils.dom.click(activityMenu.$('.dropdown-toggle'));
- testUtils.dom.click(activityMenu.$(".o_activity_filter_button[data-model_name='Issue'][data-filter='upcoming_all']"));
+ await testUtils.dom.click(activityMenu.$('.dropdown-toggle'));
+ await testUtils.dom.click(activityMenu.$(".o_activity_filter_button[data-model_name='Issue'][data-filter='upcoming_all']"));
// case 4: click anywere else
context = {
search_default_activities_overdue: 1,
search_default_activities_today: 1,
};
- testUtils.dom.click(activityMenu.$('.dropdown-toggle'));
- testUtils.dom.click(activityMenu.$(".o_mail_systray_dropdown_items > div[data-model_name='Issue']"));
+ await testUtils.dom.click(activityMenu.$('.dropdown-toggle'));
+ await testUtils.dom.click(activityMenu.$(".o_mail_systray_dropdown_items > div[data-model_name='Issue']"));
activityMenu.destroy();
});
-QUnit.test('activity menu widget: activity view icon', function (assert) {
+QUnit.test('activity menu widget: activity view icon', async function (assert) {
assert.expect(10);
var self = this;
var activityMenu = new ActivityMenu();
@@ -158,12 +160,13 @@ QUnit.test('activity menu widget: activity view icon', function (assert) {
services: this.services,
mockRPC: function (route, args) {
if (args.method === 'systray_get_activities') {
- return $.when(self.data['mail.activity.menu'].records);
+ return Promise.resolve(self.data['mail.activity.menu'].records);
}
return this._super(route, args);
},
});
- activityMenu.appendTo($('#qunit-fixture'));
+ await activityMenu.appendTo($('#qunit-fixture'));
+ await testUtils.nextTick();
assert.containsN(activityMenu, '.o_mail_activity_action', 2,
"widget should have 2 activity view icons");
@@ -189,11 +192,11 @@ QUnit.test('activity menu widget: activity view icon', function (assert) {
}, true);
// click on the "Issue" activity icon
- testUtils.dom.click(activityMenu.$('.dropdown-toggle'));
- testUtils.dom.click(activityMenu.$(".o_mail_activity_action[data-model_name='Issue']"));
+ await testUtils.dom.click(activityMenu.$('.dropdown-toggle'));
+ await testUtils.dom.click(activityMenu.$(".o_mail_activity_action[data-model_name='Issue']"));
// click on the "Note" activity icon
- testUtils.dom.click(activityMenu.$(".o_mail_activity_action[data-model_name='Note']"));
+ await testUtils.dom.click(activityMenu.$(".o_mail_activity_action[data-model_name='Note']"));
assert.verifySteps([
'do_action:Issue',
diff --git a/addons/mail/static/tests/systray/systray_messaging_menu_mail_failure_tests.js b/addons/mail/static/tests/systray/systray_messaging_menu_mail_failure_tests.js
index c03259697cd..f2c8e95ac29 100644
--- a/addons/mail/static/tests/systray/systray_messaging_menu_mail_failure_tests.js
+++ b/addons/mail/static/tests/systray/systray_messaging_menu_mail_failure_tests.js
@@ -66,7 +66,7 @@ QUnit.module('MessagingMenu (Mail Failures)', {
}
});
-QUnit.test('preview of mail failure', function (assert) {
+QUnit.test('preview of mail failure', async function (assert) {
assert.expect(4);
this.data['mail.message'].records = [{
@@ -86,8 +86,8 @@ QUnit.test('preview of mail failure', function (assert) {
data: this.data,
services: this.services,
});
- messagingMenu.appendTo($('#qunit-fixture'));
- testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
+ await messagingMenu.appendTo($('#qunit-fixture'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.containsOnce(messagingMenu, '.o_mail_preview',
"should display one preview for the mail failure");
@@ -101,7 +101,7 @@ QUnit.test('preview of mail failure', function (assert) {
messagingMenu.destroy();
});
-QUnit.test('preview grouped failures by document', function (assert) {
+QUnit.test('preview grouped failures by document', async function (assert) {
// If some failures linked to a document refers to a same document, a single
// preview should group all those failures
assert.expect(3);
@@ -142,8 +142,8 @@ QUnit.test('preview grouped failures by document', function (assert) {
data: this.data,
services: this.services,
});
- messagingMenu.appendTo($('#qunit-fixture'));
- testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
+ await messagingMenu.appendTo($('#qunit-fixture'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.containsN(messagingMenu, '.o_mail_preview', 2,
"should have a two messaging previews for the mail failures");
@@ -156,7 +156,7 @@ QUnit.test('preview grouped failures by document', function (assert) {
messagingMenu.destroy();
});
-QUnit.test('preview grouped failures by document model', function (assert) {
+QUnit.test('preview grouped failures by document model', async function (assert) {
// If all failures linked to a document model refers to different documents,
// a single preview should group all failures that are linked to this
// document model
@@ -198,8 +198,8 @@ QUnit.test('preview grouped failures by document model', function (assert) {
data: this.data,
services: this.services,
});
- messagingMenu.appendTo($('#qunit-fixture'));
- testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
+ await messagingMenu.appendTo($('#qunit-fixture'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.containsN(messagingMenu, '.o_mail_preview', 2,
"should have a two messaging previews for the mail failures");
diff --git a/addons/mail/static/tests/systray/systray_messaging_menu_tests.js b/addons/mail/static/tests/systray/systray_messaging_menu_tests.js
index 00abb2d0503..f3ae277ee56 100644
--- a/addons/mail/static/tests/systray/systray_messaging_menu_tests.js
+++ b/addons/mail/static/tests/systray/systray_messaging_menu_tests.js
@@ -101,7 +101,7 @@ QUnit.module('MessagingMenu', {
}
});
-QUnit.test('messaging menu widget: menu with no records', function (assert) {
+QUnit.test('messaging menu widget: menu with no records', async function (assert) {
assert.expect(1);
var messagingMenu = new MessagingMenu();
@@ -109,27 +109,27 @@ QUnit.test('messaging menu widget: menu with no records', function (assert) {
services: this.services,
mockRPC: function (route, args) {
if (args.method === 'message_fetch') {
- return $.when([]);
+ return Promise.resolve([]);
}
return this._super.apply(this, arguments);
}
});
- messagingMenu.appendTo($('#qunit-fixture'));
- testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
+ await messagingMenu.appendTo($('#qunit-fixture'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.hasClass(messagingMenu.$('.o_no_activity'),'o_no_activity', "should not have instance of widget");
messagingMenu.destroy();
});
-QUnit.test('messaging menu widget: messaging menu with 1 record', function (assert) {
+QUnit.test('messaging menu widget: messaging menu with 1 record', async function (assert) {
assert.expect(3);
var messagingMenu = new MessagingMenu();
testUtils.mock.addMockEnvironment(messagingMenu, {
services: this.services,
data: this.data,
});
- messagingMenu.appendTo($('#qunit-fixture'));
+ await messagingMenu.appendTo($('#qunit-fixture'));
- testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.containsOnce(messagingMenu, '.o_mail_preview',
"should display a preview");
@@ -146,7 +146,7 @@ QUnit.test('messaging menu widget: messaging menu with 1 record', function (asse
messagingMenu.destroy();
});
-QUnit.test('messaging menu widget: open inbox for needaction not linked to any document', function (assert) {
+QUnit.test('messaging menu widget: open inbox for needaction not linked to any document', async function (assert) {
assert.expect(4);
var messagingMenu = new MessagingMenu();
@@ -157,7 +157,7 @@ QUnit.test('messaging menu widget: open inbox for needaction not linked to any d
partner_id: 1,
},
});
- messagingMenu.appendTo($('#qunit-fixture'));
+ await messagingMenu.appendTo($('#qunit-fixture'));
// Simulate received needaction message without associated document,
// so that we have a message in inbox without a model and a resID
@@ -174,7 +174,7 @@ QUnit.test('messaging menu widget: open inbox for needaction not linked to any d
messagingMenu.call('bus_service', 'trigger', 'notification', notifications);
// Open messaging menu
- testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
var $firstChannelPreview =
messagingMenu.$('.o_mail_preview').first();
@@ -190,7 +190,7 @@ QUnit.test('messaging menu widget: open inbox for needaction not linked to any d
assert.step('do_action:' + ev.data.action + ':' + ev.data.options.active_id);
}
}, true);
- testUtils.dom.click($firstChannelPreview);
+ await testUtils.dom.click($firstChannelPreview);
assert.verifySteps(
['do_action:mail.action_discuss:mailbox_inbox'],
"should open Discuss with Inbox");
@@ -198,7 +198,7 @@ QUnit.test('messaging menu widget: open inbox for needaction not linked to any d
messagingMenu.destroy();
});
-QUnit.test("messaging menu widget: mark as read on thread preview", function ( assert ) {
+QUnit.test("messaging menu widget: mark as read on thread preview", async function ( assert ) {
assert.expect(8);
testUtils.mock.patch(DocumentThread, {
@@ -230,8 +230,8 @@ QUnit.test("messaging menu widget: mark as read on thread preview", function ( a
data: this.data,
});
- messagingMenu.appendTo($('#qunit-fixture'));
- testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
+ await messagingMenu.appendTo($('#qunit-fixture'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.hasClass(messagingMenu.$el,'o_mail_systray_item',
'should be the instance of widget');
assert.hasClass(messagingMenu.$el,'show',
@@ -247,7 +247,7 @@ QUnit.test("messaging menu widget: mark as read on thread preview", function ( a
assert.containsOnce(messagingMenu, '.o_mail_preview_mark_as_read',
"should have mark as read icon next to preview");
- testUtils.dom.click(messagingMenu.$(".o_mail_preview_mark_as_read"));
+ await testUtils.dom.click(messagingMenu.$(".o_mail_preview_mark_as_read"));
assert.verifySteps(['markedAsRead'],
"the document thread should be marked as read");
@@ -256,7 +256,7 @@ QUnit.test("messaging menu widget: mark as read on thread preview", function ( a
messagingMenu.destroy();
});
-QUnit.test('needaction messages in channels should appear, in addition to channel preview', function (assert) {
+QUnit.test('needaction messages in channels should appear, in addition to channel preview', async function (assert) {
// Let's suppose a channel whose before-last message (msg1) is a needaction,
// but not the last message (msg2). In that case, the systray messaging
// menu should display the needaction message msg1 in the preview, and the
@@ -295,9 +295,9 @@ QUnit.test('needaction messages in channels should appear, in addition to channe
partner_id: partnerID,
},
});
- messagingMenu.appendTo($('#qunit-fixture'));
+ await messagingMenu.appendTo($('#qunit-fixture'));
- testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.containsN(messagingMenu, '.o_mail_preview', 2,
"should display two previews");
@@ -314,7 +314,7 @@ QUnit.test('needaction messages in channels should appear, in addition to channe
messagingMenu.destroy();
});
-QUnit.test('preview of message on a document + mark as read', function (assert) {
+QUnit.test('preview of message on a document + mark as read', async function (assert) {
assert.expect(7);
this.data.initMessaging = {
@@ -351,11 +351,11 @@ QUnit.test('preview of message on a document + mark as read', function (assert)
partner_id: partnerID,
},
});
- messagingMenu.appendTo($('#qunit-fixture'));
+ await messagingMenu.appendTo($('#qunit-fixture'));
assert.strictEqual(messagingMenu.$('.o_notification_counter').text(), '1',
"should display a counter of 1 on the messaging menu icon");
- testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.containsOnce(messagingMenu, '.o_mail_preview',
"should display one preview");
@@ -367,7 +367,7 @@ QUnit.test('preview of message on a document + mark as read', function (assert)
assert.strictEqual(messagingMenu.$('.o_preview_unread .o_last_message_preview').text().replace(/\s/g, ''),
"Demo:*MessageOnDocument*", "should correctly display the preview");
- testUtils.dom.click(messagingMenu.$('.o_mail_preview_mark_as_read'));
+ await testUtils.dom.click(messagingMenu.$('.o_mail_preview_mark_as_read'));
assert.strictEqual(messagingMenu.$('.o_notification_counter').text(), '0',
"should display a counter of 0 on the messaging menu icon");
assert.containsNone(messagingMenu, '.o_mail_preview',
@@ -376,7 +376,7 @@ QUnit.test('preview of message on a document + mark as read', function (assert)
messagingMenu.destroy();
});
-QUnit.test('update messaging preview on receiving a new message in channel preview', function (assert) {
+QUnit.test('update messaging preview on receiving a new message in channel preview', async function (assert) {
assert.expect(8);
var messagingMenu = new MessagingMenu();
@@ -384,9 +384,9 @@ QUnit.test('update messaging preview on receiving a new message in channel previ
services: this.services,
data: this.data,
});
- messagingMenu.appendTo($('#qunit-fixture'));
+ await messagingMenu.appendTo($('#qunit-fixture'));
- testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.containsOnce(messagingMenu, '.o_mail_preview',
"should display a single channel preview");
@@ -410,7 +410,7 @@ QUnit.test('update messaging preview on receiving a new message in channel previ
};
var notification = [[false, 'mail.channel', 1], data];
messagingMenu.call('bus_service', 'trigger', 'notification', [notification]);
-
+ await testUtils.nextTick();
assert.containsOnce(messagingMenu, '.o_mail_preview',
"should still display a single channel preview");
assert.strictEqual(messagingMenu.$('.o_preview_name').text().trim(), "general",
@@ -427,7 +427,7 @@ QUnit.test('update messaging preview on receiving a new message in channel previ
messagingMenu.destroy();
});
-QUnit.test('preview of inbox message not linked to document + mark as read', function (assert) {
+QUnit.test('preview of inbox message not linked to document + mark as read', async function (assert) {
assert.expect(17);
this.data.initMessaging = {
@@ -459,19 +459,16 @@ QUnit.test('preview of inbox message not linked to document + mark as read', fun
},
mockRPC: function (route, args) {
if (args.method === 'set_message_done') {
- assert.step({
- method: 'set_message_done',
- messageIDs: args.args[0],
- });
+ assert.step('method: set_message_done, messageIDs: ' + JSON.stringify(args.args[0]));
}
return this._super.apply(this, arguments);
},
});
- messagingMenu.appendTo($('#qunit-fixture'));
+ await messagingMenu.appendTo($('#qunit-fixture'));
assert.strictEqual(messagingMenu.$('.o_notification_counter').text(), '2',
"should display a counter of 2 on the messaging menu icon");
- messagingMenu.$('.dropdown-toggle').click();
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.strictEqual(messagingMenu.$('.o_mail_preview').length, 2,
"should display two previews");
@@ -494,11 +491,9 @@ QUnit.test('preview of inbox message not linked to document + mark as read', fun
assert.strictEqual($preview2.find('.o_last_message_preview').text().replace(/\s/g, ''),
"Demo:*Message2*", "should correctly display the 2nd preview");
- $preview1.find('.o_mail_preview_mark_as_read').click();
- assert.verifySteps([{
- method: 'set_message_done',
- messageIDs: [689],
- }], "should mark 1st preview as read");
+ await testUtils.dom.click($preview1.find('.o_mail_preview_mark_as_read'));
+ assert.verifySteps(['method: set_message_done, messageIDs: [689]'],
+ "should mark 1st preview as read");
assert.strictEqual(messagingMenu.$('.o_notification_counter').text(), '1',
"should display a counter of 1 on the messaging menu icon after marking one preview as read");
assert.strictEqual(messagingMenu.$('.o_mail_preview').length, 1,
@@ -507,14 +502,9 @@ QUnit.test('preview of inbox message not linked to document + mark as read', fun
"Demo:*Message2*", "preview 2 should be the remaining one");
$preview2 = messagingMenu.$('.o_mail_preview');
- $preview2.find('.o_mail_preview_mark_as_read').click();
- assert.verifySteps([{
- method: 'set_message_done',
- messageIDs: [689],
- }, {
- method: 'set_message_done',
- messageIDs: [690],
- }], "should mark 2nd preview as read");
+ await testUtils.dom.click($preview2.find('.o_mail_preview_mark_as_read'));
+ assert.verifySteps(['method: set_message_done, messageIDs: [690]'],
+ "should mark 2nd preview as read");
assert.strictEqual(messagingMenu.$('.o_notification_counter').text(), '0',
"should display a counter of 0 on the messaging menu icon after marking both previews as read");
assert.strictEqual(messagingMenu.$('.o_mail_preview').length, 0,
@@ -523,7 +513,7 @@ QUnit.test('preview of inbox message not linked to document + mark as read', fun
messagingMenu.destroy();
});
-QUnit.test('grouped preview for needaction messages linked to same document', function (assert) {
+QUnit.test('grouped preview for needaction messages linked to same document', async function (assert) {
assert.expect(5);
// simulate two (read) needaction (mention) messages in channel 'general'
@@ -561,9 +551,9 @@ QUnit.test('grouped preview for needaction messages linked to same document', fu
partner_id: 44,
},
});
- messagingMenu.appendTo($('#qunit-fixture'));
+ await messagingMenu.appendTo($('#qunit-fixture'));
- messagingMenu.$('.dropdown-toggle').click();
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
var $previews = messagingMenu.$('.o_mail_preview');
assert.strictEqual($previews.length, 2,
@@ -586,7 +576,7 @@ QUnit.test('grouped preview for needaction messages linked to same document', fu
messagingMenu.destroy();
});
-QUnit.test("messaging menu widget: channel seen notification", function (assert) {
+QUnit.test("messaging menu widget: channel seen notification", async function (assert) {
assert.expect(4);
this.data.initMessaging.channel_slots = {
@@ -606,8 +596,8 @@ QUnit.test("messaging menu widget: channel seen notification", function (assert)
session: { partner_id: 3 },
});
- messagingMenu.appendTo($('#qunit-fixture'));
- messagingMenu.$('.dropdown-toggle').click();
+ await messagingMenu.appendTo($('#qunit-fixture'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.strictEqual(messagingMenu.$('.o_notification_counter').text(), '1',
"should have correct messaging menu counter (1 unread message in channel)");
@@ -625,7 +615,7 @@ QUnit.test("messaging menu widget: channel seen notification", function (assert)
[['myDB', 'mail.channel', 1], message]
];
messagingMenu.call('bus_service', 'trigger', 'notification', notifications);
-
+ await testUtils.nextTick();
assert.strictEqual(messagingMenu.$('.o_notification_counter').text(), '0',
"should no longer have a messaging menu counter (no unread message in channel)");
assert.strictEqual(messagingMenu.$('.o_preview_counter').text().replace(/\s/g, ''), '',
@@ -634,7 +624,7 @@ QUnit.test("messaging menu widget: channel seen notification", function (assert)
messagingMenu.destroy();
});
-QUnit.test("messaging menu widget: no traceback when receiving channel_fetched notification with blank thread window", function (assert) {
+QUnit.test("messaging menu widget: no traceback when receiving channel_fetched notification with blank thread window", async function (assert) {
assert.expect(3);
this.data.initMessaging.channel_slots = {
@@ -654,12 +644,12 @@ QUnit.test("messaging menu widget: no traceback when receiving channel_fetched n
session: { partner_id: 3 },
});
- messagingMenu.appendTo($('#qunit-fixture'));
- messagingMenu.$('.dropdown-toggle').click();
+ await messagingMenu.appendTo($('#qunit-fixture'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.containsOnce(messagingMenu, '.o_new_message',
"should have button to open blank thread window");
- testUtils.dom.click(messagingMenu.$('.o_new_message'));
+ await testUtils.dom.click(messagingMenu.$('.o_new_message'));
var $threadWindow = $('.o_thread_window');
assert.strictEqual($threadWindow.length, 1, "should have an open thread window");
assert.ok($threadWindow.hasClass('o_thread_less'), "should be a blank thread window");
@@ -674,11 +664,12 @@ QUnit.test("messaging menu widget: no traceback when receiving channel_fetched n
[['myDB', 'mail.channel', 1], message]
];
messagingMenu.call('bus_service', 'trigger', 'notification', notifications);
+ await testUtils.nextTick();
messagingMenu.destroy();
});
-QUnit.test("messaging menu widget: preview with no message should be undated", function ( assert ) {
+QUnit.test("messaging menu widget: preview with no message should be undated", async function ( assert ) {
assert.expect(2);
// remove any message on the channel
@@ -691,9 +682,8 @@ QUnit.test("messaging menu widget: preview with no message should be undated", f
data: this.data,
});
- messagingMenu.appendTo($('#qunit-fixture'));
-
- messagingMenu.$('.dropdown-toggle').click();
+ await messagingMenu.appendTo($('#qunit-fixture'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.strictEqual(messagingMenu.$('.o_mail_preview').length, 1,
"should have two previews in messaging menu");
@@ -704,7 +694,7 @@ QUnit.test("messaging menu widget: preview with no message should be undated", f
messagingMenu.destroy();
});
-QUnit.test("messaging menu widget: sort dated previews before undated previews", function ( assert ) {
+QUnit.test("messaging menu widget: sort dated previews before undated previews", async function ( assert ) {
assert.expect(5);
var dm = {
@@ -722,8 +712,8 @@ QUnit.test("messaging menu widget: sort dated previews before undated previews",
data: this.data,
});
- messagingMenu.appendTo($('#qunit-fixture'));
- messagingMenu.$('.dropdown-toggle').click();
+ await messagingMenu.appendTo($('#qunit-fixture'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.strictEqual(messagingMenu.$('.o_mail_preview').length, 2,
"should have two previews in messaging menu");
@@ -743,7 +733,7 @@ QUnit.test("messaging menu widget: sort dated previews before undated previews",
messagingMenu.destroy();
});
-QUnit.test('global counter with channel previews', function (assert) {
+QUnit.test('global counter with channel previews', async function (assert) {
assert.expect(5);
var channels = [{
@@ -812,11 +802,10 @@ QUnit.test('global counter with channel previews', function (assert) {
partner_id: 3,
},
});
- messagingMenu.appendTo($('#qunit-fixture'));
+ await messagingMenu.appendTo($('#qunit-fixture'));
assert.strictEqual(messagingMenu.$('.o_notification_counter').text(), '2',
"should display a counter of 2 on the messaging menu icon");
-
- messagingMenu.$('.dropdown-toggle').click();
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
assert.strictEqual(messagingMenu.$('.o_mail_preview').length, 3,
"should display 3 previews");
@@ -834,7 +823,7 @@ QUnit.test('global counter with channel previews', function (assert) {
messagingMenu.destroy();
});
-QUnit.test('messaging menu widget: do not open chat window twice on preview clicked', function (assert) {
+QUnit.test('messaging menu widget: do not open chat window twice on preview clicked', async function (assert) {
// This test assumes that a condition for opening chat window is to
// successfully fetch messages beforehand.
assert.expect(4);
@@ -844,7 +833,7 @@ QUnit.test('messaging menu widget: do not open chat window twice on preview clic
// This is necessary `message_fetch` on mailbox_inbox is required to
// display the previews.
var lockMessageFetch = false;
- var messageFetchDef = $.Deferred();
+ var messageFetchDef = testUtils.makeTestPromise();
var messagingMenu = new MessagingMenu();
testUtils.addMockEnvironment(messagingMenu, {
@@ -873,19 +862,20 @@ QUnit.test('messaging menu widget: do not open chat window twice on preview clic
return this._super.apply(this, arguments);
},
});
- messagingMenu.appendTo($('#qunit-fixture'));
+ await messagingMenu.appendTo($('#qunit-fixture'));
// Opening chat window from messaging menu (pending from `messageFetchDef`)
- testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
+ await testUtils.dom.click(messagingMenu.$('.dropdown-toggle'));
lockMessageFetch = true;
- testUtils.dom.click(messagingMenu.$('.o_mail_preview'));
+ await testUtils.dom.click(messagingMenu.$('.o_mail_preview'));
messageFetchDef.resolve();
+ await testUtils.nextTick();
assert.strictEqual($('.o_thread_window').length, 1,
"should only display a single chat window");
assert.verifySteps([
- 'channel_minimize',
'message_fetch',
+ 'channel_minimize',
], "should have fetched messages only once");
messagingMenu.destroy();
diff --git a/addons/mail/static/tests/thread_window/basic_thread_window_tests.js b/addons/mail/static/tests/thread_window/basic_thread_window_tests.js
index 5a0bc62f880..d5af9cf5357 100644
--- a/addons/mail/static/tests/thread_window/basic_thread_window_tests.js
+++ b/addons/mail/static/tests/thread_window/basic_thread_window_tests.js
@@ -55,7 +55,7 @@ QUnit.module('Basic', {
},
});
-QUnit.test('basic rendering thread window', function (assert) {
+QUnit.test('basic rendering thread window', async function (assert) {
assert.expect(10);
var parent = this.createParent({
@@ -63,9 +63,13 @@ QUnit.test('basic rendering thread window', function (assert) {
services: this.services,
});
+ await testUtils.nextTick();
// detach channel 1, so that it opens corresponding thread window.
- parent.call('mail_service', 'getChannel', 1).detach();
+ var result = parent.call('mail_service', 'getChannel', 1);
+ await testUtils.nextTick();
+ result.detach();
+ await testUtils.nextTick();
var $threadWindow = $('.o_thread_window');
assert.strictEqual($threadWindow.length, 1,
"thread window should be open");
@@ -98,7 +102,7 @@ QUnit.test('basic rendering thread window', function (assert) {
parent.destroy();
});
-QUnit.test('close thread window using ESCAPE key', function (assert) {
+QUnit.test('close thread window using ESCAPE key', async function (assert) {
assert.expect(5);
var parent = this.createParent({
@@ -107,28 +111,31 @@ QUnit.test('close thread window using ESCAPE key', function (assert) {
mockRPC: function (route, args) {
if (args.method === 'channel_fold') {
assert.ok(true, "should call channel_fold");
- return $.when();
+ return Promise.resolve();
}
return this._super.apply(this, arguments);
},
});
+ await testUtils.nextTick();
// get channel instance to link to thread window
var channel = parent.call('mail_service', 'getChannel', 1);
+ await testUtils.nextTick();
assert.ok(channel, "there should exist a channel locally with ID 1");
channel.detach();
+ await testUtils.nextTick();
assert.strictEqual($('.o_thread_window').length, 1,
"there should be a thread window that is opened");
// focus on the thread window and press ESCAPE
- testUtils.dom.click($('.o_thread_window .o_composer_text_field'));
+ await testUtils.dom.click($('.o_thread_window .o_composer_text_field'));
assert.strictEqual(document.activeElement,
$('.o_thread_window .o_composer_text_field')[0],
"thread window's input should now be focused");
var upKeyEvent = $.Event( "keyup", { which: 27 });
- $('.o_thread_window .o_composer_text_field').trigger(upKeyEvent);
+ await testUtils.dom.triggerEvents($('.o_thread_window .o_composer_text_field'), [upKeyEvent]);
assert.strictEqual($('.o_thread_window').length, 0,
"the thread window should be closed");
@@ -136,7 +143,7 @@ QUnit.test('close thread window using ESCAPE key', function (assert) {
parent.destroy();
});
-QUnit.test('thread window\'s input can still be focused when the UI is blocked', function (assert) {
+QUnit.test('thread window\'s input can still be focused when the UI is blocked', async function (assert) {
assert.expect(2);
var parent = this.createParent({
@@ -147,11 +154,13 @@ QUnit.test('thread window\'s input can still be focused when the UI is blocked',
var $dom = $('#qunit-fixture');
// get channel instance to link to thread window
+ await testUtils.nextTick();
var channel = parent.call('mail_service', 'getChannel', 1);
+ await testUtils.nextTick();
channel.detach();
-
+ await testUtils.nextTick();
var $input = $('<input/>', {type: 'text'}).appendTo($dom);
- testUtils.dom.click($input.focus());
+ await testUtils.dom.click($input.focus());
assert.strictEqual(document.activeElement, $input[0],
"fake input should be focused");
@@ -160,16 +169,17 @@ QUnit.test('thread window\'s input can still be focused when the UI is blocked',
// makes no sense, this test is just about
// making sure that the code which forces the
// focus on click is not removed
- testUtils.dom.click($('.o_thread_window .o_composer_text_field'));
+ await testUtils.dom.click($('.o_thread_window .o_composer_text_field'));
assert.strictEqual(document.activeElement,
$('.o_thread_window .o_composer_text_field')[0],
"thread window's input should now be focused");
framework.unblockUI();
parent.destroy();
+ $input.remove();
});
-QUnit.test('emoji popover should open correctly in thread windows', function (assert) {
+QUnit.test('emoji popover should open correctly in thread windows', async function (assert) {
assert.expect(1);
var parent = this.createParent({
@@ -178,23 +188,20 @@ QUnit.test('emoji popover should open correctly in thread windows', function (as
});
// get channel instance to link to thread window
+ await testUtils.nextTick();
var channel = parent.call('mail_service', 'getChannel', 1);
+ await testUtils.nextTick();
channel.detach();
-
+ await testUtils.nextTick();
var $emojiButton = $('.o_composer_button_emoji');
- testUtils.dom.click($emojiButton.trigger('focusin').focus());
+ await testUtils.dom.click($emojiButton.trigger('focusin').focus());
var $popover = $('.o_mail_emoji_container');
- var done = assert.async();
- // Async is needed as the popover focusout hiding is deferred
- setTimeout(function () {
- assert.ok($popover.is(':visible'), "emoji popover should have stayed opened");
- parent.destroy();
- done();
- }, 0);
+ assert.ok($popover.is(':visible'), "emoji popover should have stayed opened");
+ parent.destroy();
});
-QUnit.test('do not increase unread counter when receiving message with myself as author', function (assert) {
+QUnit.test('do not increase unread counter when receiving message with myself as author', async function (assert) {
assert.expect(4);
var parent = this.createParent({
@@ -204,9 +211,11 @@ QUnit.test('do not increase unread counter when receiving message with myself as
});
// get channel instance to link to thread window
+ await testUtils.nextTick();
var channel = parent.call('mail_service', 'getChannel', 1);
+ await testUtils.nextTick();
channel.detach();
-
+ await testUtils.nextTick();
var threadWindowHeaderText = $('.o_thread_window_header').text().replace(/\s/g, "");
assert.strictEqual(threadWindowHeaderText, "#general",
@@ -226,6 +235,7 @@ QUnit.test('do not increase unread counter when receiving message with myself as
var notification = [[false, 'mail.channel', 1], messageData];
parent.call('bus_service', 'trigger', 'notification', [notification]);
+ await testUtils.nextTick();
threadWindowHeaderText = $('.o_thread_window_header').text().replace(/\s/g, "");
assert.strictEqual(threadWindowHeaderText, "#general",
@@ -236,7 +246,7 @@ QUnit.test('do not increase unread counter when receiving message with myself as
parent.destroy();
});
-QUnit.test('do not increment unread counter with focus on thread window', function (assert) {
+QUnit.test('do not increment unread counter with focus on thread window', async function (assert) {
// 'hard' focus means that the user has clicked on the thread window in
// order to set the focus on it.
assert.expect(2);
@@ -248,14 +258,17 @@ QUnit.test('do not increment unread counter with focus on thread window', functi
});
// get channel instance to link to thread window
+ await testUtils.nextTick();
var channel = parent.call('mail_service', 'getChannel', 1);
+ await testUtils.nextTick();
channel.detach();
+ await testUtils.nextTick();
assert.strictEqual(channel.getUnreadCounter(), 0,
"thread should have unread counter to 0 initially");
// hard focus on thread window composer
- testUtils.dom.click($('.o_composer_text_field'));
+ await testUtils.dom.click($('.o_composer_text_field'));
// simulate receiving message from someone else
var messageData = {
@@ -268,6 +281,7 @@ QUnit.test('do not increment unread counter with focus on thread window', functi
};
var notification = [[false, 'mail.channel', 1], messageData];
parent.call('bus_service', 'trigger', 'notification', [notification]);
+ await testUtils.nextTick();
assert.strictEqual(channel.getUnreadCounter(), 0,
"thread should not have incremented its unread counter after receiving the message");
@@ -275,7 +289,7 @@ QUnit.test('do not increment unread counter with focus on thread window', functi
parent.destroy();
});
-QUnit.test('do not mark as read the newly open thread window from received message', function (assert) {
+QUnit.test('do not mark as read the newly open thread window from received message', async function (assert) {
assert.expect(5);
this.data['mail.channel'] = {
@@ -315,7 +329,7 @@ QUnit.test('do not mark as read the newly open thread window from received messa
if (args.method === 'channel_join_and_get_info') {
this.data['mail.channel'].records[0].state = 'open';
this.data['mail.channel'].records[0].is_minimized = true;
- return $.when(this.data['mail.channel'].records[0]);
+ return Promise.resolve(this.data['mail.channel'].records[0]);
}
return this._super.apply(this, arguments);
},
@@ -338,7 +352,7 @@ QUnit.test('do not mark as read the newly open thread window from received messa
// a new message from a new channel.
this.data['mail.channel'].records[0].message_unread_counter++;
parent.call('bus_service', 'trigger', 'notification', [notification]);
-
+ await testUtils.nextTick();
var $threadWindow = $('.o_thread_window');
assert.strictEqual($threadWindow.length, 1,
"a thread window should be open after receiving a new message on a new DM chat");
@@ -347,14 +361,14 @@ QUnit.test('do not mark as read the newly open thread window from received messa
assert.strictEqual($threadWindow.find('.o_thread_window_title').text().replace(/\s/g, ''), '#DM(1)',
"open DM chat window should have one unread message");
- testUtils.dom.click($threadWindow.find('.o_thread_composer'));
+ await testUtils.dom.click($threadWindow.find('.o_thread_composer'));
assert.strictEqual($threadWindow.find('.o_thread_window_title').text().replace(/\s/g, ''), '#DM',
"open DM chat window should have message marked as read on composer focus");
parent.destroy();
});
-QUnit.test('show document link of message linked to a document', function (assert) {
+QUnit.test('show document link of message linked to a document', async function (assert) {
assert.expect(6);
this.data['mail.channel'] = {
@@ -410,8 +424,11 @@ QUnit.test('show document link of message linked to a document', function (asser
"no thread window should be open initially");
// get channel instance to link to thread window
+ await testUtils.nextTick();
var channel = parent.call('mail_service', 'getChannel', 2);
+ await testUtils.nextTick();
channel.detach();
+ await testUtils.nextTick();
var $threadWindow = $('.o_thread_window');
assert.strictEqual($threadWindow.length, 1,
@@ -429,7 +446,7 @@ QUnit.test('show document link of message linked to a document', function (asser
parent.destroy();
});
-QUnit.test('do not autofocus chat window on receiving new direct message', function (assert) {
+QUnit.test('do not autofocus chat window on receiving new direct message', async function (assert) {
// Receiving a message doesn't make other input loose focus
assert.expect(3);
@@ -473,7 +490,7 @@ QUnit.test('do not autofocus chat window on receiving new direct message', funct
}],
};
- var form = testUtils.createView({
+ var form = await testUtils.createView({
View: FormView,
model: 'partner',
data: this.data,
@@ -487,7 +504,7 @@ QUnit.test('do not autofocus chat window on receiving new direct message', funct
},
mockRPC: function (route, args) {
if (args.method === 'channel_join_and_get_info') {
- return $.when(this.data['mail.channel'].records[0]);
+ return Promise.resolve(this.data['mail.channel'].records[0]);
}
return this._super.apply(this, arguments);
}
@@ -512,7 +529,7 @@ QUnit.test('do not autofocus chat window on receiving new direct message', funct
this.data['mail.message'].records.push(messageData);
var notification = [[false, 'mail.channel', 2], messageData];
form.call('bus_service', 'trigger', 'notification', [notification]);
-
+ await testUtils.nextTick();
assert.ok($('.o_thread_window.o_in_home_menu').length,
'Chat window is opened');
@@ -522,7 +539,7 @@ QUnit.test('do not autofocus chat window on receiving new direct message', funct
form.destroy();
});
-QUnit.test('do not auto-focus chat window on receiving new message from new DM', function (assert) {
+QUnit.test('do not auto-focus chat window on receiving new message from new DM', async function (assert) {
assert.expect(10);
var self = this;
@@ -564,7 +581,7 @@ QUnit.test('do not auto-focus chat window on receiving new message from new DM',
session: { partner_id: 3 },
mockRPC: function (route, args) {
if (args.method === 'channel_join_and_get_info') {
- return $.when(_.extend({}, self.data['mail.channel'].records[0], { info: 'join' }));
+ return Promise.resolve(_.extend({}, self.data['mail.channel'].records[0], { info: 'join' }));
}
if (args.method === 'channel_minimize') {
_.extend(self.data['mail.channel'].records[0], {
@@ -594,6 +611,7 @@ QUnit.test('do not auto-focus chat window on receiving new message from new DM',
this.data['mail.message'].records.push(messageData);
var notification = [[false, 'mail.channel', 2], messageData];
parent.call('bus_service', 'trigger', 'notification', [notification]);
+ await testUtils.nextTick();
assert.strictEqual($('.o_thread_window').length, 1,
"should have DM window open");
@@ -610,6 +628,7 @@ QUnit.test('do not auto-focus chat window on receiving new message from new DM',
});
notification = [[false, 'res.partner', 3], dmInfo];
parent.call('bus_service', 'trigger', 'notification', [notification]);
+ await testUtils.nextTick();
assert.strictEqual($('.o_thread_window').length, 1,
"should still have DM window open after receiving DM info from polling");
@@ -621,6 +640,7 @@ QUnit.test('do not auto-focus chat window on receiving new message from new DM',
// simulate receiving detached DM notification (cross-tab synchronization)
notification = [[false, 'res.partner', 3], self.data['mail.channel'].records[0]];
parent.call('bus_service', 'trigger', 'notification', [notification]);
+ await testUtils.nextTick();
assert.strictEqual($('.o_thread_window').length, 1,
"should still have DM open after receiving detached info from polling");
@@ -632,7 +652,7 @@ QUnit.test('do not auto-focus chat window on receiving new message from new DM',
parent.destroy();
});
-QUnit.test('out-of-office status in thread window', function (assert) {
+QUnit.test('out-of-office status in thread window', async function (assert) {
assert.expect(1);
this.data = {
'mail.message': {
@@ -655,8 +675,13 @@ QUnit.test('out-of-office status in thread window', function (assert) {
data: this.data,
services: this.services,
});
+ await testUtils.nextTick();
+
// detach channel 1, so that it opens corresponding thread window.
- parent.call('mail_service', 'getChannel', 1).detach();
+ var channel = parent.call('mail_service', 'getChannel', 1);
+ await testUtils.nextTick();
+ channel.detach();
+ await testUtils.nextTick();
var $threadWindow = $('.o_thread_window');
assert.containsOnce($threadWindow, '.o_out_of_office_text');
@@ -664,7 +689,7 @@ QUnit.test('out-of-office status in thread window', function (assert) {
parent.destroy();
});
-QUnit.test('no out-of-office status in thread window', function (assert) {
+QUnit.test('no out-of-office status in thread window', async function (assert) {
assert.expect(1);
this.data = {
'mail.message': {
@@ -687,11 +712,17 @@ QUnit.test('no out-of-office status in thread window', function (assert) {
data: this.data,
services: this.services,
});
+ await testUtils.nextTick();
+
// detach channel 1, so that it opens corresponding thread window.
- parent.call('mail_service', 'getChannel', 1).detach();
+ var channel = parent.call('mail_service', 'getChannel', 1);
+ await testUtils.nextTick();
+ channel.detach();
+ await testUtils.nextTick();
var $threadWindow = $('.o_thread_window');
assert.containsNone($threadWindow, '.o_out_of_office_text');
+
parent.destroy();
});
diff --git a/addons/mail/static/tests/thread_window/blank_thread_window_tests.js b/addons/mail/static/tests/thread_window/blank_thread_window_tests.js
index 4f103f71163..4a24a80d4c3 100644
--- a/addons/mail/static/tests/thread_window/blank_thread_window_tests.js
+++ b/addons/mail/static/tests/thread_window/blank_thread_window_tests.js
@@ -53,8 +53,8 @@ QUnit.module('Blank', {
* functions end.
*
* @param {Object} params
- * @param {$.Deferred} params.selectDef
- * @param {$.Deferred} params.sourceDef
+ * @param {Promise} params.selectDef
+ * @param {Promise} params.sourceDef
*/
this.patchAutocomplete = function (params) {
var selectDef = params.selectDef;
@@ -87,7 +87,7 @@ QUnit.module('Blank', {
},
});
-QUnit.test('basic rendering blank thread window', function (assert) {
+QUnit.test('basic rendering blank thread window', async function (assert) {
assert.expect(5);
var parent = this.createParent({
@@ -97,7 +97,7 @@ QUnit.test('basic rendering blank thread window', function (assert) {
// open blank thread window
parent.call('mail_service', 'openBlankThreadWindow');
-
+ await testUtils.nextMicrotaskTick();
assert.strictEqual($('.o_thread_window').length, 1,
"should have a thread window open");
assert.strictEqual($('.o_thread_window_title').text().trim(),
@@ -114,7 +114,7 @@ QUnit.test('basic rendering blank thread window', function (assert) {
parent.destroy();
});
-QUnit.test('close blank thread window', function (assert) {
+QUnit.test('close blank thread window', async function (assert) {
assert.expect(1);
var parent = this.createParent({
@@ -124,8 +124,9 @@ QUnit.test('close blank thread window', function (assert) {
// open blank thread window
parent.call('mail_service', 'openBlankThreadWindow');
+ await testUtils.nextMicrotaskTick();
- testUtils.dom.click($('.o_thread_window_close'));
+ await testUtils.dom.click($('.o_thread_window_close'));
assert.strictEqual($('.o_thread_window').length, 0,
"blank thread window should be closed");
@@ -133,10 +134,10 @@ QUnit.test('close blank thread window', function (assert) {
parent.destroy();
});
-QUnit.test('fold blank thread window', function (assert) {
+QUnit.test('fold blank thread window', async function (assert) {
// This test requires full height of thread windows when they are open.
// (e.g. 400px)
- assert.expect(2);
+ assert.expect(3);
var parent = this.createParent({
data: this.data,
@@ -153,34 +154,37 @@ QUnit.test('fold blank thread window', function (assert) {
// Open blank thread window
parent.call('mail_service', 'openBlankThreadWindow');
+ await testUtils.nextTick();
+
+ assert.containsOnce(document.body, '.o_thread_window');
assert.strictEqual($('.o_thread_window').css('height'), HEIGHT_OPEN,
"blank thread window should be open");
if ($('.o_thread_window').css('height') !== HEIGHT_OPEN) {
console.warn('Assertion above may fail due to too narrow height of browser');
}
- testUtils.dom.click($('.o_thread_window_title'));
+ await testUtils.dom.click($('.o_thread_window_title'));
assert.strictEqual($('.o_thread_window').css('height'), HEIGHT_FOLDED,
- "blank thread window should be open");
+ "blank thread window should be folded");
parent.destroy();
testUtils.mock.unpatch(AbstractThreadWindow);
});
-QUnit.test('open new DM chat from blank thread window', function (assert) {
+QUnit.test('open new DM chat from blank thread window', async function (assert) {
assert.expect(6);
var done = assert.async();
var self = this;
- var selectDef = $.Deferred();
- var sourceDef = $.Deferred();
+ var selectDef = testUtils.makeTestPromise();
+ var sourceDef = testUtils.makeTestPromise();
this.patchAutocomplete({
selectDef: selectDef,
sourceDef: sourceDef,
});
- var def = $.Deferred();
+ var def = testUtils.makeTestPromise();
this.data['res.partner'] = {
fields: {},
@@ -193,13 +197,13 @@ QUnit.test('open new DM chat from blank thread window', function (assert) {
mockRPC: function (route, args) {
if (args.method === 'im_search') {
def.resolve();
- return $.when([
+ return Promise.resolve([
{ id: 1, name: 'DemoUser1' },
{ id: 2, name: 'DemoUser2', }
]);
}
if (args.method === 'channel_get_and_minimize') {
- return $.when({
+ return Promise.resolve({
channel_type: 'chat',
direct_partner: [{ id: args.args[0][0], name: 'DemoUser1', im_status: '' }],
id: 50,
@@ -213,19 +217,20 @@ QUnit.test('open new DM chat from blank thread window', function (assert) {
// open blank thread window
parent.call('mail_service', 'openBlankThreadWindow');
-
- $('.o_thread_search_input input').val("D").trigger('keydown');
-
- $.when(sourceDef, def).then(function () {
- assert.strictEqual($('.ui-menu-item a').length, 2,
- "should suggest 2 partners for DM");
- assert.strictEqual($('.ui-menu-item a').eq(0).text(), "DemoUser1",
- "first suggestion should be 'DemoUser1'");
- assert.strictEqual($('.ui-menu-item a').eq(1).text(), "DemoUser2",
- "second suggestion should be 'DemoUser2'");
-
- testUtils.dom.click($('.ui-menu-item a').eq(0));
- });
+ await testUtils.nextMicrotaskTick();
+ await testUtils.fields.editAndTrigger($('.o_thread_search_input input'), 'D', 'keydown');
+ await testUtils.nextTick();
+ await Promise.all([sourceDef, def]);
+ await testUtils.nextTick();
+ assert.strictEqual($('.ui-menu-item a').length, 2,
+ "should suggest 2 partners for DM");
+ assert.strictEqual($('.ui-menu-item a').eq(0).text(), "DemoUser1",
+ "first suggestion should be 'DemoUser1'");
+ assert.strictEqual($('.ui-menu-item a').eq(1).text(), "DemoUser2",
+ "second suggestion should be 'DemoUser2'");
+
+ await testUtils.dom.clickFirst($('.ui-menu-item a'),{allowInvisible:true});
+ await testUtils.nextTick();
selectDef.then(function () {
assert.strictEqual($('.o_thread_window').length, 1,
"should be a single window");
@@ -240,22 +245,22 @@ QUnit.test('open new DM chat from blank thread window', function (assert) {
});
});
-QUnit.test('open already detached DM chat from blank thread window', function (assert) {
+QUnit.test('open already detached DM chat from blank thread window', async function (assert) {
// when opening an already detach DM chat from the blank thread window,
// the blank thread window should disappear
assert.expect(6);
var done = assert.async();
var self = this;
- var selectDef = $.Deferred();
- var sourceDef = $.Deferred();
+ var selectDef = testUtils.makeTestPromise();
+ var sourceDef = testUtils.makeTestPromise();
this.patchAutocomplete({
selectDef: selectDef,
sourceDef: sourceDef,
});
- var def = $.Deferred();
+ var def = testUtils.makeTestPromise();
this.data['res.partner'] = {
fields: {},
@@ -275,7 +280,7 @@ QUnit.test('open already detached DM chat from blank thread window', function (a
mockRPC: function (route, args) {
if (args.method === 'im_search') {
def.resolve();
- return $.when([
+ return Promise.resolve([
{ id: 1, name: 'DemoUser1' },
]);
}
@@ -283,6 +288,7 @@ QUnit.test('open already detached DM chat from blank thread window', function (a
},
});
+ await testUtils.nextTick();
assert.strictEqual($('.o_thread_window').length, 1,
"should be a single window");
assert.strictEqual($('.o_thread_window_title').text().trim(), "DemoUser1",
@@ -292,15 +298,16 @@ QUnit.test('open already detached DM chat from blank thread window', function (a
// open blank thread window
parent.call('mail_service', 'openBlankThreadWindow');
-
+ await testUtils.nextMicrotaskTick();
assert.strictEqual($('.o_thread_window').length, 2,
"should have two thread windows open");
+ await testUtils.fields.editAndTrigger($('.o_thread_search_input input'), 'D', 'keydown');
- $('.o_thread_search_input input').val("D").trigger('keydown');
- $.when(sourceDef, def).then(function () {
- testUtils.dom.click($('.ui-menu-item a').eq(0));
- });
+ await Promise.all([sourceDef, def]);
+ await testUtils.nextTick();
+ await testUtils.dom.click($('.ui-menu-item a'),{allowInvisible:true});
+ await testUtils.nextTick();
selectDef.then(function () {
assert.strictEqual($('.o_thread_window').length, 1,
"should now have a single thread window open");
diff --git a/addons/mail/static/tests/thread_window/hidden_thread_window_tests.js b/addons/mail/static/tests/thread_window/hidden_thread_window_tests.js
index b87dbe0f794..691e37df362 100644
--- a/addons/mail/static/tests/thread_window/hidden_thread_window_tests.js
+++ b/addons/mail/static/tests/thread_window/hidden_thread_window_tests.js
@@ -48,12 +48,15 @@ QUnit.module('Hidden', {
};
},
afterEach: function () {
+ // remove thread window dropup appended by mail service
+ var $target = $(this.services.mail_service.prototype.THREAD_WINDOW_APPENDTO);
+ $target.find('.o_thread_window_dropdown').remove();
// reset thread window append to body
this.services.mail_service.prototype.THREAD_WINDOW_APPENDTO = 'body';
},
});
-QUnit.test('hidden thread windows dropdown when not enough horizontal space (version 1)', function (assert) {
+QUnit.test('hidden thread windows dropdown when not enough horizontal space (version 1)', async function (assert) {
// This test has hard-set global width, so that it does not depend on
// the width of the screen: at most 2 thread windows visible at the
// same time, and additional thread windows are in hidden while and
@@ -87,9 +90,10 @@ QUnit.test('hidden thread windows dropdown when not enough horizontal space (ver
data: this.data,
services: this.services,
});
-
+ await testUtils.nextTick();
parent.call('mail_service', 'getChannel', 0).detach();
parent.call('mail_service', 'getChannel', 1).detach();
+ await testUtils.nextTick();
var $visibleThreadWindows = $('.o_thread_window:not(.o_thread_window_dropdown, .o_hidden)');
@@ -106,6 +110,7 @@ QUnit.test('hidden thread windows dropdown when not enough horizontal space (ver
// detach a channel so that it exceeds available slots
parent.call('mail_service', 'getChannel', 2).detach();
+ await testUtils.nextTick();
// update list of visible thread windows
$visibleThreadWindows = $('.o_thread_window:not(.o_thread_window_dropdown, .o_hidden)');
@@ -131,7 +136,7 @@ QUnit.test('hidden thread windows dropdown when not enough horizontal space (ver
testUtils.mock.unpatch(this.services.mail_service);
});
-QUnit.test('hidden thread windows dropdown when not enough horizontal space (version 2)', function (assert) {
+QUnit.test('hidden thread windows dropdown when not enough horizontal space (version 2)', async function (assert) {
// This is almost the same test as the one before, except there are
// at most 3 thread windows visible, and 2 thread windows are visible
// when it shows the 'hidden thread window' button.
@@ -171,10 +176,11 @@ QUnit.test('hidden thread windows dropdown when not enough horizontal space (ver
data: this.data,
services: this.services,
});
-
+ await testUtils.nextTick();
parent.call('mail_service', 'getChannel', 0).detach();
parent.call('mail_service', 'getChannel', 1).detach();
parent.call('mail_service', 'getChannel', 2).detach();
+ await testUtils.nextTick();
var $visibleThreadWindows = $('.o_thread_window:not(.o_thread_window_dropdown, .o_hidden)');
@@ -193,6 +199,7 @@ QUnit.test('hidden thread windows dropdown when not enough horizontal space (ver
// detach a channel so that it exceeds available slots
parent.call('mail_service', 'getChannel', 3).detach();
+ await testUtils.nextTick();
// update list of visible thread windows
$visibleThreadWindows = $('.o_thread_window:not(.o_thread_window_dropdown, .o_hidden)');
diff --git a/addons/mail/static/tests/thread_window/moderation_thread_window_tests.js b/addons/mail/static/tests/thread_window/moderation_thread_window_tests.js
index b35405a2243..732a5fe7938 100644
--- a/addons/mail/static/tests/thread_window/moderation_thread_window_tests.js
+++ b/addons/mail/static/tests/thread_window/moderation_thread_window_tests.js
@@ -84,7 +84,7 @@ QUnit.module('Moderation', {
},
});
-QUnit.test('moderator: moderated channel with pending moderation message', function (assert) {
+QUnit.test('moderator: moderated channel with pending moderation message', async function (assert) {
assert.expect(5);
this.data.initMessaging = {
@@ -114,9 +114,10 @@ QUnit.test('moderator: moderated channel with pending moderation message', funct
data: this.data,
services: this.services,
});
-
+ await testUtils.nextTick();
// detach channel 1, so that it opens corresponding thread window.
parent.call('mail_service', 'getChannel', 1).detach();
+ await testUtils.nextTick();
assert.strictEqual($('.o_thread_message ').length, 1,
"should display a message in the thread window");
diff --git a/addons/mail/static/tests/thread_window/typing_thread_window_tests.js b/addons/mail/static/tests/thread_window/typing_thread_window_tests.js
index 549cfdb7184..be2bd4beec8 100644
--- a/addons/mail/static/tests/thread_window/typing_thread_window_tests.js
+++ b/addons/mail/static/tests/thread_window/typing_thread_window_tests.js
@@ -40,7 +40,7 @@ QUnit.module('Typing', {
* @param {integer} params.partnerID
* @param {Widget} params.widget a widget that can call the bus_service
*/
- this.simulateIsTyping = function (params) {
+ this.simulateIsTyping = async function (params) {
var typingData = {
info: 'typing_status',
partner_id: params.partnerID,
@@ -48,6 +48,7 @@ QUnit.module('Typing', {
};
var notification = [[false, 'mail.channel', params.channelID], typingData];
params.widget.call('bus_service', 'trigger', 'notification', [notification]);
+ await testUtils.nextMicrotaskTick();
};
this.createParent = function (params) {
@@ -72,7 +73,7 @@ QUnit.module('Typing', {
},
});
-QUnit.test('receive typing notification', function (assert) {
+QUnit.test('receive typing notification', async function (assert) {
assert.expect(4);
var parent = this.createParent({
@@ -82,22 +83,24 @@ QUnit.test('receive typing notification', function (assert) {
// when receiving an 'is typing' notification, fetch the list of
// members of this channel if we haven't done yet.
if (args.method === 'channel_fetch_listeners') {
- return $.when([
+ return Promise.resolve([
{ id: 42, name: "Someone" },
]);
}
return this._super.apply(this, arguments);
},
});
+ await testUtils.nextTick();
// detach channel 1, so that it opens corresponding thread window.
parent.call('mail_service', 'getChannel', 1).detach();
+ await testUtils.nextTick();
var $threadWindow = $('.o_thread_window');
assert.containsNone($threadWindow, '.o_mail_thread_typing_icon',
"should not display an icon that someone is typing something on this thread");
- this.simulateIsTyping({
+ await this.simulateIsTyping({
channelID: 1,
isTyping: true,
partnerID: 42,
@@ -110,7 +113,7 @@ QUnit.test('receive typing notification', function (assert) {
"Someone is typing...",
"should display someone is typing something on hover of this icon");
- this.simulateIsTyping({
+ await this.simulateIsTyping({
channelID: 1,
isTyping: false,
partnerID: 42,
diff --git a/addons/mail/static/tests/tools/debug_manager_tests.js b/addons/mail/static/tests/tools/debug_manager_tests.js
index 8b9312ca733..7671150f0d8 100644
--- a/addons/mail/static/tests/tools/debug_manager_tests.js
+++ b/addons/mail/static/tests/tools/debug_manager_tests.js
@@ -7,7 +7,7 @@ var createDebugManager = testUtils.createDebugManager;
QUnit.module('Mail DebugManager', {}, function () {
- QUnit.test("Manage Messages", function (assert) {
+ QUnit.test("Manage Messages", async function (assert) {
assert.expect(3);
var debugManager = createDebugManager({
@@ -47,15 +47,16 @@ QUnit.module('Mail DebugManager', {}, function () {
},
modelName: 'testModel',
};
- debugManager.update('action', action, view);
+ await testUtils.nextTick();
+ await debugManager.update('action', action, view);
var $messageMenu = debugManager.$('a[data-action=getMailMessages]');
assert.strictEqual($messageMenu.length, 1, "should have Manage Message menu item");
assert.strictEqual($messageMenu.text().trim(), "Manage Messages",
"should have correct menu item text");
- testUtils.dom.click(debugManager.$('> a')); // open dropdown
- testUtils.dom.click($messageMenu);
+ await testUtils.dom.click(debugManager.$('> a')); // open dropdown
+ await testUtils.dom.click($messageMenu);
debugManager.destroy();
});