[IMP] website_livechat : add various tests on livechat and visitors

Adds Python tests and javascripts tours on livechat (website and visitor
integration). Because breaking livechat every two days in rush periods
(or even not) is getting quite annoying.

Those tests are testing :

- The client side flow (open livechat, send messages,
  send rating and close the livechat session)
- The channel and message author naming, visitor page view history
- Chat request flow (complete chat request flow, open empty operator's
  chat request and cancel due to visitor's new chat session)

Task ID : 2079087
PR #40052

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
David Beguin
2020-03-17 12:21:48 +00:00
parent 69b1e1a052
commit 190dab8144
15 changed files with 658 additions and 3 deletions
@@ -184,9 +184,9 @@ class ImLivechatChannel(models.Model):
FROM mail_channel c
LEFT OUTER JOIN mail_message_mail_channel_rel r ON c.id = r.mail_channel_id
LEFT OUTER JOIN mail_message m ON r.mail_message_id = m.id
WHERE m.create_date > ((now() at time zone 'UTC') - interval '30 minutes')
AND c.channel_type = 'livechat'
WHERE c.channel_type = 'livechat'
AND c.livechat_operator_id in %s
AND m.create_date > ((now() at time zone 'UTC') - interval '30 minutes')
GROUP BY c.livechat_operator_id
ORDER BY COUNT(DISTINCT c.id) asc""", (tuple(operators.mapped('partner_id').ids),))
active_channels = self.env.cr.dictfetchall()
@@ -482,7 +482,7 @@ var Feedback = Widget.extend({
if (reason) {
content += " \n" + reason;
}
self.trigger('send_message', { content: content });
self.trigger('send_message', { content: content, isFeedback: true });
});
},
/**
+1
View File
@@ -12,6 +12,7 @@ Allow website visitors to chat with the collaborators. This module also brings a
'application': False,
'auto_install': True,
'data': [
'views/assets.xml',
'views/website_livechat.xml',
'views/res_config_settings_views.xml',
'views/website_livechat_view.xml',
@@ -1,2 +1,3 @@
# -*- coding: utf-8 -*-
from . import main
from . import test
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.http import Controller, request, route
class TestBusController(Controller):
"""
This controller is only useful for test purpose. Bus is unavailable in test mode, but there is no way to know,
at client side, if we are running in test mode or not. This route can be called while running tours to mock
some behaviour in function of the test mode status (activated or not).
E.g. : To test the livechat and to check there is no duplicates in message displayed in the chatter,
in test mode, we need to mock a 'message added' notification that is normally triggered by the bus.
In Normal mode, the bus triggers itself the notification.
"""
@route('/bus/test_mode_activated', type="json", auth="public")
def is_test_mode_activated(self):
return request.registry.in_test_mode()
@@ -15,6 +15,7 @@ class ImLivechatChannel(models.Model):
if not user_id:
mail_channel_vals['anonymous_name'] = visitor_sudo.display_name + (' (%s)' % visitor_sudo.country_id.name if visitor_sudo.country_id else '')
# As chat requested by the visitor, delete the chat requested by an operator if any to avoid conflicts between two flows
# TODO DBE : Move this into the proper method (open or init mail channel)
chat_request_channel = self.env['mail.channel'].sudo().search([('livechat_visitor_id', '=', visitor_sudo.id), ('livechat_active', '=', True)])
for mail_channel in chat_request_channel:
mail_channel._close_livechat_session(cancel=True, speaking_with=operator.name)
@@ -0,0 +1,165 @@
odoo.define('website_livechat.tour_common', function(require) {
'use strict';
var session = require('web.session');
var LivechatButton = require('im_livechat.im_livechat').LivechatButton;
/**
* Alter this method for test purposes.
*
* Fake the notification after sending message
* As bus is not available, it's necessary to add the message in the chatter + in livechat.messages
*
* Add a class to the chatter window after sendFeedback is done
* to force the test to wait until feedback is really done
* (to check afterwards if the livechat session is set to inactive)
*
* Note : this asset is loaded for tests only (rpc call done only during tests)
*/
LivechatButton.include({
_sendMessage: function (message) {
var self = this;
return this._super.apply(this, arguments).then(function () {
if (message.isFeedback) {
$('div.o_thread_window_header').addClass('feedback_sent');
}
else {
session.rpc('/bus/test_mode_activated', {}).then(function (in_test_mode) {
if (in_test_mode) {
var notification = [
self._livechat.getUUID(),
{
'id': -1,
'author_id': [0, 'Website Visitor Test'],
'email_from': 'Website Visitor Test',
'body': '<p>' + message.content + '</p>',
'is_discussion': true,
'subtype_id': [1, "Discussions"],
'date': moment().format('YYYY-MM-DD HH:mm:ss'),
}
]
self._handleNotification(notification);
}
});
}
});
},
});
/*******************************
* Common Steps
*******************************/
var startStep = [{
content: "click on livechat widget",
trigger: "div.o_livechat_button"
}, {
content: "Say hello!",
trigger: "input.o_composer_text_field",
run: "text Hello Sir!"
}, {
content: "Send the message",
trigger: "input.o_composer_text_field",
run: function() {
$('input.o_composer_text_field').trigger($.Event('keydown', {which: $.ui.keyCode.ENTER}));
}
}, {
content: "Verify your message has been typed",
trigger: "div.o_thread_message_content>p:contains('Hello Sir!')"
}, {
content: "Verify there is no duplicates",
trigger: "body",
run: function () {
if ($("div.o_thread_message_content p:contains('Hello Sir!')").length === 1) {
$('body').addClass('no_duplicated_message');
}
}
}, {
content: "Is your message correctly sent ?",
trigger: 'body.no_duplicated_message'
}];
var endDiscussionStep = [{
content: "Close the chatter",
trigger: "a.o_thread_window_close",
run: function() {
$('a.o_thread_window_close').click();
}
}];
var feedbackStep = [{
content: "Type a feedback",
trigger: "div.o_livechat_rating_reason > textarea",
run: "text ;-) This was really helpful. Thanks ;-)!"
}, {
content: "Send the feedback",
trigger: "input[type='button'].o_rating_submit_button",
}, {
content: "Check if feedback has been sent",
trigger: "div.o_thread_window_header.feedback_sent",
}, {
content: "Thanks for your feedback",
trigger: "div.o_livechat_rating_box:has(div:contains('Thank you for your feedback'))",
}];
var transcriptStep = [{
content: "Type your email",
trigger: "input[id='o_email']",
run: "text deboul@onner.com"
}, {
content: "Send the conversation to your email address",
trigger: "button.o_email_chat_button",
}, {
content: "Type your email",
trigger: "div.o_livechat_email:has(strong:contains('Conversation Sent'))",
}];
var closeStep = [{
content: "Close the conversation with the x button",
trigger: "a.o_thread_window_close",
}, {
content: "Check that the chat window is closed",
trigger: 'body',
run: function () {
if ($('div.o_livechat_button').length === 1 && !$('div.o_livechat_button').is(':visible')) {
$('body').addClass('tour_success');
}
}
}, {
content: "Is the Test succeded ?",
trigger: 'body.tour_success'
}];
var goodRatingStep = [{
content: "Send Good Rating",
trigger: "div.o_livechat_rating_choices > img[data-value=10]",
}, {
content: "Check if feedback has been sent",
trigger: "div.o_thread_window_header.feedback_sent",
}, {
content: "Thanks for your feedback",
trigger: "div.o_livechat_rating_box:has(div:contains('Thank you for your feedback'))"
}];
var okRatingStep = [{
content: "Send ok Rating",
trigger: "div.o_livechat_rating_choices > img[data-value=5]",
}];
var sadRatingStep = [{
content: "Send bad Rating",
trigger: "div.o_livechat_rating_choices > img[data-value=1]",
}];
return {
'startStep': startStep,
'endDiscussionStep': endDiscussionStep,
'transcriptStep': transcriptStep,
'feedbackStep': feedbackStep,
'closeStep': closeStep,
'goodRatingStep': goodRatingStep,
'okRatingStep': okRatingStep,
'sadRatingStep': sadRatingStep,
};
});
@@ -0,0 +1,38 @@
odoo.define('website_livechat.tour', function(require) {
'use strict';
var commonSteps = require("website_livechat.tour_common");
var tour = require("web_tour.tour");
tour.register('website_livechat_complete_flow_tour', {
test: true,
url: '/',
}, [].concat(commonSteps.startStep, commonSteps.endDiscussionStep, commonSteps.okRatingStep, commonSteps.feedbackStep, commonSteps.transcriptStep, commonSteps.closeStep));
tour.register('website_livechat_happy_rating_tour', {
test: true,
url: '/',
}, [].concat(commonSteps.startStep, commonSteps.endDiscussionStep, commonSteps.goodRatingStep));
tour.register('website_livechat_ok_rating_tour', {
test: true,
url: '/',
}, [].concat(commonSteps.startStep, commonSteps.endDiscussionStep, commonSteps.okRatingStep, commonSteps.feedbackStep));
tour.register('website_livechat_sad_rating_tour', {
test: true,
url: '/',
}, [].concat(commonSteps.startStep, commonSteps.endDiscussionStep, commonSteps.sadRatingStep, commonSteps.feedbackStep));
tour.register('website_livechat_no_rating_tour', {
test: true,
url: '/',
}, [].concat(commonSteps.startStep, commonSteps.endDiscussionStep, commonSteps.transcriptStep, commonSteps.closeStep));
tour.register('website_livechat_no_rating_no_close_tour', {
test: true,
url: '/',
}, [].concat(commonSteps.startStep));
return {};
});
@@ -0,0 +1,46 @@
odoo.define('website_livechat.chat_request_tour', function(require) {
'use strict';
var commonSteps = require("website_livechat.tour_common");
var tour = require("web_tour.tour");
var stepWithChatRequestStep = [{
content: "Answer the chat request!",
trigger: "input.o_composer_text_field",
run: "text Hi ! What a coincidence! I need your help indeed."
}, {
content: "Send the message",
trigger: "input.o_composer_text_field",
run: function() {
$('input.o_composer_text_field').trigger($.Event('keydown', {which: $.ui.keyCode.ENTER}));
}
}, {
content: "Verify your message has been typed",
trigger: "div.o_thread_message_content>p:contains('Hi ! What a coincidence! I need your help indeed.')"
}, {
content: "Verify there is no duplicates",
trigger: "body",
run: function () {
if ($("div.o_thread_message_content p:contains('Hi ! What a coincidence! I need your help indeed.')").length === 1) {
$('body').addClass('no_duplicated_message');
}
}
}, {
content: "Is your message correctly sent ?",
trigger: 'body.no_duplicated_message'
}];
tour.register('website_livechat_chat_request_part_1_no_close_tour', {
test: true,
url: '/',
}, [].concat(stepWithChatRequestStep));
tour.register('website_livechat_chat_request_part_2_end_session_tour', {
test: true,
url: '/',
}, [].concat(commonSteps.endDiscussionStep, commonSteps.okRatingStep, commonSteps.feedbackStep, commonSteps.transcriptStep, commonSteps.closeStep));
return {};
});
@@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
from . import common
from . import test_ui
from . import test_livechat_basic_flow
from . import test_livechat_request
+87
View File
@@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, tests
class TestLivechatCommon(tests.TransactionCase):
def setUp(self):
super(TestLivechatCommon, self).setUp()
self.base_datetime = fields.Datetime.from_string("2019-11-11 21:30:00")
self.operator = self.env['res.users'].create({
'name': 'Operator Michel',
'login': 'operator',
'email': 'operator@example.com',
'password': "ideboulonate",
'livechat_username': 'El Deboulonnator',
})
self.livechat_channel = self.env['im_livechat.channel'].create({
'name': 'The basic channel',
'user_ids': [(6, 0, [self.operator.id])]
})
self.max_sessions_per_operator = 5
visitor_vals = {
'lang_id': self.env.ref('base.lang_en').id,
'country_id': self.env.ref('base.be').id,
'website_id': self.env.ref('website.default_website').id,
}
self.visitors = self.env['website.visitor'].create([{
'lang_id': self.env.ref('base.lang_en').id,
'country_id': self.env.ref('base.de').id,
'website_id': self.env.ref('website.default_website').id,
'partner_id': self.env.ref('base.user_demo').partner_id.id,
}] + [visitor_vals]*self.max_sessions_per_operator)
self.visitor_demo, self.visitor = self.visitors[0], self.visitors[1]
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
self.open_chat_url = base_url + "/im_livechat/get_session"
self.open_chat_params = {'params': {
'channel_id': self.livechat_channel.id,
'anonymous_name': "Wrong Name"
}}
self.send_feedback_url = base_url + "/im_livechat/feedback"
self.leave_session_url = base_url + "/im_livechat/visitor_leave_session"
# override the get_available_users to return only Michel as available
operators = self.operator
def get_available_users(self):
return operators
self.patch(type(self.env['im_livechat.channel']), '_get_available_users', get_available_users)
# override the _get_visitor_from_request to return self.visitor
self.target_visitor = self.visitor
def get_visitor_from_request(self_mock, **kwargs):
return self.target_visitor
self.patch(type(self.env['website.visitor']), '_get_visitor_from_request', get_visitor_from_request)
def _send_message(self, channel, email_from, body, author_id=False):
# As bus is unavailable in test mode, we cannot call /mail/chat_post route to post a message.
# Instead, we post directly the message on the given channel.
channel.with_context(mail_create_nosubscribe=True) \
.message_post(author_id=author_id, email_from=email_from, body=body,
message_type='comment', subtype_id=self.env.ref('mail.mt_comment').id)
def _send_rating(self, channel, visitor, rating_value, reason=False):
channel_messages_count = len(channel.message_ids)
rating_to_emoji = {1: "😞", 5: "😐", 10: "😊"}
self.opener.post(url=self.send_feedback_url, json={'params': {
'uuid': channel.uuid,
'rate': rating_value,
'reason': reason,
}})
res_model_id = self.env['ir.model'].sudo().search([('model', '=', channel._name)], limit=1).id
rating = self.env['rating.rating'].search([('res_id', '=', channel.id), ('res_model_id', '=', res_model_id)])
self.assertEqual(rating.rating, rating_value, "The rating is not correct.")
message = "Rating: %s" % rating_to_emoji[rating_value]
if reason:
message += " \n%s" % reason
self._send_message(channel, visitor.display_name, message, author_id=False)
self.assertEqual(len(channel.message_ids), channel_messages_count + 1)
@@ -0,0 +1,113 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import datetime
from odoo import tests, _
from odoo.addons.website_livechat.tests.common import TestLivechatCommon
@tests.tagged('post_install', '-at_install')
class TestLivechatBasicFlowHttpCase(tests.HttpCase, TestLivechatCommon):
def test_visitor_banner_history(self):
# create visitor history
self.env['website.track'].create([{
'page_id': self.env.ref('website.homepage_page').id,
'visitor_id': self.visitor.id,
'visit_datetime': self.base_datetime,
}, {
'page_id': self.env.ref('website.contactus_page').id,
'visitor_id': self.visitor.id,
'visit_datetime': self.base_datetime - datetime.timedelta(minutes=10),
}, {
'page_id': self.env.ref('website.aboutus_page').id,
'visitor_id': self.visitor.id,
'visit_datetime': self.base_datetime - datetime.timedelta(minutes=20),
}, {
'page_id': self.env.ref('website.contactus_page').id,
'visitor_id': self.visitor.id,
'visit_datetime': self.base_datetime - datetime.timedelta(minutes=30),
}])
handmade_history = "%s (21:10) → %s (21:20) → %s (21:30)" % (
self.env.ref('website.aboutus_page').name,
self.env.ref('website.contactus_page').name,
self.env.ref('website.homepage_page').name
)
history = self.env['mail.channel']._get_visitor_history(self.visitor)
self.assertEqual(history, handmade_history)
def test_livechat_username(self):
# Open a new live chat
res = self.opener.post(url=self.open_chat_url, json=self.open_chat_params)
self.assertEqual(res.status_code, 200)
channel_1 = self.env['mail.channel'].search([('livechat_visitor_id', '=', self.visitor.id), ('livechat_active', '=', True)], limit=1)
# Check Channel naming
self.assertEqual(channel_1.name, "%s, %s" % (self.visitor.display_name, self.operator.livechat_username))
channel_1.unlink()
# Remove livechat_username
self.operator.livechat_username = False
# Open a new live chat
res = self.opener.post(url=self.open_chat_url, json=self.open_chat_params)
self.assertEqual(res.status_code, 200)
channel_2 = self.env['mail.channel'].search([('livechat_visitor_id', '=', self.visitor.id), ('livechat_active', '=', True)], limit=1)
# Check Channel naming
self.assertEqual(channel_2.name, "%s, %s" % (self.visitor.display_name, self.operator.name))
def test_basic_flow_with_rating(self):
channel = self._common_basic_flow()
self._send_rating(channel, self.visitor, 5, "This deboulonnage was fine but not topitop.")
channel._close_livechat_session()
self.assertEqual(len(channel.message_ids), 4)
self.assertEqual(channel.message_ids[0].author_id, self.env.ref('base.partner_root'), "Odoobot must be the sender of the 'has left the conversation' message.")
self.assertEqual(channel.message_ids[0].body, "<p>%s has left the conversation.</p>" % self.visitor.display_name)
self.assertEqual(channel.livechat_active, False, "The livechat session must be inactive as the visitor sent his feedback.")
def test_basic_flow_without_rating(self):
channel = self._common_basic_flow()
# has left the conversation
channel._close_livechat_session()
self.assertEqual(len(channel.message_ids), 3)
self.assertEqual(channel.message_ids[0].author_id, self.env.ref('base.partner_root'), "Odoobot must be the author the message.")
self.assertEqual(channel.message_ids[0].body, "<p>%s has left the conversation.</p>" % self.visitor.display_name)
self.assertEqual(channel.livechat_active, False, "The livechat session must be inactive since visitor has left the conversation.")
def _common_basic_flow(self):
# Open a new live chat
res = self.opener.post(url=self.open_chat_url, json=self.open_chat_params)
self.assertEqual(res.status_code, 200)
channel = self.env['mail.channel'].search([('livechat_visitor_id', '=', self.visitor.id), ('livechat_active', '=', True)], limit=1)
# Check Channel and Visitor naming
self.assertEqual(self.visitor.display_name, "%s #%s" % (_("Website Visitor"), self.visitor.id))
self.assertEqual(channel.name, "%s, %s" % (self.visitor.display_name, self.operator.livechat_username))
# Post Message from visitor
self._send_message(channel, self.visitor.display_name, "Message from Visitor")
self.assertEqual(len(channel.message_ids), 1)
self.assertEqual(channel.message_ids[0].author_id.id, False, "The author of the message is not a partner.")
self.assertEqual(channel.message_ids[0].email_from, self.visitor.display_name, "The sender's email should be the visitor's email.")
self.assertEqual(channel.message_ids[0].body, "<p>Message from Visitor</p>")
self.assertEqual(channel.livechat_active, True, "The livechat session must be active as the visitor did not left the conversation yet.")
# Post message from operator
self._send_message(channel, self.operator.email, "Message from Operator", author_id=self.operator.partner_id.id)
self.assertEqual(len(channel.message_ids), 2)
self.assertEqual(channel.message_ids[0].author_id, self.operator.partner_id, "The author of the message should be the operator.")
self.assertEqual(channel.message_ids[0].email_from, self.operator.email, "The sender's email should be the operator's email.")
self.assertEqual(channel.message_ids[0].body, "<p>Message from Operator</p>")
self.assertEqual(channel.livechat_active, True, "The livechat session must be active as the visitor did not left the conversation yet.")
return channel
@@ -0,0 +1,79 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import tests
from odoo.addons.website_livechat.tests.common import TestLivechatCommon
@tests.tagged('post_install', '-at_install')
class TestLivechatRequestHttpCase(tests.HttpCase, TestLivechatCommon):
def test_livechat_request_complete_flow(self):
self._clean_livechat_sessions()
# Send first chat request - Open chat from operator side
channel_1 = self._common_chat_request_flow()
# Visitor Rates the conversation (Good)
self._send_rating(channel_1, self.visitor, 10)
# Operator Re-Send a chat request
channel_2 = self._common_chat_request_flow()
# Visitor Rates the conversation (Bad)
self._send_rating(channel_2, self.visitor, 1, "Stop bothering me! I hate you </3 !")
def test_cancel_chat_request_on_visitor_demand(self):
self._clean_livechat_sessions()
self.operator_b = self.env['res.users'].create({
'name': 'Operator Marc',
'login': 'operator_b',
'email': 'operatormarc@example.com',
'password': "operatormarc",
'livechat_username': "Marco'r El",
})
# Open Chat Request
self.visitor.with_user(self.operator_b).action_send_chat_request()
chat_request = self.env['mail.channel'].search([('livechat_visitor_id', '=', self.visitor.id), ('livechat_active', '=', True)])
self.assertEqual(chat_request.livechat_operator_id, self.operator_b.partner_id, "Operator for active livechat session must be Operator Marc")
# Click on livechatbutton at client side
res = self.opener.post(url=self.open_chat_url, json=self.open_chat_params)
self.assertEqual(res.status_code, 200)
channel = self.env['mail.channel'].search([('livechat_visitor_id', '=', self.visitor.id),
('livechat_active', '=', True)])
# Check that the chat request has been canceled.
chat_request.invalidate_cache()
self.assertEqual(chat_request.livechat_active, False, "The livechat request must be inactive as the visitor started himself a livechat session.")
self.assertEqual(len(channel), 1)
self.assertEqual(channel.livechat_operator_id, self.operator.partner_id, "Operator for active livechat session must be Michel Operator")
def _common_chat_request_flow(self):
self.visitor.with_user(self.operator).action_send_chat_request()
channel = self.env['mail.channel'].search([('livechat_visitor_id', '=', self.visitor.id), ('livechat_active', '=', True)])
self.assertEqual(len(channel), 1)
self.assertEqual(channel.livechat_operator_id, self.operator.partner_id, "Michel Operator should be the operator of this channel.")
self.assertEqual(len(channel.message_ids), 0)
# Operator Sends message
self._send_message(channel, self.operator.email, "Hello Again !", author_id=self.operator.partner_id.id)
self.assertEqual(len(channel.message_ids), 1)
# Visitor Answers
self._send_message(channel, self.visitor.display_name, "Answer from Visitor")
self.assertEqual(len(channel.message_ids), 2)
# Visitor Leave the conversation
channel._close_livechat_session()
self.assertEqual(len(channel.message_ids), 3)
self.assertEqual(channel.message_ids[0].author_id, self.env.ref('base.partner_root'), "Odoobot must be the sender of the 'has left the conversation' message.")
self.assertEqual(channel.message_ids[0].body, "<p>%s has left the conversation.</p>" % self.visitor.display_name)
self.assertEqual(channel.livechat_active, False, "The livechat session must be inactive as the visitor sent his feedback.")
return channel
def _clean_livechat_sessions(self):
# clean every possible mail channel linked to the visitor
active_channels = self.env['mail.channel'].search([('livechat_visitor_id', '=', self.visitor.id), ('livechat_active', '=', True)])
for active_channel in active_channels:
active_channel._close_livechat_session()
+87
View File
@@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import tests, _
from odoo.addons.website_livechat.tests.common import TestLivechatCommon
@tests.tagged('post_install', '-at_install')
class TestLivechatUI(tests.HttpCase, TestLivechatCommon):
def setUp(self):
super(TestLivechatUI, self).setUp()
self.visitor_tour = self.env['website.visitor'].create({
'name': 'Visitor Tour',
'website_id': self.env.ref('website.default_website').id,
})
self.target_visitor = self.visitor_tour
def test_complete_rating_flow_ui(self):
self.start_tour("/", 'website_livechat_complete_flow_tour')
self._check_end_of_rating_tours()
def test_happy_rating_flow_ui(self):
self.start_tour("/", 'website_livechat_happy_rating_tour')
self._check_end_of_rating_tours()
def test_ok_rating_flow_ui(self):
self.start_tour("/", 'website_livechat_ok_rating_tour')
self._check_end_of_rating_tours()
def test_bad_rating_flow_ui(self):
self.start_tour("/", 'website_livechat_sad_rating_tour')
self._check_end_of_rating_tours()
def test_no_rating_flow_ui(self):
self.start_tour("/", 'website_livechat_no_rating_tour')
channel = self.env['mail.channel'].search([('livechat_visitor_id', '=', self.visitor_tour.id)])
self.assertEqual(len(channel), 1, "There can only be one channel created for 'Visitor Tour'.")
self.assertEqual(channel.livechat_active, False, 'Livechat must be inactive after closing the chat window.')
def test_no_rating_no_close_flow_ui(self):
self.start_tour("/", 'website_livechat_no_rating_no_close_tour')
channel = self.env['mail.channel'].search([('livechat_visitor_id', '=', self.visitor_tour.id)])
self.assertEqual(len(channel), 1, "There can only be one channel created for 'Visitor Tour'.")
self.assertEqual(channel.livechat_active, True, 'Livechat must be active while the chat window is not closed.')
def test_empty_chat_request_flow_no_rating_no_close_ui(self):
# Open an empty chat request
self.visitor_tour.with_user(self.operator).action_send_chat_request()
chat_request = self.env['mail.channel'].search([('livechat_visitor_id', '=', self.visitor_tour.id), ('livechat_active', '=', True)])
# Visitor ask a new livechat session before the operator start to send message in chat request session
self.start_tour("/", 'website_livechat_no_rating_no_close_tour')
# Visitor's session must be active (gets the priority)
channel = self.env['mail.channel'].search([('livechat_visitor_id', '=', self.visitor_tour.id), ('livechat_active', '=', True)])
self.assertEqual(len(channel), 1, "There can only be one channel created for 'Visitor Tour'.")
self.assertEqual(channel.livechat_active, True, 'Livechat must be active while the chat window is not closed.')
# Check that the chat request has been canceled.
chat_request.invalidate_cache()
self.assertEqual(chat_request.livechat_active, False, "The livechat request must be inactive as the visitor started himself a livechat session.")
def test_chat_request_flow_with_rating_ui(self):
# Open a chat request
self.visitor_tour.with_user(self.operator).action_send_chat_request()
chat_request = self.env['mail.channel'].search([('livechat_visitor_id', '=', self.visitor_tour.id), ('livechat_active', '=', True)])
# Operator send a message to the visitor
self._send_message(chat_request, self.operator.email, "Hello my friend !", author_id=self.operator.partner_id.id)
self.assertEqual(len(chat_request.message_ids), 1, "Number of messages incorrect.")
# Visitor comes to the website and receives the chat request
self.start_tour("/", 'website_livechat_chat_request_part_1_no_close_tour')
# Check that the current session is the chat request
channel = self.env['mail.channel'].search([('livechat_visitor_id', '=', self.visitor_tour.id), ('livechat_active', '=', True)])
self.assertEqual(len(channel), 1, "There can only be one channel created for 'Visitor Tour'.")
self.assertEqual(channel, chat_request, "The active livechat session must be the chat request one.")
# Visitor reload the page and continues the chat with the operator normally
self.start_tour("/", 'website_livechat_chat_request_part_2_end_session_tour')
self._check_end_of_rating_tours()
def _check_end_of_rating_tours(self):
channel = self.env['mail.channel'].search([('livechat_visitor_id', '=', self.visitor_tour.id)])
self.assertEqual(len(channel), 1, "There can only be one channel created for 'Visitor Tour'.")
self.assertEqual(channel.livechat_active, False, 'Livechat must be inactive after rating.')
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<template id="assets_tests" name="Website Livechat Assets Tests" inherit_id="web.assets_tests">
<xpath expr="." position="inside">
<script type="text/javascript" src="/website_livechat/static/tests/tours/website_livechat_common.js"></script>
<script type="text/javascript" src="/website_livechat/static/tests/tours/website_livechat_rating.js"></script>
<script type="text/javascript" src="/website_livechat/static/tests/tours/website_livechat_request.js"></script>
</xpath>
</template>
</data>
</odoo>