Files
odoo_source/addons/im_support/static/tests/systray_tests.js
T
Alexandre Kühn f2302dfb27 [REF][FIX] mail, im_livechat: various improvements (JS)
This commit makes a lot of small improvements of the JS of mail and
related modules.

	A. Mail Manager
	---------------

		im_support:

		- [REF] Slightly more robust way to determine a support
		        message, so that it more reliably falls back on
		        default kind of message (i.e. support channel UUID
		        should be clearly set).

		mail:

		- [REF] Improved method names for readability purposes.
		        Some examples:

		        - `fetchFromServer` becomes `fetchMailStateFromServer`
		        - `_initialize{*}` becomes `_update{*}FromServer`
		        - `_isModerator` becomes `_isMyselfModerator`

		- [REF] Use 'template' pattern design to make Include on
				Mail Manager much more robust. In particular,
				the flow is always as follow:

					1. Initialize internal state.
					2. Listen on buses.
					3. Fetch mail data from server.

		- [REF] Improved workflow for thread window workflow
		        (Shorter & more readable).

	B. Mail Tests
	-------------

		- [REF] Thread Window Tests crashes with clean message when
		        there are some thread windows open before running the
		        tests.

	C. (Model) Message
	------------------

		- [REF] Improved method names for readability purposes
				(e.g. `isAuthor` becomes `isMyselfAuthor`).

	D. (Model) Thread
	-----------------

		- [REF] Improved `init` parameters on each kind of thread.
		- [REF] 'Thread With Cache' has been renamed to 'Searchable
		        Thread': it embraces all kinds of threads that can
		        be used with the search view.
		- [REF] 'DM' has been renamed to 'DM Chat' (for clarity).
		- [IMP] New Livechat model in the backend.
		- [REF] No more direct instances of the Channel class: public
		        and private channels are now 'Multi-User' channels,
		        while DM Chat and Livechat are 'Two-User' channels:

		        This change has been made so that instances of classes
		        always have direct classes as "leaf" in the Class
		        modeling. It eases making changes to a certain model
		        without being too constrained by another model.

		- [REF] As a consequence of above changed, the method `isChat`
		        has been renamed to `isTwoUserThread`.

		        This is to avoid confusion with the terminology
		        'chat', which is more like a shortcut for 'quick real-
		        time conversation'. In other words, the property of
		        'chat' depends of the way to interact on a thread, not
		        of the intrinsic type of the thread.

		        Still, some parts have kept the terminology 'chat',
		        such as in the systray messagin menu.

		- [IMP] Added `message_added` and `message_posted` hooks,
		        which may be useful to easily hook on those events.

	E. Thread Widget
	----------------

		- [REF] Now uses a `mail.model.AbstractThread` for the
		        rendering of a thread, instead of a list of
		        `{mail.model.AbstractMessage}`.
		- [FIX] Stick thread scroll height to bottom on new rendering,
		        if it was previously at the bottom of the thread.
		- [REF] Option ORDER has its meaning changed: it now refers
		        to the chronological order of messages in the thread,
		        in which DESC means 'from top to bottom', while ASC
		        means 'from bottom to top'.
		- [REF] Improved doc on templates, in particular with the
	            option `ORDER`.

	F. Thread Window
	----------------

		- [REF] Moved more logic to thread windows, which were
		        previously in Mail Window Manager.
		- [REF] Now hides the thread widget attribute. So instead of
		        `threadWindow.threadWidget.isAtBottom()`, it uses
		        `threadWindow.isAtBottom()`.
		- [FIX] New received messages when not having focus on Odoo
		        tab should always make the corresponding thread
		        windows "passive" (i.e. windows that keep threads
		        unread until click on them).
		- [FIX] Blank thread window (i.e. 'New message' TW) correctly
		        opens Discuss with 'Inbox' when clicking on 'Expand'
		        Button in the title
		- [FIX] Do not display the composer for channels with property
		        'mass-mailing' set in thread windows.

	G. (Website) Livechat
	---------------------

		- [REF] Some `trigger` have been turned into `trigger_up`.
		- [REF] Some logic has been moved to models (e.g.
		        `{im_livechat.model.WebsiteLivechat}`), from
		        `{im_livechat.im_livechat.LivechatButton}`.
		- [FIX] New messages should be received in real-time. The
		        longpolling was broken with a recent refactoring on
		        bus service (6448420c5d).
2018-08-13 14:17:27 +02:00

342 lines
12 KiB
JavaScript

odoo.define('im_support.systray_tests', function (require) {
"use strict";
var imSupportTestUtils = require('im_support.test_utils');
var mailTestUtils = require('mail.testUtils');
var MessagingMenu = require('mail.systray.MessagingMenu');
var testUtils = require('web.test_utils');
var addMockSupportEnvironment = imSupportTestUtils.addMockSupportEnvironment;
QUnit.module('im_support', {}, function () {
QUnit.module('systray', {
beforeEach: function () {
this.data = {
'mail.message': {
fields: {},
},
};
this.services = mailTestUtils.getMailServices();
this.supportParams = {
db_uuid: 'some_uuid',
support_token: 'ABCDEFGHIJ',
support_origin: 'something.com',
};
},
});
QUnit.test('messaging menu displays the Support channel', function (assert) {
assert.expect(1);
var messagingMenu = new MessagingMenu();
addMockSupportEnvironment(messagingMenu, {
data: this.data,
services: this.services,
session: this.supportParams,
});
messagingMenu.appendTo($('#qunit-fixture'));
messagingMenu.$('.dropdown-toggle').click();
assert.strictEqual(messagingMenu.$('.o_mail_systray_dropdown_bottom .o_mail_preview[data-preview-id=SupportChannel]').length,
1, "should display the Support channel");
messagingMenu.destroy();
});
QUnit.test('clicking on Support channel: channel not available', function (assert) {
assert.expect(9);
var messagingMenu = new MessagingMenu();
addMockSupportEnvironment(messagingMenu, {
data: this.data,
mockRPC: function (route, args) {
if (!_.string.endsWith(route, '.png')) { // ignore images
assert.step(args.method || route);
}
return this._super.apply(this, arguments);
},
mockSupportRPC: function (route) {
assert.step('cors: ' + route);
if (route === '/odoo_im_support/get_support_channel') {
return this._super.apply(this, arguments).then(function (supportChannel) {
supportChannel.available = false;
return supportChannel;
});
}
return this._super.apply(this, arguments);
},
services: this.services,
session: this.supportParams,
});
messagingMenu.appendTo($('#qunit-fixture'));
messagingMenu.$('.dropdown-toggle').click();
assert.strictEqual(messagingMenu.$('.o_mail_systray_dropdown_bottom .o_mail_preview[data-preview-id=SupportChannel]').length,
1, "should display the Support channel");
messagingMenu.$('.o_mail_preview[data-preview-id=SupportChannel]').click();
assert.strictEqual($('.o_thread_window').length, 1,
"should have open a chat window");
assert.strictEqual($('.o_thread_window .o_thread_window_title').text().trim(), 'Support (offline)',
"should display the offline status in the header");
assert.strictEqual($('.o_thread_window .o_composer_input').length, 0,
"should have no composer");
assert.verifySteps([
'/mail/init_messaging',
'message_fetch',
'cors: /odoo_im_support/get_support_channel',
'cors: /odoo_im_support/fetch_messages',
]);
messagingMenu.destroy();
});
QUnit.test('clicking on Support channel: channel available', function (assert) {
assert.expect(9);
var messagingMenu = new MessagingMenu();
addMockSupportEnvironment(messagingMenu, {
data: this.data,
mockRPC: function (route, args) {
if (!_.string.endsWith(route, '.png')) { // ignore images
assert.step(args.method || route);
}
return this._super.apply(this, arguments);
},
mockSupportRPC: function (route) {
if (route.split('/')[1] === 'odoo_im_support') {
assert.step('cors: ' + route);
}
return this._super.apply(this, arguments);
},
services: this.services,
session: this.supportParams,
});
messagingMenu.appendTo($('#qunit-fixture'));
messagingMenu.$('.dropdown-toggle').click();
assert.strictEqual(messagingMenu.$('.o_mail_systray_dropdown_bottom .o_mail_preview[data-preview-id=SupportChannel]').length,
1, "should display the Support channel");
messagingMenu.$('.o_mail_preview[data-preview-id=SupportChannel]').click();
assert.strictEqual($('.o_thread_window').length, 1,
"should have open a chat window");
assert.strictEqual($('.o_thread_window .o_thread_window_title').text().trim(), 'Support',
"should display the correct thread title");
assert.strictEqual($('.o_thread_window .o_composer_input').length, 1,
"should have a composer");
assert.verifySteps([
'/mail/init_messaging',
'message_fetch',
'cors: /odoo_im_support/get_support_channel',
'cors: /odoo_im_support/fetch_messages',
]);
messagingMenu.destroy();
});
QUnit.test('post messages in Support channel', function (assert) {
assert.expect(8);
var messagingMenu = new MessagingMenu();
addMockSupportEnvironment(messagingMenu, {
data: this.data,
mockRPC: function (route, args) {
if (!_.string.endsWith(route, '.png')) { // ignore images
assert.step(args.method || route);
}
return this._super.apply(this, arguments);
},
mockSupportRPC: function (route) {
if (route.split('/')[1] === 'odoo_im_support') {
assert.step('cors: ' + route);
}
return this._super.apply(this, arguments);
},
services: this.services,
session: this.supportParams,
});
messagingMenu.appendTo($('#qunit-fixture'));
messagingMenu.$('.dropdown-toggle').click();
assert.strictEqual(messagingMenu.$('.o_mail_systray_dropdown_bottom .o_mail_preview[data-preview-id=SupportChannel]').length,
1, "should display the Support channel");
messagingMenu.$('.o_mail_preview[data-preview-id=SupportChannel]').click();
assert.strictEqual($('.o_thread_window .o_composer_input').length, 1,
"should have a composer");
$('.o_thread_window .o_composer_input .o_input')
.val('some message')
.trigger($.Event('keydown', {which: $.ui.keyCode.ENTER}));
assert.verifySteps([
'/mail/init_messaging',
'message_fetch',
'cors: /odoo_im_support/get_support_channel',
'cors: /odoo_im_support/fetch_messages',
'cors: /odoo_im_support/chat_post',
]);
messagingMenu.destroy();
});
QUnit.test('fold Support channel', function (assert) {
assert.expect(11);
var messagingMenu = new MessagingMenu();
addMockSupportEnvironment(messagingMenu, {
data: this.data,
mockRPC: function (route, args) {
if (!_.string.endsWith(route, '.png')) { // ignore images
assert.step(args.method || route);
}
return this._super.apply(this, arguments);
},
mockSupportRPC: function (route) {
if (route.split('/')[1] === 'odoo_im_support') {
assert.step('cors: ' + route);
}
return this._super.apply(this, arguments);
},
services: this.services,
session: this.supportParams,
});
testUtils.intercept(messagingMenu, 'call_service', function (ev) {
if (ev.data.service === 'local_storage') {
assert.step('LocalStorage: ' + ev.data.method + ' ' + ev.data.args);
}
}, true);
messagingMenu.appendTo($('#qunit-fixture'));
messagingMenu.$('.dropdown-toggle').click();
assert.strictEqual(messagingMenu.$('.o_mail_systray_dropdown_bottom .o_mail_preview[data-preview-id=SupportChannel]').length,
1, "should display the Support channel");
messagingMenu.$('.o_mail_preview[data-preview-id=SupportChannel]').click();
assert.strictEqual($('.o_thread_window').length, 1,
"should have open a chat window");
// fold, re-open and close channel
$('.o_thread_window .o_thread_window_title').click();
$('.o_thread_window .o_thread_window_title').click();
$('.o_thread_window .o_thread_window_close').click();
assert.verifySteps([
'/mail/init_messaging',
'message_fetch',
'cors: /odoo_im_support/get_support_channel',
'LocalStorage: setItem im_support.channel_state,open',
'cors: /odoo_im_support/fetch_messages',
'LocalStorage: setItem im_support.channel_state,folded',
'LocalStorage: setItem im_support.channel_state,open',
'LocalStorage: setItem im_support.channel_state,closed',
]);
messagingMenu.destroy();
});
QUnit.test('restore Support channel if necessary', function (assert) {
assert.expect(5);
var messagingMenu = new MessagingMenu();
addMockSupportEnvironment(messagingMenu, {
data: this.data,
enableSupportPoll: true,
mockRPC: function (route, args) {
if (!_.string.endsWith(route, '.png')) { // ignore images
assert.step(args.method || route);
}
return this._super.apply(this, arguments);
},
mockSupportRPC: function (route) {
if (route.split('/')[1] === 'odoo_im_support') {
assert.step('cors: ' + route);
}
return this._super.apply(this, arguments);
},
services: this.services,
session: this.supportParams,
});
messagingMenu.appendTo($('#qunit-fixture'));
assert.strictEqual($('.o_thread_window').length, 1,
"should have open a chat window");
assert.verifySteps([
'/mail/init_messaging',
'cors: /odoo_im_support/get_support_channel',
'cors: /odoo_im_support/fetch_messages',
]);
messagingMenu.destroy();
});
QUnit.test('receive messages in the Support channel', function (assert) {
assert.expect(10);
var supportChannelID;
var messagingMenu = new MessagingMenu();
addMockSupportEnvironment(messagingMenu, {
data: this.data,
enableSupportPoll: true,
mockRPC: function (route, args) {
if (!_.string.endsWith(route, '.png')) { // ignore images
assert.step(args.method || route);
}
return this._super.apply(this, arguments);
},
mockSupportRPC: function (route) {
if (route.split('/')[1] === 'odoo_im_support') {
assert.step('cors: ' + route);
}
return this._super.apply(this, arguments);
},
services: this.services,
session: this.supportParams,
});
messagingMenu.appendTo($('#qunit-fixture'));
assert.strictEqual($('.o_thread_window').length, 1,
"should have open a chat window");
assert.strictEqual($('.o_thread_window .o_thread_message').length, 0,
"there should be no message in the thread");
// simulate an incoming message on the supportBus
var data = {
author_id: [42, 'An operator'],
body: 'A message',
channel_ids: [supportChannelID],
};
var notification = [[false, 'mail.channel', 1], data];
messagingMenu.call('support_bus_service', 'trigger', 'notification', [notification]);
assert.strictEqual($('.o_thread_window .o_thread_message').length, 1,
"there should be a new message in the thread");
assert.strictEqual($('.o_thread_window .o_thread_message .o_thread_author ').text().trim(),
'An operator', "should correctly display the author");
assert.strictEqual($('.o_thread_window .o_thread_message .o_thread_message_avatar').attr('data-src'),
'/mail/static/src/img/odoo_o.png', "should have correct avatar");
assert.strictEqual($('.o_thread_window .o_thread_message .o_thread_message_content ').text().trim(),
'A message', "message is correct");
assert.verifySteps([
'/mail/init_messaging',
'cors: /odoo_im_support/get_support_channel',
'cors: /odoo_im_support/fetch_messages',
]);
messagingMenu.destroy();
});
});
});