19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:32:39 +01:00
parent 38c6088dcc
commit d9452d2060
243 changed files with 30797 additions and 10815 deletions

View file

@ -14,7 +14,6 @@ pip install odoo-bringout-oca-ocb-test_event_full
## Dependencies
This addon depends on:
- event
- event_booth
- event_crm
@ -23,43 +22,18 @@ This addon depends on:
- event_sms
- payment_demo
- website_event_booth_sale_exhibitor
- website_event_crm_questions
- website_event_exhibitor
- website_event_questions
- website_event_meet
- website_event_sale
- website_event_track
- website_event_track_live
- website_event_track_quiz
## Manifest Information
- **Name**: Test Full Event Flow
- **Version**: 1.0
- **Category**: Hidden/Tests
- **License**: LGPL-3
- **Installable**: False
## Source
Based on [OCA/OCB](https://github.com/OCA/OCB) branch 16.0, addon `test_event_full`.
- Repository: https://github.com/OCA/OCB
- Branch: 19.0
- Path: addons/test_event_full
## License
This package maintains the original LGPL-3 license from the upstream Odoo project.
## Documentation
- Overview: doc/OVERVIEW.md
- Architecture: doc/ARCHITECTURE.md
- Models: doc/MODELS.md
- Controllers: doc/CONTROLLERS.md
- Wizards: doc/WIZARDS.md
- Reports: doc/REPORTS.md
- Security: doc/SECURITY.md
- Install: doc/INSTALL.md
- Usage: doc/USAGE.md
- Configuration: doc/CONFIGURATION.md
- Dependencies: doc/DEPENDENCIES.md
- Troubleshooting: doc/TROUBLESHOOTING.md
- FAQ: doc/FAQ.md
This package preserves the original LGPL-3 license.

View file

@ -1,27 +1,26 @@
[project]
name = "odoo-bringout-oca-ocb-test_event_full"
version = "16.0.0"
description = "Test Full Event Flow - Odoo addon"
description = "Test Full Event Flow -
Odoo addon
"
authors = [
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
]
dependencies = [
"odoo-bringout-oca-ocb-event>=16.0.0",
"odoo-bringout-oca-ocb-event_booth>=16.0.0",
"odoo-bringout-oca-ocb-event_crm>=16.0.0",
"odoo-bringout-oca-ocb-event_crm_sale>=16.0.0",
"odoo-bringout-oca-ocb-event_sale>=16.0.0",
"odoo-bringout-oca-ocb-event_sms>=16.0.0",
"odoo-bringout-oca-ocb-payment_demo>=16.0.0",
"odoo-bringout-oca-ocb-website_event_booth_sale_exhibitor>=16.0.0",
"odoo-bringout-oca-ocb-website_event_crm_questions>=16.0.0",
"odoo-bringout-oca-ocb-website_event_exhibitor>=16.0.0",
"odoo-bringout-oca-ocb-website_event_questions>=16.0.0",
"odoo-bringout-oca-ocb-website_event_meet>=16.0.0",
"odoo-bringout-oca-ocb-website_event_sale>=16.0.0",
"odoo-bringout-oca-ocb-website_event_track>=16.0.0",
"odoo-bringout-oca-ocb-website_event_track_live>=16.0.0",
"odoo-bringout-oca-ocb-website_event_track_quiz>=16.0.0",
"odoo-bringout-oca-ocb-event>=19.0.0",
"odoo-bringout-oca-ocb-event_booth>=19.0.0",
"odoo-bringout-oca-ocb-event_crm>=19.0.0",
"odoo-bringout-oca-ocb-event_crm_sale>=19.0.0",
"odoo-bringout-oca-ocb-event_sale>=19.0.0",
"odoo-bringout-oca-ocb-event_sms>=19.0.0",
"TODO_MAP-payment_demo>=19.0.0",
"odoo-bringout-oca-ocb-website_event_booth_sale_exhibitor>=19.0.0",
"odoo-bringout-oca-ocb-website_event_exhibitor>=19.0.0",
"odoo-bringout-oca-ocb-website_event_sale>=19.0.0",
"odoo-bringout-oca-ocb-website_event_track>=19.0.0",
"odoo-bringout-oca-ocb-website_event_track_live>=19.0.0",
"odoo-bringout-oca-ocb-website_event_track_quiz>=19.0.0",
"requests>=2.25.1"
]
readme = "README.md"
@ -31,7 +30,7 @@ classifiers = [
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Office/Business",
]

View file

@ -19,10 +19,7 @@ automatic lead generation, full Online support, ...
'event_sms',
'payment_demo',
'website_event_booth_sale_exhibitor',
'website_event_crm_questions',
'website_event_exhibitor',
'website_event_questions',
'website_event_meet',
'website_event_sale',
'website_event_track',
'website_event_track_live',
@ -35,8 +32,12 @@ automatic lead generation, full Online support, ...
],
'assets': {
'web.assets_tests': [
'test_event_full/static/**/*',
'test_event_full/static/src/js/tours/*',
],
'web.assets_unit_tests': [
'test_event_full/static/src/js/tests/*',
],
},
'author': 'Odoo S.A.',
'license': 'LGPL-3',
}

View file

@ -1,122 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo><data noupdate="0">
<record id="event_booth_category_data_1" model="event.booth.category">
<field name="description" type="html"><p>Standard</p></field>
<field name="name">Standard</field>
<field name="product_id" ref="event_booth_sale.product_product_event_booth"/>
</record>
<record id="event_booth_category_data_2" model="event.booth.category">
<field name="description" type="html"><p>Premium</p></field>
<field name="name">Premium</field>
<field name="product_id" ref="event_booth_sale.product_product_event_booth"/>
<field name="price">90</field>
</record>
<record id="event_type_data_full" model="event.type">
<field name="auto_confirm" eval="True"/>
<field name="default_timezone">Europe/Paris</field>
<field name="event_type_booth_ids" eval="[
(5, 0),
(0, 0, {'booth_category_id': ref('test_event_full.event_booth_category_data_1'),
'name': 'Standard Booth',
}
),
(0, 0, {'booth_category_id': ref('test_event_full.event_booth_category_data_1'),
'name': 'Standard Booth 2',
}
),
(0, 0, {'booth_category_id': ref('test_event_full.event_booth_category_data_2'),
'name': 'Premium Booth',
}
),
(0, 0, {'booth_category_id': ref('test_event_full.event_booth_category_data_2'),
'name': 'Premium Booth 2',
}
)]"/>
<field name="event_type_mail_ids" eval="[
(5, 0),
(0, 0, {'interval_unit': 'now',
'interval_type': 'after_sub',
'notification_type': 'mail',
'template_ref': 'mail.template,%i' % ref('event.event_subscription'),
}
),
(0, 0, {'interval_nbr': 1,
'interval_unit': 'days',
'interval_type': 'before_event',
'notification_type': 'mail',
'template_ref': 'mail.template,%i' % ref('event.event_reminder'),
}
),
(0, 0, {'interval_nbr': 1,
'interval_unit': 'days',
'interval_type': 'after_event',
'notification_type': 'sms',
'template_ref': 'sms.template,%i' % ref('event_sms.sms_template_data_event_reminder'),
}
)]"/>
<field name="event_type_ticket_ids" eval="[
(5, 0),
(0, 0, {'description': 'Ticket1 Description',
'name': 'Ticket1',
'product_id': ref('event_sale.product_product_event'),
'seats_max': 10,
}
),
(0, 0, {'description': 'Ticket2 Description',
'name': 'Ticket2',
'product_id': ref('event_sale.product_product_event'),
'price': 45,
}
)]"/>
<field name="has_seats_limitation" eval="True"/>
<field name="name">Test Type</field>
<field name="note" type="html"><p>Template note</p></field>
<field name="question_ids" eval="[(5, 0)]"/>
<field name="seats_max">30</field>
<field name="tag_ids" eval="[(5, 0)]"/>
<field name="ticket_instructions" type="html"><p>Ticket Instructions</p></field>
<field name="website_menu" eval="True"/>
</record>
<record id="event_question_type_full_1" model="event.question">
<field name="question_type">simple_choice</field>
<field name="once_per_order" eval="False"/>
<field name="event_type_id" ref="test_event_full.event_type_data_full"/>
<field name="title">Question1</field>
</record>
<record id="event_question_type_full_1_answer_1" model="event.question.answer">
<field name="name">Q1-Answer1</field>
<field name="sequence">1</field>
<field name="question_id" ref="test_event_full.event_question_type_full_1"/>
</record>
<record id="event_question_type_full_1_answer_2" model="event.question.answer">
<field name="name">Q1-Answer2</field>
<field name="sequence">2</field>
<field name="question_id" ref="test_event_full.event_question_type_full_1"/>
</record>
<record id="event_question_type_full_2" model="event.question">
<field name="question_type">simple_choice</field>
<field name="once_per_order" eval="False"/>
<field name="event_type_id" ref="test_event_full.event_type_data_full"/>
<field name="title">Question2</field>
</record>
<record id="event_question_type_full_2_answer_1" model="event.question.answer">
<field name="name">Q2-Answer1</field>
<field name="sequence">1</field>
<field name="question_id" ref="test_event_full.event_question_type_full_2"/>
</record>
<record id="event_question_type_full_2_answer_2" model="event.question.answer">
<field name="name">Q2-Answer2</field>
<field name="sequence">2</field>
<field name="question_id" ref="test_event_full.event_question_type_full_2"/>
</record>
<record id="event_question_type_full_3" model="event.question">
<field name="question_type">text_box</field>
<field name="once_per_order" eval="True"/>
<field name="event_type_id" ref="test_event_full.event_type_data_full"/>
<field name="title">Question3</field>
</record>
</data></odoo>

View file

@ -0,0 +1,124 @@
import { defineMailModels } from "@mail/../tests/mail_test_helpers";
import { describe, expect, test } from "@odoo/hoot";
import { click, select } from "@odoo/hoot-dom";
import { animationFrame } from "@odoo/hoot-mock";
import { defineModels, fields, models, mountView, onRpc } from "@web/../tests/web_test_helpers";
class EventMail extends models.Model {
_name = "event.mail";
template_ref = fields.Reference({
selection: [
["mail.template", "Mail Template"],
["sms.template", "SMS Template"],
["some.template", "Some Template"],
],
});
_records = [
{
id: 1,
template_ref: "mail.template,1",
},
{
id: 2,
template_ref: "sms.template,1",
},
{
id: 3,
template_ref: "some.template,1",
},
];
}
class MailTemplate extends models.Model {
_name = "mail.template";
name = fields.Char();
_records = [{ id: 1, name: "Mail Template 1" }];
}
class SmsTemplate extends models.Model {
_name = "sms.template";
name = fields.Char();
_records = [{ id: 1, name: "SMS template 1" }];
}
class SomeTemplate extends models.Model {
_name = "some.template";
name = fields.Char();
_records = [{ id: 1, name: "Some Template 1" }];
}
defineMailModels();
defineModels([EventMail, MailTemplate, SmsTemplate, SomeTemplate]);
describe.current.tags("desktop");
test("Reference field displays right icons", async () => {
// bypass list controller check
onRpc("has_group", () => true);
await mountView({
type: "list",
resModel: "event.mail",
arch: `
<list editable="top">
<field name="template_ref" widget="EventMailTemplateReferenceField"/>
</list>`,
});
// each field cell will be the field of a different record (1 field/line)
expect(".o_field_cell").toHaveCount(3);
expect(".o_field_cell.o_EventMailTemplateReferenceField_cell").toHaveCount(3);
expect(".o_field_cell:eq(0) .fa-envelope").toHaveCount(1);
expect(".o_field_cell:eq(1) .fa-mobile").toHaveCount(1);
expect(".o_field_cell:eq(2) .fa-envelope").toHaveCount(0);
expect(".o_field_cell:eq(2) .fa-mobile").toHaveCount(0);
// select a sms.template instead of mail.template
await click(".o_field_cell:eq(0)");
await animationFrame();
await click(".o_field_cell:eq(0) select.o_input");
await select("sms.template");
await animationFrame();
await click(".o_field_cell:eq(0) .o_field_many2one_selection input");
await animationFrame();
await click(".o_field_cell:eq(0) .o-autocomplete--dropdown-item");
// click out
await click(".o_list_renderer");
await animationFrame();
expect(".o_field_cell:eq(0) .fa-mobile").toHaveCount(1);
expect(".o_field_cell:eq(0) .fa-envelope").toHaveCount(0);
// select a some other model to check it has no icon
await click(".o_field_cell:eq(0)");
await animationFrame();
await click(".o_field_cell:eq(0) select.o_input");
await select("some.template");
await animationFrame();
await click(".o_field_cell:eq(0) .o_field_many2one_selection input");
await animationFrame();
await click(".o_field_cell:eq(0) .o-autocomplete--dropdown-item");
await click(".o_list_renderer");
await animationFrame();
expect(".o_field_cell:eq(0) .fa-mobile").toHaveCount(0);
expect(".o_field_cell:eq(0) .fa-envelope").toHaveCount(0);
// select no record for the model
await click(".o_field_cell:eq(1)");
await animationFrame();
await click(".o_field_cell:eq(1) select.o_input");
await select("mail.template");
await click(".o_list_renderer");
await animationFrame();
expect(".o_field_cell:eq(1) .fa-mobile").toHaveCount(0);
expect(".o_field_cell:eq(1) .fa-envelope").toHaveCount(0);
});

View file

@ -1,85 +1,76 @@
odoo.define('test_event_full.tour.performance', function (require) {
"use strict";
var tour = require('web_tour.tour');
import { registry } from "@web/core/registry";
import * as wsTourUtils from '@website_sale/js/tours/tour_utils';
var registerSteps = [{
content: "Select 2 units of 'Ticket1' ticket type",
trigger: '#o_wevent_tickets_collapse .row.o_wevent_ticket_selector[name="Ticket1"] select',
run: 'text 2',
content: "Open ticket modal",
trigger: 'button.btn-primary:contains("Register")',
run: "click",
}, {
content: "Select 1 unit of 'Ticket2' ticket type",
trigger: '#o_wevent_tickets_collapse .row.o_wevent_ticket_selector[name="Ticket2"] select',
run: 'text 1',
content: "Add 2 units of 'Ticket1' ticket type by clicking the '+' button",
trigger: 'button[data-increment-type*="plus"]',
run: "dblclick",
}, {
content: "Edit 1 unit of 'Ticket2' ticket type",
trigger: '.modal input:eq(2)',
run: "edit 1",
}, {
content: "Click on 'Register' button",
trigger: '#o_wevent_tickets .btn-primary:contains("Register"):not(:disabled)',
run: 'click',
}, {
content: "Fill attendees details",
trigger: 'form[id="attendee_registration"] .btn:contains("Continue")',
run: function () {
$("input[name='1-name']").val("Raoulette Poiluchette");
$("input[name='1-phone']").val("0456112233");
$("input[name='1-email']").val("raoulette@example.com");
$("div[name*='Question1'] select[name*='question_answer-1']").val($("select[name*='question_answer-1'] option:contains('Q1-Answer2')").val());
$("div[name*='Question2'] select[name*='question_answer-1']").val($("select[name*='question_answer-1'] option:contains('Q2-Answer1')").val());
$("input[name='2-name']").val("Michel Tractopelle");
$("input[name='2-phone']").val("0456332211");
$("input[name='2-email']").val("michel@example.com");
$("div[name*='Question1'] select[name*='question_answer-2']").val($("select[name*='question_answer-2'] option:contains('Q1-Answer1')").val());
$("div[name*='Question2'] select[name*='question_answer-2']").val($("select[name*='question_answer-2'] option:contains('Q2-Answer2')").val());
$("input[name='3-name']").val("Hubert Boitaclous");
$("input[name='3-phone']").val("0456995511");
$("input[name='3-email']").val("hubert@example.com");
$("div[name*='Question1'] select[name*='question_answer-3']").val($("select[name*='question_answer-3'] option:contains('Q1-Answer2')").val());
$("div[name*='Question2'] select[name*='question_answer-3']").val($("select[name*='question_answer-3'] option:contains('Q2-Answer2')").val());
$("textarea[name*='question_answer']").text("Random answer from random guy");
},
content: "Choose the 'Q1-Answer2' answer of the 'Question1' for the first ticket",
trigger: 'select[name*="1-simple_choice"]',
run: "selectByIndex 2",
}, {
content: "Choose the 'Q2-Answer1' answer of the 'Question2' for the first ticket",
trigger: 'select[name*="1-simple_choice"]:last',
run: "selectByIndex 1",
}, {
content: "Choose the 'Q1-Answer1' answer of the 'Question1' for the second ticket",
trigger: 'select[name*="2-simple_choice"]',
run: "selectByIndex 1",
}, {
content: "Choose the 'Q2-Answer2' answer of the 'Question2' for the second ticket",
trigger: 'select[name*="2-simple_choice"]:last',
run: "selectByIndex 2",
}, {
content: "Choose the 'Q1-Answer2' answer of the 'Question1' for the third ticket",
trigger: 'select[name*="3-simple_choice"]',
run: "selectByIndex 2",
}, {
content: "Choose the 'Q2-Answer2' answer of the 'Question2' for the third ticket",
trigger: 'select[name*="3-simple_choice"]:last',
run: "selectByIndex 2",
}, {
content: "Fill the text content of the 'Question3' for the third ticket",
trigger: 'textarea[name*="text_box"]',
run: "edit Random answer from random guy",
}, {
content: "Validate attendees details",
extra_trigger: "input[name='1-name'], input[name='2-name'], input[name='3-name']",
trigger: 'button:contains("Continue")',
trigger: 'button[type=submit]:last',
run: 'click',
}, {
content: "Address filling",
trigger: 'select[name="country_id"]',
run: function () {
$('input[name="name"]').val('Raoulette Poiluchette');
$('input[name="phone"]').val('0456112233');
$('input[name="email"]').val('raoulette@example.com');
$('input[name="street"]').val('Cheesy Crust Street, 42');
$('input[name="city"]').val('CheeseCity');
$('input[name="zip"]').val('8888');
$('#country_id option:eq(1)').attr('selected', true);
},
}, {
content: "Next",
trigger: '.oe_cart .btn:contains("Next")',
}, {
content: 'Select Test payment provider',
trigger: '.o_payment_option_card:contains("Demo")'
}, {
content: 'Add card number',
trigger: 'input[name="customer_input"]',
run: 'text 4242424242424242'
}, {
content: "Pay now",
extra_trigger: "#cart_products:contains(Ticket1):contains(Ticket2)",
trigger: 'button:contains(Pay Now)',
run: 'click',
}, {
content: 'Payment is successful',
trigger: '.oe_website_sale_tx_status:contains("Your payment has been successfully processed.")',
run: function () {}
}];
expectUnloadPage: true,
},
...wsTourUtils.fillAdressForm({
name: "Raoulette Poiluchette",
phone: "0456112233",
email: "raoulette@example.com",
street: "Cheesy Crust Street, 42",
city: "CheeseCity",
zip: "8888",
}),
{
content: "Confirm address",
trigger: 'a[name="website_sale_main_button"]',
run: "click",
expectUnloadPage: true,
},
...wsTourUtils.payWithDemo(),
];
tour.register('wevent_performance_register', {
test: true
}, [].concat(
registry.category("web_tour.tours").add('wevent_performance_register', {
steps: () => [].concat(
registerSteps,
)
);
});

View file

@ -1,18 +1,57 @@
odoo.define('test_event_full.tour.register', function (require) {
"use strict";
var tour = require('web_tour.tour');
import { registry } from "@web/core/registry";
import { session } from "@web/session";
/**
* TALKS STEPS
*/
const reminderToggleSteps = function (talkName, reminderOn, toggleReminder) {
let steps = [];
if (reminderOn) {
steps = steps.concat([{
content: `Check Favorite for ${talkName} was already on`,
trigger: "div.o_wetrack_js_reminder i.fa-bell",
}]);
}
else {
steps = steps.concat([{
content: `Check Favorite for ${talkName} was off`,
trigger: "div.o_wetrack_js_reminder i.fa-bell-o",
}]);
if (toggleReminder) {
steps = steps.concat([{
content: "Set Favorite",
trigger: "i[title='Set Favorite']",
run: "click",
}]);
if (session.is_public){
steps = steps.concat([{
content: "The form of the email reminder modal is filled",
trigger: "#o_wetrack_email_reminder_form input[name='email']",
run: "fill visitor@odoo.com",
},
{
content: "The form is submit",
trigger: "#o_wetrack_email_reminder_form button[type='submit']",
run: "click",
}]);
}
steps = steps.concat([{
content: `Check Favorite for ${talkName} is now on`,
trigger: "div.o_wetrack_js_reminder i.fa-bell",
}]);
}
}
return steps;
};
var discoverTalkSteps = function (talkName, fromList, reminderOn, toggleReminder) {
const discoverTalkSteps = function (talkName, fromList, checkToggleReminder, reminderOn, toggleReminder) {
var steps;
if (fromList) {
steps = [{
content: 'Go on "' + talkName + '" talk in List',
trigger: 'a:contains("' + talkName + '")',
run: "click",
expectUnloadPage: true,
}];
}
else {
@ -20,109 +59,98 @@ var discoverTalkSteps = function (talkName, fromList, reminderOn, toggleReminder
content: 'Click on Live Track',
trigger: 'article span:contains("' + talkName + '")',
run: 'click',
expectUnloadPage: true,
}];
}
steps = steps.concat([{
content: `Check we are on the "${talkName}" talk page`,
trigger: 'div.o_wesession_track_main',
run: function () {}, // it's a check
}]);
if (reminderOn) {
steps = steps.concat([{
content: `Check Favorite for ${talkName} was already on`,
trigger: 'div.o_wetrack_js_reminder i.fa-bell',
extra_trigger: 'span.o_wetrack_js_reminder_text:contains("Favorite On")',
run: function () {}, // it's a check
}]);
}
else {
steps = steps.concat([{
content: `Check Favorite for ${talkName} was off`,
trigger: 'span.o_wetrack_js_reminder_text:contains("Set Favorite")',
run: function () {}, // it's a check
}]);
if (toggleReminder) {
steps = steps.concat([{
content: "Set Favorite",
trigger: 'span.o_wetrack_js_reminder_text',
run: 'click',
}, {
content: `Check Favorite for ${talkName} is now on`,
trigger: 'div.o_wetrack_js_reminder i.fa-bell',
extra_trigger: 'span.o_wetrack_js_reminder_text:contains("Favorite On")',
run: function () {}, // it's a check
}]);
}
if (checkToggleReminder){
steps = steps.concat(reminderToggleSteps(talkName, reminderOn, toggleReminder));
}
return steps;
};
/**
* ROOMS STEPS
*/
var discoverRoomSteps = function (roomName) {
var steps = [{
content: 'Go on "' + roomName + '" room in List',
trigger: 'a.o_wevent_meeting_room_card h4:contains("' + roomName + '")',
run: function() {
// can't click on it, it will try to launch Jitsi and fail on chrome headless
},
}];
return steps;
};
/**
* REGISTER STEPS
*/
var registerSteps = [{
content: 'Go on Register',
trigger: 'a.btn-primary:contains("Register")',
}, {
content: "Select 2 units of 'Standard' ticket type",
trigger: '#o_wevent_tickets_collapse .row:has(.o_wevent_registration_multi_select:contains("Free")) select',
run: 'text 2',
}, {
content: "Click on 'Register' button",
trigger: '#o_wevent_tickets .btn-primary:contains("Register"):not(:disabled)',
run: 'click',
}, {
content: "Fill attendees details",
trigger: 'form[id="attendee_registration"] .btn:contains("Continue")',
run: function () {
$("input[name='1-name']").val("Raoulette Poiluchette");
$("input[name='1-phone']").val("0456112233");
$("input[name='1-email']").val("raoulette@example.com");
$("select[name*='question_answer-1']").val($("select[name*='question_answer-1'] option:contains('Consumers')").val());
$("input[name='2-name']").val("Michel Tractopelle");
$("input[name='2-phone']").val("0456332211");
$("input[name='2-email']").val("michel@example.com");
$("select[name*='question_answer-2']").val($("select[name*='question_answer-1'] option:contains('Research')").val());
$("textarea[name*='question_answer']").text("An unicorn told me about you. I ate it afterwards.");
const registerSteps = [
{
content: "Open ticket modal",
trigger: "button.btn-primary:contains(Register):enabled",
run: "click",
},
}, {
content: "Validate attendees details",
extra_trigger: "input[name='1-name'], input[name='2-name'], input[name='3-name']",
trigger: 'button:contains("Continue")',
run: 'click',
}, {
trigger: 'div.o_wereg_confirmed_attendees span:contains("Raoulette Poiluchette")',
run: function () {} // check
}, {
trigger: 'div.o_wereg_confirmed_attendees span:contains("Michel Tractopelle")',
run: function () {} // check
}, {
content: "Click on 'register favorites talks' button",
trigger: 'a:contains("register to your favorites talks now")',
run: 'click',
}, {
trigger: 'h1:contains("Book your talks")',
run: function() {},
}];
{
content: "Edit 2 units of 'Standard' ticket type",
trigger: ".modal .o_wevent_ticket_selector input",
run: "edit 2",
},
{
content: "Click on 'Register' button",
trigger: ".modal #o_wevent_tickets .btn-primary:contains(Register):enabled",
run: "click",
},
{
content: "Wait the modal is shown before continue",
trigger: ".modal.modal_shown.show form[id=attendee_registration]",
},
{
trigger: ".modal input[name*='1-name']",
run: "edit Raoulette Poiluchette",
},
{
trigger: ".modal input[name*='1-phone']",
run: "edit 0456112233",
},
{
trigger: ".modal input[name*='1-email']",
run: "edit raoulette@example.com",
},
{
trigger: ".modal select[name*='1-simple_choice']",
run: "selectByLabel Consumers",
},
{
trigger: ".modal input[name*='2-name']",
run: "edit Michel Tractopelle",
},
{
trigger: ".modal input[name*='2-phone']",
run: "edit 0456332211",
},
{
trigger: ".modal input[name*='2-email']",
run: "edit michel@example.com",
},
{
trigger: ".modal select[name*='2-simple_choice']",
run: "selectByLabel Research",
},
{
trigger: ".modal textarea[name*='text_box']",
run: "edit An unicorn told me about you. I ate it afterwards.",
},
{
trigger: ".modal input[name*='1-name'], input[name*='2-name'], input[name*='3-name']",
},
{
content: "Validate attendees details",
trigger: ".modal button[type=submit]:enabled",
run: "click",
expectUnloadPage: true,
},
{
content: "Click on 'register favorites talks' button",
trigger: "a:contains(register to your favorites talks now)",
run: "click",
expectUnloadPage: true,
},
{
trigger: "h5:contains(Book your talks)",
},
];
/**
* MAIN STEPS
@ -132,43 +160,46 @@ var initTourSteps = function (eventName) {
return [{
content: 'Go on "' + eventName + '" page',
trigger: 'a[href*="/event"]:contains("' + eventName + '"):first',
run: "click",
expectUnloadPage: true,
}];
};
var browseTalksSteps = [{
content: 'Browse Talks',
trigger: 'a:contains("Talks")',
content: 'Browse Talks Menu',
trigger: 'a[href*="#"]:contains("Talks")',
run: "click",
}, {
content: 'Browse Talks Submenu',
trigger: 'a.dropdown-item span:contains("Talks")',
run: "click",
expectUnloadPage: true,
}, {
content: 'Check we are on the talk list page',
trigger: 'h1:contains("Book your talks")',
run: function () {} // check
trigger: 'h5:contains("Book your talks")',
}];
var browseMeetSteps = [{
content: 'Browse Meet',
trigger: 'a:contains("Community")',
var browseBackSteps = [{
content: 'Browse Back',
trigger: 'a:contains("All Talks")',
run: "click",
expectUnloadPage: true,
}, {
content: 'Check we are on the community page',
trigger: 'span:contains("Join a room")',
run: function () {} // check
content: 'Check we are back on the talk list page',
trigger: 'h5:contains("Book your talks")',
}];
tour.register('wevent_register', {
registry.category("web_tour.tours").add('wevent_register', {
url: '/event',
test: true
}, [].concat(
steps: () => [].concat(
initTourSteps('Online Reveal'),
browseTalksSteps,
discoverTalkSteps('What This Event Is All About', true, true),
browseTalksSteps,
discoverTalkSteps('Live Testimonial', false, false, false),
browseTalksSteps,
discoverTalkSteps('Our Last Day Together !', true, false, true),
browseMeetSteps,
discoverRoomSteps('Best wood for furniture'),
discoverTalkSteps('What This Event Is All About', true, true, true),
browseBackSteps,
discoverTalkSteps('Live Testimonial', false, false, false, false),
browseBackSteps,
discoverTalkSteps('Our Last Day Together!', true, true, false, true),
browseBackSteps,
registerSteps,
)
);
});

View file

@ -7,5 +7,5 @@ from . import test_event_event
from . import test_event_mail
from . import test_event_security
from . import test_performance
from . import test_wevent_menu
from . import test_wevent_register
from . import test_event_discount

View file

@ -3,10 +3,14 @@
from datetime import datetime, timedelta, time
from odoo import Command
from odoo.addons.base.tests.common import HttpCaseWithUserDemo, HttpCaseWithUserPortal
from odoo.addons.base.tests.test_ir_cron import CronMixinCase
from odoo.addons.event.tests.common import EventCase
from odoo.addons.event_crm.tests.common import EventCrmCase
from odoo.addons.mail.tests.common import mail_new_test_user
from odoo.addons.mail.tests.common import mail_new_test_user, MailCase
from odoo.addons.sales_team.tests.common import TestSalesCommon
from odoo.addons.sms.tests.common import SMSCase
from odoo.addons.website.tests.test_website_visitor import MockVisitor
@ -15,7 +19,6 @@ class TestEventFullCommon(EventCrmCase, TestSalesCommon, MockVisitor):
@classmethod
def setUpClass(cls):
super(TestEventFullCommon, cls).setUpClass()
cls._init_mail_gateway()
# Context data: dates
# ------------------------------------------------------------
@ -37,6 +40,7 @@ class TestEventFullCommon(EventCrmCase, TestSalesCommon, MockVisitor):
# set country in order to format Belgian numbers
cls.company_admin.write({
'country_id': cls.env.ref('base.be').id,
'email': 'info@yourcompany.com',
})
cls.event_user = mail_new_test_user(
cls.env,
@ -55,7 +59,6 @@ class TestEventFullCommon(EventCrmCase, TestSalesCommon, MockVisitor):
'country_id': cls.env.ref('base.be').id,
'email': 'customer.test@example.com',
'name': 'Test Customer',
'mobile': '0456123456',
'phone': '0456123456',
})
# make a SO for a customer, selling some tickets
@ -68,14 +71,16 @@ class TestEventFullCommon(EventCrmCase, TestSalesCommon, MockVisitor):
cls.ticket_product = cls.env['product.product'].create({
'description_sale': 'Ticket Product Description',
'detailed_type': 'event',
'type': 'service',
'service_tracking': 'event',
'list_price': 10,
'name': 'Test Registration Product',
'standard_price': 30.0,
})
cls.booth_product = cls.env['product.product'].create({
'description_sale': 'Booth Product Description',
'detailed_type': 'event_booth',
'type': 'service',
'service_tracking': 'event_booth',
'list_price': 20,
'name': 'Test Booth Product',
'standard_price': 60.0,
@ -120,9 +125,8 @@ class TestEventFullCommon(EventCrmCase, TestSalesCommon, MockVisitor):
# ------------------------------------------------------------
test_registration_report = cls.env.ref('test_event_full.event_registration_report_test')
subscription_template = cls.env.ref('event.event_subscription')
subscription_template.write({'report_template': test_registration_report.id})
subscription_template.write({'report_template_ids': [(6, 0, test_registration_report.ids)]})
cls.test_event_type = cls.env['event.type'].create({
'auto_confirm': True,
'default_timezone': 'Europe/Paris',
'event_type_booth_ids': [
(0, 0, {'booth_category_id': cls.event_booth_categories[0].id,
@ -145,21 +149,18 @@ class TestEventFullCommon(EventCrmCase, TestSalesCommon, MockVisitor):
'event_type_mail_ids': [
(0, 0, {'interval_unit': 'now', # right at subscription
'interval_type': 'after_sub',
'notification_type': 'mail',
'template_ref': 'mail.template,%i' % subscription_template.id,
}
),
(0, 0, {'interval_nbr': 1, # 1 days before event
'interval_unit': 'days',
'interval_type': 'before_event',
'notification_type': 'mail',
'template_ref': 'mail.template,%i' % cls.env['ir.model.data']._xmlid_to_res_id('event.event_reminder'),
}
),
(0, 0, {'interval_nbr': 1, # 1 days after event
'interval_unit': 'days',
'interval_type': 'after_event',
'notification_type': 'sms',
'template_ref': 'sms.template,%i' % cls.env['ir.model.data']._xmlid_to_res_id('event_sms.sms_template_data_event_reminder'),
}
),
@ -228,15 +229,15 @@ class TestEventFullCommon(EventCrmCase, TestSalesCommon, MockVisitor):
'is_published': True,
}
cls.test_event = cls.env['event.event'].create({
'name': 'Test Event',
'auto_confirm': True,
'date_begin': datetime.now() + timedelta(days=1),
'date_end': datetime.now() + timedelta(days=5),
'date_tz': 'Europe/Brussels',
'event_type_id': cls.test_event_type.id,
'is_published': True,
})
with cls.mock_datetime_and_now(cls, cls.reference_now):
cls.test_event = cls.env['event.event'].create({
'name': 'Test Event',
'date_begin': datetime.now() + timedelta(days=1),
'date_end': datetime.now() + timedelta(days=5),
'date_tz': 'Europe/Brussels',
'event_type_id': cls.test_event_type.id,
'is_published': True,
})
# update post-synchronize data
ticket_1 = cls.test_event.event_ticket_ids.filtered(lambda t: t.name == 'Ticket1')
ticket_2 = cls.test_event.event_ticket_ids.filtered(lambda t: t.name == 'Ticket2')
@ -251,39 +252,36 @@ class TestEventFullCommon(EventCrmCase, TestSalesCommon, MockVisitor):
], limit=1)
cls.customer_data = [
{'email': 'customer.email.%02d@test.example.com' % x,
'name': 'My Customer %02d' % x,
'mobile': '04569999%02d' % x,
{'email': f'customer.email.{idx:02d}@test.example.com',
'name': f'My Customer {idx:02d}',
'partner_id': False,
'phone': '04560000%02d' % x,
} for x in range(0, 10)
'phone': f'04560000{idx:02d}',
} for idx in range(0, 10)
]
cls.website_customer_data = [
{'email': 'website.email.%02d@test.example.com' % x,
'name': 'My Customer %02d' % x,
'mobile': '04569999%02d' % x,
{'email': f'website.email.{idx:02d}@test.example.com',
'name': f'My Customer {idx:02d}',
'partner_id': cls.env.ref('base.public_partner').id,
'phone': '04560000%02d' % x,
'phone': f'04560000{idx:02d}',
'registration_answer_ids': [
(0, 0, {
'question_id': cls.test_event.question_ids[0].id,
'value_answer_id': cls.test_event.question_ids[0].answer_ids[(x % 2)].id,
'value_answer_id': cls.test_event.question_ids[0].answer_ids[(idx % 2)].id,
}), (0, 0, {
'question_id': cls.test_event.question_ids[1].id,
'value_answer_id': cls.test_event.question_ids[1].answer_ids[(x % 2)].id,
'value_answer_id': cls.test_event.question_ids[1].answer_ids[(idx % 2)].id,
}), (0, 0, {
'question_id': cls.test_event.question_ids[2].id,
'value_text_box': 'CustomerAnswer%s' % x,
'value_text_box': f'CustomerAnswer{idx}',
})
],
} for x in range(0, 10)
} for idx in range(0, 10)
]
cls.partners = cls.env['res.partner'].create([
{'email': 'partner.email.%02d@test.example.com' % x,
'name': 'PartnerCustomer',
'mobile': '04569999%02d' % x,
'phone': '04560000%02d' % x,
} for x in range(0, 10)
{'email': f'partner.email.{idx:02d}@test.example.com',
'name': f'PartnerCustomer {idx:02d}',
'phone': f'04560000{idx:02d}',
} for idx in range(0, 10)
])
def assertLeadConvertion(self, rule, registrations, partner=None, **expected):
@ -304,6 +302,98 @@ class TestEventFullCommon(EventCrmCase, TestSalesCommon, MockVisitor):
self.assertIn(answer.value_text_box, lead.description) # better: check multi line
class TestEventMailCommon(EventCase, SMSCase, MailCase, CronMixinCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.event_cron_id = cls.env.ref('event.event_mail_scheduler')
# deactivate other schedulers to avoid messing with crons
cls.env['event.mail'].search([]).unlink()
# consider asynchronous sending as default sending
cls.env["ir.config_parameter"].set_param("event.event_mail_async", False)
cls.env.company.write({
'email': 'info@yourcompany.example.com',
'name': 'YourCompany',
})
# prepare SMS templates
cls.sms_template_sub = cls.env['sms.template'].create({
'name': 'Test SMS Subscription',
'model_id': cls.env.ref('event.model_event_registration').id,
'body': '{{ object.event_id.organizer_id.name }} registration confirmation.',
'lang': '{{ object.partner_id.lang }}'
})
cls.sms_template_rem = cls.env['sms.template'].create({
'name': 'Test SMS Reminder',
'model_id': cls.env.ref('event.model_event_registration').id,
'body': '{{ object.event_id.organizer_id.name }} reminder',
'lang': '{{ object.partner_id.lang }}'
})
# freeze some datetimes, and ensure more than 1D+1H before event starts
# to ease time-based scheduler check
# Since `now` is used to set the `create_date` of an event and create_date
# has often microseconds, we set it to ensure that the scheduler we still be
# launched if scheduled_date == create_date - microseconds
cls.reference_now = datetime(2021, 3, 20, 14, 30, 15, 123456)
cls.event_date_begin = datetime(2021, 3, 25, 8, 0, 0)
cls.event_date_end = datetime(2021, 3, 28, 18, 0, 0)
cls._setup_test_reports()
with cls.mock_datetime_and_now(cls, cls.reference_now):
cls.test_event = cls.env['event.event'].create({
'name': 'TestEventMail',
'user_id': cls.user_eventmanager.id,
'date_begin': cls.event_date_begin,
'date_end': cls.event_date_end,
'event_mail_ids': [
(0, 0, { # right at subscription: mail
'interval_unit': 'now',
'interval_type': 'after_sub',
'notification_type': 'mail',
'template_ref': f'mail.template,{cls.template_subscription.id}',
}),
(0, 0, { # right at subscription: sms
'interval_unit': 'now',
'interval_type': 'after_sub',
'notification_type': 'sms',
'template_ref': f'sms.template,{cls.sms_template_sub.id}',
}),
(0, 0, { # 3 days before event: mail
'interval_nbr': 3,
'interval_unit': 'days',
'interval_type': 'before_event',
'notification_type': 'mail',
'template_ref': f'mail.template,{cls.template_reminder.id}',
}),
(0, 0, { # 3 days before event: SMS
'interval_nbr': 3,
'interval_unit': 'days',
'interval_type': 'before_event',
'notification_type': 'sms',
'template_ref': f'sms.template,{cls.sms_template_rem.id}',
}),
(0, 0, { # 1h after event: mail
'interval_nbr': 1,
'interval_unit': 'hours',
'interval_type': 'after_event',
'notification_type': 'mail',
'template_ref': f'mail.template,{cls.template_reminder.id}',
}),
(0, 0, { # 1h after event: SMS
'interval_nbr': 1,
'interval_unit': 'hours',
'interval_type': 'after_event',
'notification_type': 'sms',
'template_ref': f'sms.template,{cls.sms_template_rem.id}',
}),
],
})
class TestWEventCommon(HttpCaseWithUserDemo, HttpCaseWithUserPortal, MockVisitor):
def setUp(self):
@ -322,7 +412,8 @@ class TestWEventCommon(HttpCaseWithUserDemo, HttpCaseWithUserPortal, MockVisitor
'description_sale': 'Mighty Description',
'list_price': 10,
'standard_price': 30.0,
'detailed_type': 'event',
'type': 'service',
'service_tracking': 'event',
})
self.event_tag_category_1 = self.env['event.tag.category'].create({
@ -336,13 +427,12 @@ class TestWEventCommon(HttpCaseWithUserDemo, HttpCaseWithUserPortal, MockVisitor
'color': 8,
})
self.env['event.event'].search(
[('name', 'like', '%Online Reveal%')]
[('name', 'like', 'Online Reveal')]
).write(
{'name': 'Do not click on me'}
)
self.event = self.env['event.event'].create({
'name': 'Online Reveal TestEvent',
'auto_confirm': True,
'stage_id': self.env.ref('event.event_stage_booked').id,
'address_id': False,
'user_id': self.user_demo.id,
@ -377,7 +467,6 @@ class TestWEventCommon(HttpCaseWithUserDemo, HttpCaseWithUserPortal, MockVisitor
'email': 'constantin@test.example.com',
'country_id': self.env.ref('base.be').id,
'phone': '0485112233',
'mobile': False,
})
self.event_speaker = self.env['res.partner'].create({
'name': 'Brandon Freeman',
@ -392,7 +481,7 @@ class TestWEventCommon(HttpCaseWithUserDemo, HttpCaseWithUserPortal, MockVisitor
self.event_question_1 = self.env['event.question'].create({
'title': 'Which field are you working in',
'question_type': 'simple_choice',
'event_id': self.event.id,
'event_ids': [Command.set(self.event.ids)],
'once_per_order': False,
'answer_ids': [
(0, 0, {'name': 'Consumers'}),
@ -403,7 +492,7 @@ class TestWEventCommon(HttpCaseWithUserDemo, HttpCaseWithUserPortal, MockVisitor
self.event_question_2 = self.env['event.question'].create({
'title': 'How did you hear about us ?',
'question_type': 'text_box',
'event_id': self.event.id,
'event_ids': [Command.set(self.event.ids)],
'once_per_order': True,
})
@ -421,6 +510,7 @@ class TestWEventCommon(HttpCaseWithUserDemo, HttpCaseWithUserPortal, MockVisitor
'wishlisted_by_default': True,
'user_id': self.user_admin.id,
'partner_id': self.event_speaker.id,
'description': 'Performance of Raoul Grosbedon.'
})
self.track_1 = self.env['event.track'].create({
'name': 'Live Testimonial',
@ -431,9 +521,10 @@ class TestWEventCommon(HttpCaseWithUserDemo, HttpCaseWithUserPortal, MockVisitor
'is_published': True,
'user_id': self.user_admin.id,
'partner_id': self.event_speaker.id,
'description': 'Description of the live.'
})
self.track_2 = self.env['event.track'].create({
'name': 'Our Last Day Together !',
'name': 'Our Last Day Together!',
'event_id': self.event.id,
'stage_id': self.env.ref('website_event_track.event_track_stage3').id,
'date': self.reference_now + timedelta(days=1),
@ -441,22 +532,7 @@ class TestWEventCommon(HttpCaseWithUserDemo, HttpCaseWithUserPortal, MockVisitor
'is_published': True,
'user_id': self.user_admin.id,
'partner_id': self.event_speaker.id,
})
# ------------------------------------------------------------
# MEETING ROOMS
# ----------------------------------------------------------
self.env['event.meeting.room'].create({
'name': 'Best wood for furniture',
'summary': 'Let\'s talk about wood types for furniture',
'target_audience': 'wood expert(s)',
'is_pinned': True,
'website_published': True,
'event_id': self.event.id,
'room_lang_id': self.env.ref('base.lang_en').id,
'room_max_capacity': '12',
'room_participant_count': 9,
'description': 'Description of our last day together.'
})
self.env.flush_all()

View file

@ -2,9 +2,10 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.test_event_full.tests.common import TestEventFullCommon
from odoo.tests import users
from odoo.tests import tagged, users
@tagged("event_crm")
class TestEventCrm(TestEventFullCommon):
@classmethod

View file

@ -1,78 +0,0 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import time
from odoo.tests import tagged
from odoo.fields import Command
from odoo.addons.test_event_full.tests.common import TestEventFullCommon
@tagged('post_install', '-at_install')
class TestEventTicketPriceRounding(TestEventFullCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.ticket_product.write({
'lst_price': 1.0
})
cls.currency_jpy = cls.env['res.currency'].create({
'name': 'JPX',
'symbol': '¥',
'rounding': 1.0,
'rate_ids': [Command.create({'rate': 133.6200, 'name': time.strftime('%Y-%m-%d')})],
})
cls.currency_cad = cls.env['res.currency'].create({
'name': 'CXD',
'symbol': '$',
'rounding': 0.01,
'rate_ids': [Command.create({'rate': 1.338800, 'name': time.strftime('%Y-%m-%d')})],
})
cls.pricelist_usd = cls.env['product.pricelist'].create({
'name': 'Pricelist USD',
'currency_id': cls.env.ref('base.USD').id,
})
cls.pricelist_jpy = cls.env['product.pricelist'].create({
'name': 'Pricelist JPY',
'currency_id': cls.currency_jpy.id,
})
cls.pricelist_cad = cls.env['product.pricelist'].create({
'name': 'Pricelist CAD',
'currency_id': cls.currency_cad.id,
})
cls.event_type = cls.env['event.type'].create({
'name': 'Test Event Type',
'auto_confirm': True,
'event_type_ticket_ids': [
(0, 0, {
'name': 'Test Event Ticket',
'product_id': cls.ticket_product.id,
'price': 30.0,
})
],
})
cls.event_ticket = cls.event_type.event_type_ticket_ids[0]
def test_no_discount_usd(self):
ticket = self.event_ticket.with_context(pricelist=self.pricelist_usd.id)
ticket._compute_price_reduce()
self.assertAlmostEqual(ticket.price_reduce, 30.0, places=6, msg="No discount should be applied for the USD pricelist.")
def test_no_discount_jpy(self):
ticket = self.event_ticket.with_context(pricelist=self.pricelist_jpy.id)
ticket._compute_price_reduce()
self.assertAlmostEqual(ticket.price_reduce, 30.0, places=6, msg="No discount should be applied for the JPY pricelist.")
def test_no_discount_cad(self):
ticket = self.event_ticket.with_context(pricelist=self.pricelist_cad.id)
ticket._compute_price_reduce()
self.assertAlmostEqual(ticket.price_reduce, 30.0, places=6, msg="No discount should be applied for the CAD pricelist.")

View file

@ -36,16 +36,13 @@ class TestEventEvent(TestEventFullCommon):
# check result
self.assertEqual(event.address_id, self.env.user.company_id.partner_id)
self.assertTrue(event.auto_confirm)
self.assertEqual(event.country_id, self.env.user.company_id.country_id)
self.assertEqual(event.date_tz, 'Europe/Paris')
self.assertEqual(event.event_booth_count, 4)
self.assertEqual(len(event.event_mail_ids), 3)
self.assertEqual(len(event.event_ticket_ids), 2)
self.assertTrue(event.introduction_menu)
self.assertTrue(event.location_menu)
self.assertTrue(event.menu_register_cta)
self.assertEqual(event.message_partner_ids, self.env.user.partner_id + self.env.user.company_id.partner_id)
self.assertEqual(event.message_partner_ids, self.env.user.partner_id)
self.assertEqual(event.note, '<p>Template note</p>')
self.assertTrue(event.register_menu)
self.assertEqual(len(event.question_ids), 3)
@ -75,12 +72,23 @@ class TestEventEvent(TestEventFullCommon):
self.assertTrue(event.is_ongoing)
self.assertTrue(event.event_registrations_started)
def test_event_kanban_state_on_stage_change(self):
"""Test that kanban_state updates correctly when stage is changed."""
test_event_1 = self.env['event.event'].browse(self.test_event.ids)
test_event_2 = test_event_1.copy()
test_event_1.kanban_state = 'done'
test_event_2.kanban_state = 'cancel' # Event Cancelled
new_stage = self.env['event.stage'].create({'name': 'New Stage', 'sequence': 1})
(test_event_1 | test_event_2).stage_id = new_stage.id # Change event stage
self.assertEqual(test_event_1.kanban_state, 'normal', 'kanban state should reset to "normal" on stage change')
self.assertEqual(test_event_2.kanban_state, 'cancel', 'kanban state should not reset on stage change')
@freeze_time('2021-12-01 11:00:00')
@users('event_user')
def test_event_seats_and_schedulers(self):
now = datetime.now() # used to force create_date, as sql is not wrapped by freeze gun
self.env.cr._now = now
test_event = self.env['event.event'].browse(self.test_event.ids)
ticket_1 = test_event.event_ticket_ids.filtered(lambda ticket: ticket.name == 'Ticket1')
ticket_2 = test_event.event_ticket_ids.filtered(lambda ticket: ticket.name == 'Ticket2')
@ -94,14 +102,15 @@ class TestEventEvent(TestEventFullCommon):
self.assertFalse(ticket_2.sale_available)
# make 9 registrations (let 1 on ticket)
with self.mock_mail_gateway():
with self.mock_datetime_and_now(self.reference_now), \
self.mock_mail_gateway():
self.env['event.registration'].create([
{'create_date': now,
'email': 'test.customer.%02d@test.example.com' % x,
'phone': '04560011%02d' % x,
'event_id': test_event.id,
'event_ticket_id': ticket_1.id,
'name': 'Customer %d' % x,
{
'email': 'test.customer.%02d@test.example.com' % x,
'phone': '04560011%02d' % x,
'event_id': test_event.id,
'event_ticket_id': ticket_1.id,
'name': 'Customer %d' % x,
}
for x in range(0, 9)
])
@ -114,27 +123,29 @@ class TestEventEvent(TestEventFullCommon):
self.assertEqual(ticket_2.seats_available, 0)
# prevent registration due to ticket limit
with self.assertRaises(exceptions.ValidationError):
with self.mock_datetime_and_now(self.reference_now), \
self.assertRaises(exceptions.ValidationError):
self.env['event.registration'].create([
{'create_date': now,
'email': 'additional.customer.%02d@test.example.com' % x,
'phone': '04560011%02d' % x,
'event_id': test_event.id,
'event_ticket_id': ticket_1.id,
'name': 'Additional Customer %d' % x,
{
'email': 'additional.customer.%02d@test.example.com' % x,
'phone': '04560011%02d' % x,
'event_id': test_event.id,
'event_ticket_id': ticket_1.id,
'name': 'Additional Customer %d' % x,
}
for x in range(0, 2)
])
# make 20 registrations (on free ticket)
with self.mock_mail_gateway():
with self.mock_datetime_and_now(self.reference_now), \
self.mock_mail_gateway():
self.env['event.registration'].create([
{'create_date': now,
'email': 'other.customer.%02d@test.example.com' % x,
'phone': '04560011%02d' % x,
'event_id': test_event.id,
'event_ticket_id': ticket_2.id,
'name': 'Other Customer %d' % x,
{
'email': 'other.customer.%02d@test.example.com' % x,
'phone': '04560011%02d' % x,
'event_id': test_event.id,
'event_ticket_id': ticket_2.id,
'name': 'Other Customer %d' % x,
}
for x in range(0, 20)
])
@ -145,14 +156,15 @@ class TestEventEvent(TestEventFullCommon):
self.assertEqual(ticket_2.seats_available, 0)
# prevent registration due to event limit
with self.assertRaises(exceptions.ValidationError):
with self.mock_datetime_and_now(self.reference_now), \
self.assertRaises(exceptions.ValidationError):
self.env['event.registration'].create([
{'create_date': now,
'email': 'additional.customer.%02d@test.example.com' % x,
'phone': '04560011%02d' % x,
'event_id': test_event.id,
'event_ticket_id': ticket_2.id,
'name': 'Additional Customer %d' % x,
{
'email': 'additional.customer.%02d@test.example.com' % x,
'phone': '04560011%02d' % x,
'event_id': test_event.id,
'event_ticket_id': ticket_2.id,
'name': 'Additional Customer %d' % x,
}
for x in range(0, 2)
])

View file

@ -2,15 +2,15 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import datetime, timedelta
from freezegun import freeze_time
from unittest.mock import patch
from odoo.addons.mail.tests.common import MockEmail
from odoo.addons.sms.tests.common import MockSMS
from odoo.addons.test_event_full.tests.common import TestWEventCommon
from odoo.exceptions import ValidationError
from odoo.tools import mute_logger
from odoo.addons.test_event_full.tests.common import TestEventFullCommon, TestEventMailCommon
from odoo.tests import tagged, users
from odoo.tools import formataddr
class TestTemplateRefModel(TestWEventCommon):
@tagged('event_mail', 'post_install', '-at_install')
class TestEventMailInternals(TestEventMailCommon):
def test_template_ref_delete_lines(self):
""" When deleting a template, related lines should be deleted too """
@ -51,117 +51,303 @@ class TestTemplateRefModel(TestWEventCommon):
self.assertEqual(len(event_type.event_type_mail_ids.exists()), 0)
self.assertEqual(len(event.event_mail_ids.exists()), 0)
def test_template_ref_model_constraint(self):
test_cases = [
('mail', 'mail.template', True),
('mail', 'sms.template', False),
('sms', 'sms.template', True),
('sms', 'mail.template', False),
]
@tagged('event_mail', 'post_install', '-at_install')
class TestEventMailSchedule(TestEventMailCommon):
for notification_type, template_type, valid in test_cases:
with self.subTest(notification_type=notification_type, template_type=template_type):
if template_type == 'mail.template':
template = self.env[template_type].create({
'name': 'test template',
'model_id': self.env['ir.model']._get_id('event.registration'),
})
else:
template = self.env[template_type].create({
'name': 'test template',
'body': 'Body Test',
'model_id': self.env['ir.model']._get_id('event.registration'),
})
if not valid:
with self.assertRaises(ValidationError) as cm:
self.env['event.mail'].create({
'event_id': self.event.id,
'notification_type': notification_type,
'interval_unit': 'now',
'interval_type': 'before_event',
'template_ref': template,
})
if notification_type == 'mail':
self.assertEqual(str(cm.exception), 'The template which is referenced should be coming from mail.template model.')
else:
self.assertEqual(str(cm.exception), 'The template which is referenced should be coming from sms.template model.')
class TestEventSmsMailSchedule(TestWEventCommon, MockEmail, MockSMS):
@freeze_time('2020-07-06 12:00:00')
@mute_logger('odoo.addons.base.models.ir_model', 'odoo.models')
def test_event_mail_before_trigger_sent_count(self):
""" Emails are sent to both confirmed and unconfirmed attendees.
This test checks that the count of sent emails includes the emails sent to unconfirmed ones
Time in the test is frozen to simulate the following state:
NOW Event Start Event End
12:00 13:00 14:00
| | |
| | time
3 hours
Trigger before event
"""
self.sms_template_rem = self.env['sms.template'].create({
'name': 'Test reminder',
'model_id': self.env.ref('event.model_event_registration').id,
'body': '{{ object.event_id.organizer_id.name }} reminder',
'lang': '{{ object.partner_id.lang }}'
})
test_event = self.env['event.event'].create({
'name': 'TestEventMail',
# 'user_id': self.env.ref('base.user_admin').id,
'auto_confirm': False,
'date_begin': datetime.now() + timedelta(hours=1),
'date_end': datetime.now() + timedelta(hours=2),
'event_mail_ids': [
(0, 0, { # email 3 hours before event
'interval_nbr': 3,
'interval_unit': 'hours',
'interval_type': 'before_event',
'template_ref': 'mail.template,%i' % self.env['ir.model.data']._xmlid_to_res_id('event.event_reminder')}),
(0, 0, { # sms 3 hours before event
'interval_nbr': 3,
'interval_unit': 'hours',
'interval_type': 'before_event',
'notification_type': 'sms',
'template_ref': 'sms.template,%i' % self.sms_template_rem.id}),
]
})
mail_scheduler = test_event.event_mail_ids
self.assertEqual(len(mail_scheduler), 2, 'There should be two mail schedulers. One for mail one for sms. Cannot perform test')
""" Emails are only sent to confirmed attendees. """
test_event = self.test_event
mail_schedulers = test_event.event_mail_ids
self.assertEqual(len(mail_schedulers), 6)
before = mail_schedulers.filtered(lambda m: m.interval_type == "before_event" and m.interval_unit == "days")
self.assertEqual(len(before), 2)
# Add registrations
self.env['event.registration'].create([{
_dummy, _dummy, open_reg, done_reg = self.env['event.registration'].create([{
'event_id': test_event.id,
'name': 'RegistrationUnconfirmed',
'email': 'Registration@Unconfirmed.com',
'phone': '1',
'state': 'draft',
}, {
'event_id': test_event.id,
'name': 'RegistrationCanceled',
'email': 'Registration@Canceled.com',
'phone': '2',
'state': 'cancel',
}, {
'event_id': test_event.id,
'name': 'RegistrationConfirmed',
'email': 'Registration@Confirmed.com',
'phone': '3',
'state': 'open',
}, {
'event_id': test_event.id,
'name': 'RegistrationDone',
'email': 'Registration@Done.com',
'phone': '4',
'state': 'done',
}])
with self.mock_mail_gateway(), self.mockSMSGateway():
mail_scheduler.execute()
with self.mock_datetime_and_now(self.event_date_begin - timedelta(days=2)), \
self.mock_mail_gateway(), \
self.mockSMSGateway():
before.execute()
self.assertEqual(len(self._new_mails), 2, 'Mails were not created')
self.assertEqual(len(self._new_sms), 2, 'SMS were not created')
for registration in open_reg, done_reg:
with self.subTest(registration_state=registration.state, medium='mail'):
self.assertMailMailWEmails(
[formataddr((registration.name, registration.email.lower()))],
'outgoing',
)
with self.subTest(registration_state=registration.state, medium='sms'):
self.assertSMS(
self.env['res.partner'],
registration.phone,
None,
)
self.assertEqual(len(self._new_mails), 2, 'Mails should not be sent to draft or cancel registrations')
self.assertEqual(len(self._new_sms), 2, 'SMS should not be sent to draft or cancel registrations')
self.assertEqual(test_event.seats_expected, 2, 'Wrong number of expected seats (attendees)')
self.assertEqual(test_event.seats_taken, 2, 'Wrong number of seats_taken')
self.assertEqual(mail_scheduler.filtered(lambda r: r.notification_type == 'mail').mail_count_done, 2,
'Wrong Emails Sent Count! Probably emails sent to unconfirmed attendees were not included into the Sent Count')
self.assertEqual(mail_scheduler.filtered(lambda r: r.notification_type == 'sms').mail_count_done, 2,
'Wrong SMS Sent Count! Probably SMS sent to unconfirmed attendees were not included into the Sent Count')
for scheduler in before:
self.assertEqual(
scheduler.mail_count_done, 2,
'Wrong Emails Sent Count! Probably emails sent to unconfirmed attendees were not included into the Sent Count'
)
@users('user_eventmanager')
def test_schedule_event_scalability(self):
""" Test scalability / iterative work on event-based schedulers """
test_event = self.env['event.event'].browse(self.test_event.ids)
registrations = self._create_registrations(test_event, 30)
registrations = registrations.sorted("id")
# check event-based schedulers
after_mail = test_event.event_mail_ids.filtered(lambda s: s.interval_type == "after_event" and s.notification_type == "mail")
self.assertEqual(len(after_mail), 1)
self.assertEqual(after_mail.mail_count_done, 0)
self.assertFalse(after_mail.mail_done)
after_sms = test_event.event_mail_ids.filtered(lambda s: s.interval_type == "after_event" and s.notification_type == "sms")
self.assertEqual(len(after_sms), 1)
self.assertEqual(after_sms.mail_count_done, 0)
self.assertFalse(after_sms.mail_done)
before_mail = test_event.event_mail_ids.filtered(lambda s: s.interval_type == "before_event" and s.notification_type == "mail")
self.assertEqual(len(before_mail), 1)
self.assertEqual(before_mail.mail_count_done, 0)
self.assertFalse(before_mail.mail_done)
before_sms = test_event.event_mail_ids.filtered(lambda s: s.interval_type == "before_event" and s.notification_type == "sms")
self.assertEqual(len(before_sms), 1)
self.assertEqual(before_sms.mail_count_done, 0)
self.assertFalse(before_sms.mail_done)
# setup batch and cron limit sizes to check iterative behavior
batch_size, cron_limit = 5, 20
self.env["ir.config_parameter"].sudo().set_param("mail.batch_size", batch_size)
self.env["ir.config_parameter"].sudo().set_param("mail.render.cron.limit", cron_limit)
# launch before event schedulers -> all communications are sent
current_now = self.event_date_begin - timedelta(days=1)
EventMail = type(self.env['event.mail'])
exec_origin = EventMail._execute_event_based_for_registrations
with (
patch.object(
EventMail, '_execute_event_based_for_registrations', autospec=True, wraps=EventMail, side_effect=exec_origin,
) as mock_exec,
self.mock_datetime_and_now(current_now),
self.mockSMSGateway(),
self.mock_mail_gateway(),
self.capture_triggers('event.event_mail_scheduler') as capture,
):
self.event_cron_id.method_direct_trigger()
self.assertFalse(after_mail.last_registration_id)
self.assertEqual(after_mail.mail_count_done, 0)
self.assertFalse(after_mail.mail_done)
self.assertFalse(after_sms.last_registration_id)
self.assertEqual(after_sms.mail_count_done, 0)
self.assertFalse(after_sms.mail_done)
# iterative work on registrations: only 20 (cron limit) are taken into account
self.assertEqual(before_mail.last_registration_id, registrations[19])
self.assertEqual(before_mail.mail_count_done, 20)
self.assertFalse(before_mail.mail_done)
self.assertEqual(before_sms.last_registration_id, registrations[19])
self.assertEqual(before_sms.mail_count_done, 20)
self.assertFalse(before_sms.mail_done)
self.assertEqual(mock_exec.call_count, 8, "Batch of 5 to make 20 registrations: 4 calls / scheduler")
# cron should have been triggered for the remaining registrations
self.assertSchedulerCronTriggers(capture, [current_now] * 2)
# relaunch to close scheduler
with (
self.mock_datetime_and_now(current_now),
self.mockSMSGateway(),
self.mock_mail_gateway(),
self.capture_triggers('event.event_mail_scheduler') as capture,
):
self.event_cron_id.method_direct_trigger()
self.assertEqual(before_mail.last_registration_id, registrations[-1])
self.assertEqual(before_mail.mail_count_done, 30)
self.assertTrue(before_mail.mail_done)
self.assertEqual(before_sms.last_registration_id, registrations[-1])
self.assertEqual(before_sms.mail_count_done, 30)
self.assertTrue(before_sms.mail_done)
self.assertFalse(capture.records)
# launch after event schedulers -> all communications are sent
current_now = self.event_date_end + timedelta(hours=1)
with (
self.mock_datetime_and_now(current_now),
self.mockSMSGateway(),
self.mock_mail_gateway(),
self.capture_triggers('event.event_mail_scheduler') as capture,
):
self.event_cron_id.method_direct_trigger()
# iterative work on registrations: only 20 (cron limit) are taken into account
self.assertEqual(after_mail.last_registration_id, registrations[19])
self.assertEqual(after_mail.mail_count_done, 20)
self.assertFalse(after_mail.mail_done)
self.assertEqual(after_sms.last_registration_id, registrations[19])
self.assertEqual(after_sms.mail_count_done, 20)
self.assertFalse(after_sms.mail_done)
self.assertEqual(mock_exec.call_count, 8, "Batch of 5 to make 20 registrations: 4 calls / scheduler")
# cron should have been triggered for the remaining registrations
self.assertSchedulerCronTriggers(capture, [current_now] * 2)
# relaunch to close scheduler
with (
self.mock_datetime_and_now(current_now),
self.mockSMSGateway(),
self.mock_mail_gateway(),
self.capture_triggers('event.event_mail_scheduler') as capture,
):
self.event_cron_id.method_direct_trigger()
self.assertEqual(after_mail.last_registration_id, registrations[-1])
self.assertEqual(after_mail.mail_count_done, 30)
self.assertTrue(after_mail.mail_done)
self.assertEqual(after_sms.last_registration_id, registrations[-1])
self.assertEqual(after_sms.mail_count_done, 30)
self.assertTrue(after_sms.mail_done)
self.assertFalse(capture.records)
@users('user_eventmanager')
def test_schedule_subscription_scalability(self):
""" Test scalability / iterative work on subscription-based schedulers """
test_event = self.env['event.event'].browse(self.test_event.ids)
sub_mail = test_event.event_mail_ids.filtered(lambda s: s.interval_type == "after_sub" and s.interval_unit == "now" and s.notification_type == "mail")
self.assertEqual(len(sub_mail), 1)
self.assertEqual(sub_mail.mail_count_done, 0)
sub_sms = test_event.event_mail_ids.filtered(lambda s: s.interval_type == "after_sub" and s.interval_unit == "now" and s.notification_type == "sms")
self.assertEqual(len(sub_sms), 1)
self.assertEqual(sub_sms.mail_count_done, 0)
# setup batch and cron limit sizes to check iterative behavior
batch_size, cron_limit = 5, 20
self.env["ir.config_parameter"].sudo().set_param("mail.batch_size", batch_size)
self.env["ir.config_parameter"].sudo().set_param("mail.render.cron.limit", cron_limit)
# create registrations -> each one receives its on subscribe communication
EventMailRegistration = type(self.env['event.mail.registration'])
exec_origin = EventMailRegistration._execute_on_registrations
with patch.object(
EventMailRegistration, '_execute_on_registrations', autospec=True, wraps=EventMailRegistration, side_effect=exec_origin,
) as mock_exec, \
self.mock_datetime_and_now(self.reference_now + timedelta(hours=1)), \
self.mockSMSGateway(), \
self.mock_mail_gateway(), \
self.capture_triggers('event.event_mail_scheduler') as capture:
self._create_registrations(test_event, 30)
# iterative work on registrations: only 20 (cron limit) are taken into account
self.assertEqual(sub_mail.mail_count_done, 20)
self.assertEqual(sub_sms.mail_count_done, 20)
self.assertEqual(mock_exec.call_count, 8, "Batch of 5 to make 20 registrations: 4 calls / scheduler")
# cron should have been triggered for the remaining registrations
self.assertSchedulerCronTriggers(capture, [self.reference_now + timedelta(hours=1)] * 2)
# iterative work on registrations, force cron to close those
with (
patch.object(
EventMailRegistration, '_execute_on_registrations', autospec=True, wraps=EventMailRegistration, side_effect=exec_origin,
) as mock_exec,
self.mock_datetime_and_now(self.reference_now + timedelta(hours=1)),
self.mockSMSGateway(),
self.mock_mail_gateway(),
self.capture_triggers('event.event_mail_scheduler') as capture,
):
self.event_cron_id.method_direct_trigger()
# finished sending communications
self.assertEqual(sub_mail.mail_count_done, 30)
self.assertEqual(sub_sms.mail_count_done, 30)
self.assertFalse(capture.records)
self.assertEqual(mock_exec.call_count, 4, "Batch of 5 to make 10 remaining registrations: 2 calls / scheduler")
@tagged('event_mail', 'post_install', '-at_install')
class TestEventSaleMail(TestEventFullCommon):
def test_event_mail_on_sale_confirmation(self):
"""Test that a mail is sent to the customer when a sale order is confirmed."""
ticket = self.test_event.event_ticket_ids[0]
self.test_event.env.company.partner_id.email = 'test.email@test.example.com'
order_line_vals = {
"event_id": self.test_event.id,
"event_ticket_id": ticket.id,
"product_id": ticket.product_id.id,
"product_uom_qty": 1,
}
self.customer_so.write({"order_line": [(0, 0, order_line_vals)]})
# check sale mail configuration
aftersub = self.test_event.event_mail_ids.filtered(
lambda m: m.interval_type == "after_sub"
)
self.assertTrue(aftersub)
aftersub.template_ref.email_from = "{{ (object.event_id.organizer_id.email_formatted or object.event_id.user_id.email_formatted or '') }}"
self.assertEqual(self.test_event.organizer_id, self.test_event.env.company.partner_id)
registration = self.env["event.registration"].create(
{
**self.website_customer_data[0],
"partner_id": self.event_customer.id,
"sale_order_line_id": self.customer_so.order_line[0].id,
}
)
self.assertEqual(self.test_event.registration_ids, registration)
self.assertEqual(self.customer_so.state, "draft")
self.assertEqual(registration.state, "draft")
with self.mock_mail_gateway():
self.customer_so.action_confirm()
# mail send is done when writing state value, hence flushing for the test
registration.flush_recordset()
self.assertEqual(self.customer_so.state, "sale")
self.assertEqual(registration.state, "open")
# Ensure mails are sent to customers right after subscription
self.assertMailMailWRecord(
registration,
[self.event_customer.id],
"outgoing",
author=self.test_event.organizer_id,
fields_values={
"email_from": self.test_event.organizer_id.email_formatted,
},
)
def test_registration_template_body_translation(self):
self.env['res.lang']._activate_lang('fr_BE')
test_event = self.test_event
self.partners[0].lang = 'fr_BE'
self.env.ref('event.event_subscription').with_context(lang='fr_BE').body_html = 'Bonjour'
with self.mock_mail_gateway(mail_unlink_sent=False):
self.env['event.registration'].create({
'event_id': test_event.id,
'partner_id': self.partners[0].id
})
self.assertEqual(self._new_mails[0].body_html, "<p>Bonjour</p>")

View file

@ -5,6 +5,7 @@ from datetime import datetime, timedelta
from odoo.addons.test_event_full.tests.common import TestEventFullCommon
from odoo.exceptions import AccessError
from odoo.fields import Command
from odoo.tests import tagged
from odoo.tests.common import users
from odoo.tools import mute_logger
@ -55,7 +56,7 @@ class TestEventSecurity(TestEventFullCommon):
def test_event_access_event_registration(self):
# Event: read ok
event = self.test_event.with_user(self.env.user)
event.read(['name', 'user_id', 'kanban_state_label'])
event.read(['name', 'user_id', 'kanban_state'])
# Event: read only
with self.assertRaises(AccessError):
@ -77,7 +78,7 @@ class TestEventSecurity(TestEventFullCommon):
def test_event_access_event_user(self):
# Event
event = self.test_event.with_user(self.env.user)
event.read(['name', 'user_id', 'kanban_state_label'])
event.read(['name', 'user_id', 'kanban_state'])
event.write({'name': 'New name'})
self.env['event.event'].create({
'name': 'Event',
@ -133,7 +134,7 @@ class TestEventSecurity(TestEventFullCommon):
event_type.unlink()
# Settings access rights required to enable some features
self.user_eventmanager.write({'groups_id': [
self.user_eventmanager.write({'group_ids': [
(3, self.env.ref('base.group_system').id),
(4, self.env.ref('base.group_erp_manager').id)
]})
@ -142,6 +143,45 @@ class TestEventSecurity(TestEventFullCommon):
})
event_config.execute()
def test_event_question_access(self):
""" Check that some user groups have access to questions and answers only if they are linked to at
least one published event. """
question = self.env['event.question'].create({
"title": "Question",
"event_ids": [Command.create({
'name': 'Unpublished Event',
'is_published': False,
})]
})
answer = self.env['event.question.answer'].create({
"name": "Answer",
"question_id": question.id,
})
restricted_users = [self.user_employee, self.user_portal, self.user_public]
unrestricted_users = [self.user_eventmanager, self.user_eventuser]
for user in restricted_users:
with self.assertRaises(AccessError, msg=f'{user.name} should not have access to questions of unpublished events'):
question.with_user(user).read(['title'])
with self.assertRaises(AccessError, msg=f'{user.name} should not have access to answers of unpublished events'):
answer.with_user(user).read(['name'])
for user in unrestricted_users:
question.with_user(user).read(['title'])
answer.with_user(user).read(['name'])
# To check the access of user groups to questions and answers linked to at least one published event.
self.env['event.event'].create({
'name': 'Published Event',
'is_published': True,
'question_ids': [Command.set(question.ids)],
})
# Check that all user groups have access to questions and answers linked to at least one published event.
for user in restricted_users + unrestricted_users:
question.with_user(user).read(['title'])
answer.with_user(user).read(['name'])
def test_implied_groups(self):
"""Test that the implied groups are correctly set.

View file

@ -6,8 +6,7 @@ from freezegun import freeze_time
from odoo.addons.test_event_full.tests.common import TestEventFullCommon
from odoo.addons.website.tests.test_performance import UtilPerf
from odoo.tests.common import users, warmup, Form
from odoo.tests import tagged
from odoo.tests import Form, users, warmup, tagged
@tagged('event_performance', 'post_install', '-at_install', '-standard')
@ -17,6 +16,9 @@ class EventPerformanceCase(TestEventFullCommon):
super(EventPerformanceCase, self).setUp()
# patch registry to simulate a ready environment
self.patch(self.env.registry, 'ready', True)
# we don't use mock_mail_gateway thus want to mock smtp to test the stack
self._mock_smtplib_connection()
self._flush_tracking()
def _flush_tracking(self):
@ -52,7 +54,7 @@ class TestEventPerformance(EventPerformanceCase):
batch_size = 20
# simple without type involved + website
with freeze_time(self.reference_now), self.assertQueryCount(event_user=5368): # tef 4944 / com 4943
with freeze_time(self.reference_now), self.assertQueryCount(event_user=3418): # tef 3316 / com 3315
self.env.cr._now = self.reference_now # force create_date to check schedulers
event_values = [
dict(self.event_base_vals,
@ -60,7 +62,7 @@ class TestEventPerformance(EventPerformanceCase):
)
for x in range(batch_size)
]
self.env['event.event'].create(event_values)
self.env['event.event'].with_context(lang='en_US').create(event_values)
@users('event_user')
@warmup
@ -70,7 +72,7 @@ class TestEventPerformance(EventPerformanceCase):
event_type = self.env['event.type'].browse(self.test_event_type.ids)
# complex with type
with freeze_time(self.reference_now), self.assertQueryCount(event_user=439): # 439
with freeze_time(self.reference_now), self.assertQueryCount(event_user=432): # tef 432
self.env.cr._now = self.reference_now # force create_date to check schedulers
event_values = [
dict(self.event_base_vals,
@ -89,7 +91,7 @@ class TestEventPerformance(EventPerformanceCase):
event_type = self.env['event.type'].browse(self.test_event_type.ids)
# complex with type + website
with freeze_time(self.reference_now), self.assertQueryCount(event_user=5480): # tef 5056 / com 5055
with freeze_time(self.reference_now), self.assertQueryCount(event_user=3522): # tef 3420 / com 3419
self.env.cr._now = self.reference_now # force create_date to check schedulers
event_values = [
dict(self.event_base_vals,
@ -97,7 +99,7 @@ class TestEventPerformance(EventPerformanceCase):
)
for x in range(batch_size)
]
self.env['event.event'].create(event_values)
self.env['event.event'].with_context(lang='en_US').create(event_values)
@users('event_user')
@ -107,7 +109,7 @@ class TestEventPerformance(EventPerformanceCase):
has_social = 'social_menu' in self.env['event.event'] # otherwise view may crash in enterprise
# no type, no website
with freeze_time(self.reference_now), self.assertQueryCount(event_user=206): # tef 160 / com 160
with freeze_time(self.reference_now), self.assertQueryCount(event_user=108): # tef 103 / com 103
self.env.cr._now = self.reference_now # force create_date to check schedulers
# Require for `website_menu` to be visible
# <div name="event_menu_configuration" groups="base.group_no_one">
@ -128,7 +130,7 @@ class TestEventPerformance(EventPerformanceCase):
has_social = 'social_menu' in self.env['event.event'] # otherwise view may crash in enterprise
# no type, website
with freeze_time(self.reference_now), self.assertQueryCount(event_user=666): # tef 565 / com 566
with freeze_time(self.reference_now), self.assertQueryCount(event_user=429): # tef 379 / com 380
self.env.cr._now = self.reference_now # force create_date to check schedulers
# Require for `website_menu` to be visible
# <div name="event_menu_configuration" groups="base.group_no_one">
@ -150,7 +152,7 @@ class TestEventPerformance(EventPerformanceCase):
has_social = 'social_menu' in self.env['event.event'] # otherwise view may crash in enterprise
# type and website
with freeze_time(self.reference_now), self.assertQueryCount(event_user=692): # tef 593 / com 596
with freeze_time(self.reference_now), self.assertQueryCount(event_user=472): # tef 426 / com 428
self.env.cr._now = self.reference_now # force create_date to check schedulers
# Require for `website_menu` to be visible
# <div name="event_menu_configuration" groups="base.group_no_one">
@ -168,7 +170,7 @@ class TestEventPerformance(EventPerformanceCase):
def test_event_create_single_notype(self):
""" Test a single event creation """
# simple without type involved
with freeze_time(self.reference_now), self.assertQueryCount(event_user=31): # 31
with freeze_time(self.reference_now), self.assertQueryCount(event_user=31): # tef 31
self.env.cr._now = self.reference_now # force create_date to check schedulers
event_values = dict(
self.event_base_vals,
@ -181,13 +183,13 @@ class TestEventPerformance(EventPerformanceCase):
def test_event_create_single_notype_website(self):
""" Test a single event creation """
# simple without type involved + website
with freeze_time(self.reference_now), self.assertQueryCount(event_user=352): # tef 327 / com 326
with freeze_time(self.reference_now), self.assertQueryCount(event_user=242): # tef 228 / com 234
self.env.cr._now = self.reference_now # force create_date to check schedulers
event_values = dict(
self.event_base_vals,
website_menu=True
)
self.env['event.event'].create([event_values])
self.env['event.event'].with_context(lang='en_US').create([event_values])
@users('event_user')
@warmup
@ -196,7 +198,7 @@ class TestEventPerformance(EventPerformanceCase):
event_type = self.env['event.type'].browse(self.test_event_type.ids)
# complex with type
with freeze_time(self.reference_now), self.assertQueryCount(event_user=58): # 58
with freeze_time(self.reference_now), self.assertQueryCount(event_user=52): # tef 52
self.env.cr._now = self.reference_now # force create_date to check schedulers
event_values = dict(
self.event_base_vals,
@ -212,13 +214,13 @@ class TestEventPerformance(EventPerformanceCase):
event_type = self.env['event.type'].browse(self.test_event_type.ids)
# complex with type + website
with freeze_time(self.reference_now), self.assertQueryCount(event_user=387): # tef 362 / com 361
with freeze_time(self.reference_now), self.assertQueryCount(event_user=274): # tef 266 / com 265
self.env.cr._now = self.reference_now # force create_date to check schedulers
event_values = dict(
self.event_base_vals,
event_type_id=event_type.id,
)
self.env['event.event'].create([event_values])
self.env['event.event'].with_context(lang='en_US').create([event_values])
@tagged('event_performance', 'registration_performance', 'post_install', '-at_install', '-standard')
@ -234,7 +236,7 @@ class TestRegistrationPerformance(EventPerformanceCase):
"""
event = self.env['event.event'].browse(self.test_event.ids)
with freeze_time(self.reference_now), self.assertQueryCount(event_user=720): # tef only: 674? - com runbot 716 - ent runbot 719
with freeze_time(self.reference_now), self.assertQueryCount(event_user=638): # tef 633 / com 636
self.env.cr._now = self.reference_now # force create_date to check schedulers
registration_values = [
dict(reg_data,
@ -258,7 +260,7 @@ class TestRegistrationPerformance(EventPerformanceCase):
"""
event = self.env['event.event'].browse(self.test_event.ids)
with freeze_time(self.reference_now), self.assertQueryCount(event_user=210): # tef 167 / com runbot 206
with freeze_time(self.reference_now), self.assertQueryCount(event_user=165): # tef 164 / com runbot 163
self.env.cr._now = self.reference_now # force create_date to check schedulers
registration_values = [
dict(reg_data,
@ -280,7 +282,7 @@ class TestRegistrationPerformance(EventPerformanceCase):
form like) """
event = self.env['event.event'].browse(self.test_event.ids)
with freeze_time(self.reference_now), self.assertQueryCount(event_user=731): # tef only: 685? - com runbot 727
with freeze_time(self.reference_now), self.assertQueryCount(event_user=651): # tef 647 - com 649
self.env.cr._now = self.reference_now # force create_date to check schedulers
registration_values = [
dict(reg_data,
@ -301,12 +303,11 @@ class TestRegistrationPerformance(EventPerformanceCase):
""" Test a single registration creation using Form """
event = self.env['event.event'].browse(self.test_event.ids)
with freeze_time(self.reference_now), self.assertQueryCount(event_user=231): # tef only: 210? - com runbot 216
with freeze_time(self.reference_now), self.assertQueryCount(event_user=145): # tef 140 / com 143
self.env.cr._now = self.reference_now # force create_date to check schedulers
with Form(self.env['event.registration']) as reg_form:
reg_form.event_id = event
reg_form.email = 'email.00@test.example.com'
reg_form.mobile = '0456999999'
reg_form.name = 'My Customer'
reg_form.phone = '0456000000'
_registration = reg_form.save()
@ -317,7 +318,7 @@ class TestRegistrationPerformance(EventPerformanceCase):
""" Test a single registration creation using Form """
event = self.env['event.event'].browse(self.test_event.ids)
with freeze_time(self.reference_now), self.assertQueryCount(event_user=233): # tef only: 213? - com runbot 217
with freeze_time(self.reference_now), self.assertQueryCount(event_user=146): # tef 141 / com 144
self.env.cr._now = self.reference_now # force create_date to check schedulers
with Form(self.env['event.registration']) as reg_form:
reg_form.event_id = event
@ -330,7 +331,7 @@ class TestRegistrationPerformance(EventPerformanceCase):
""" Test a single registration creation using Form """
event = self.env['event.event'].browse(self.test_event.ids)
with freeze_time(self.reference_now), self.assertQueryCount(event_user=124): # tef 107 / com 109
with freeze_time(self.reference_now), self.assertQueryCount(event_user=63): # tef 61 / com 61
self.env.cr._now = self.reference_now # force create_date to check schedulers
with Form(self.env['event.registration'].with_context(event_lead_rule_skip=True)) as reg_form:
reg_form.event_id = event
@ -344,7 +345,7 @@ class TestRegistrationPerformance(EventPerformanceCase):
event = self.env['event.event'].browse(self.test_event.ids)
# simple customer data
with freeze_time(self.reference_now), self.assertQueryCount(event_user=143): # tef only: 135? - com runbot 140
with freeze_time(self.reference_now), self.assertQueryCount(event_user=122): # tef 118 / com 120
self.env.cr._now = self.reference_now # force create_date to check schedulers
registration_values = dict(
self.customer_data[0],
@ -358,7 +359,7 @@ class TestRegistrationPerformance(EventPerformanceCase):
event = self.env['event.event'].browse(self.test_event.ids)
# partner-based customer
with freeze_time(self.reference_now), self.assertQueryCount(event_user=149): # tef only: 142? - com runbot 146
with freeze_time(self.reference_now), self.assertQueryCount(event_user=121): # tef 117 / com 120
self.env.cr._now = self.reference_now # force create_date to check schedulers
registration_values = {
'event_id': event.id,
@ -373,7 +374,7 @@ class TestRegistrationPerformance(EventPerformanceCase):
event = self.env['event.event'].browse(self.test_event.ids)
# partner-based customer
with freeze_time(self.reference_now), self.assertQueryCount(event_user=46): # tef 41 / com 43
with freeze_time(self.reference_now), self.assertQueryCount(event_user=39): # tef 38 / com 38
self.env.cr._now = self.reference_now # force create_date to check schedulers
registration_values = {
'event_id': event.id,
@ -388,7 +389,7 @@ class TestRegistrationPerformance(EventPerformanceCase):
event = self.env['event.event'].browse(self.test_event.ids)
# website customer data
with freeze_time(self.reference_now), self.assertQueryCount(event_user=151): # tef only: 142? - com runbot 146
with freeze_time(self.reference_now), self.assertQueryCount(event_user=126): # tef 122 / com 124
self.env.cr._now = self.reference_now # force create_date to check schedulers
registration_values = dict(
self.website_customer_data[0],
@ -429,7 +430,6 @@ class TestOnlineEventPerformance(EventPerformanceCase, UtilPerf):
])
def _test_url_open(self, url):
url += ('?' not in url and '?' or '') + '&debug=disable-t-cache'
return self.url_open(url)
@warmup
@ -437,7 +437,7 @@ class TestOnlineEventPerformance(EventPerformanceCase, UtilPerf):
# website customer data
with freeze_time(self.reference_now):
self.authenticate('user_eventmanager', 'user_eventmanager')
with self.assertQueryCount(default=36): # tef 35
with self.assertQueryCount(default=35): # tef 34
self._test_url_open('/event/%i' % self.test_event.id)
@warmup
@ -445,7 +445,7 @@ class TestOnlineEventPerformance(EventPerformanceCase, UtilPerf):
# website customer data
with freeze_time(self.reference_now):
self.authenticate(None, None)
with self.assertQueryCount(default=27):
with self.assertQueryCount(default=25):
self._test_url_open('/event/%i' % self.test_event.id)
@warmup
@ -453,7 +453,7 @@ class TestOnlineEventPerformance(EventPerformanceCase, UtilPerf):
# website customer data
with freeze_time(self.reference_now):
self.authenticate('user_eventmanager', 'user_eventmanager')
with self.assertQueryCount(default=39): # tef 38
with self.assertQueryCount(default=43): # tef 42
self._test_url_open('/event')
@warmup
@ -461,23 +461,22 @@ class TestOnlineEventPerformance(EventPerformanceCase, UtilPerf):
# website customer data
with freeze_time(self.reference_now):
self.authenticate(None, None)
with self.assertQueryCount(default=28):
with self.assertQueryCount(default=39):
self._test_url_open('/event')
# @warmup
# def test_register_public(self):
# with freeze_time(self.reference_now + timedelta(hours=3)): # be sure sales has started
# self.assertTrue(self.test_event.event_registrations_started)
# self.authenticate(None, None)
# with self.assertQueryCount(default=99999): # tef only: 1110
# self.browser_js(
# '/event/%i/register' % self.test_event.id,
# 'odoo.__DEBUG__.services["web_tour.tour"].run("wevent_performance_register")',
# 'odoo.__DEBUG__.services["web_tour.tour"].tours.wevent_performance_register.ready',
# login=None,
# timeout=200,
# )
@warmup
def test_register_public(self):
with freeze_time(self.reference_now + timedelta(hours=3)): # be sure sales has started
self.assertTrue(self.test_event.event_registrations_started)
self.authenticate(None, None)
with self.assertQueryCount(default=1197): # tef: 1197
self.start_tour(
'/event/%i/register' % self.test_event.id,
'wevent_performance_register',
login=None,
timeout=200,
)
# # minimal checkup, to be improved in future tests independently from performance
# self.assertEqual(len(self.test_event.registration_ids), 3)
# self.assertEqual(len(self.test_event.registration_ids.visitor_id), 1)
# minimal checkup, to be improved in future tests independently from performance
self.assertEqual(len(self.test_event.registration_ids), 3)
self.assertEqual(len(self.test_event.registration_ids.visitor_id), 1)

View file

@ -0,0 +1,41 @@
from odoo.addons.test_event_full.tests.common import TestWEventCommon
from odoo.tests import tagged
from odoo.tests.common import users
@tagged('event_online', 'post_install', '-at_install')
class TestWEventMenu(TestWEventCommon):
@users('admin')
def test_seo_data(self):
"""Test SEO data for submenus on event website page"""
self.assertFalse(self.event.website_meta_title, 'Event should initially have no meta title')
self.event.write({
'website_meta_title': 'info',
})
self.assertTrue(self.event.website_meta_title, 'Event should have a meta title after writing')
menus = [
('booth_menu_ids', 'Get a Booth'),
('exhibitor_menu_ids', 'Exhibitor'),
('community_menu_ids', 'Leaderboard'),
('track_menu_ids', 'Talks'),
('track_menu_ids', 'Agenda'),
('track_proposal_menu_ids', 'Talk Proposal'),
]
for menu_field, menu_name in menus:
menu = self.event[menu_field]
if menu_field == 'track_menu_ids':
menu_url = '/track' if menu_name == 'Talks' else '/agenda'
menu = self.event[menu_field].filtered(lambda menu: menu.menu_id.url.endswith(menu_url))
self.assertFalse(menu.website_meta_title, f"{menu_name} page should initially have no meta title")
menu.write({'website_meta_title': menu_name})
web_page = self.url_open(menu.menu_id.url)
self.assertTrue(menu.website_meta_title, f"{menu_name} page should have a meta title after writing")
self.assertIn(f"<title>{menu.website_meta_title}</title>", web_page.text)

View file

@ -4,6 +4,7 @@
from freezegun import freeze_time
from odoo import tests
from odoo.addons.mail.tests.common import mail_new_test_user
from odoo.addons.test_event_full.tests.common import TestWEventCommon
@ -11,13 +12,9 @@ from odoo.addons.test_event_full.tests.common import TestWEventCommon
class TestWEventRegister(TestWEventCommon):
def test_register(self):
self.env.company.country_id = self.env.ref('base.us')
with freeze_time(self.reference_now, tick=True):
self.browser_js(
'/event',
'odoo.__DEBUG__.services["web_tour.tour"].run("wevent_register")',
'odoo.__DEBUG__.services["web_tour.tour"].tours.wevent_register.ready',
login=None
)
self.start_tour('/event', 'wevent_register', login=None)
new_registrations = self.event.registration_ids
visitor = new_registrations.visitor_id
@ -40,5 +37,15 @@ class TestWEventRegister(TestWEventCommon):
self.assertEqual(visitor.display_name, "Raoulette Poiluchette")
self.assertEqual(visitor.event_registration_ids, new_registrations)
self.assertEqual(visitor.partner_id, self.env['res.partner'])
self.assertEqual(visitor.mobile, "0456112233")
self.assertEqual(visitor.email, "raoulette@example.com")
def test_internal_user_register(self):
mail_new_test_user(
self.env,
name='User Internal',
login='user_internal',
email='user_internal@example.com',
groups='base.group_user',
)
with freeze_time(self.reference_now, tick=True):
self.start_tour('/event', 'wevent_register', login='user_internal')