19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:32:12 +01:00
parent 79f83631d5
commit 73afc09215
6267 changed files with 1534193 additions and 1130106 deletions

View file

@ -1,76 +1,87 @@
odoo.define('website_event_sale.tour.WebsiteEventSaleTourMethods', function (require) {
'use strict';
import * as wsTourUtils from '@website_sale/js/tours/tour_utils';
function changePricelist(pricelistName) {
return [
{
content: "Go to page Shop",
trigger: '.nav-link:contains("Shop")',
},
{
content: "Toggle Pricelist",
trigger: '.o_pricelist_dropdown > .dropdown-toggle',
run: 'click',
},
{
content: `Activate Pricelist ${pricelistName}`,
trigger: `.dropdown-item:contains(${pricelistName})`,
run: 'click',
},
{
content: 'Wait for pricelist to load',
trigger: `.dropdown-toggle:contains(${pricelistName})`,
run: function () {},
},
];
const closeModal = {
content: "Close the ticket picking modal",
trigger: `.modal.modal_shown .modal-content button:contains("Close")`,
run: "click",
};
export function changePricelist(pricelistName) {
return [
{
content: "Go to page Shop",
trigger: '.nav-link:contains("Shop")',
run: "click",
expectUnloadPage: true,
},
{
content: "Toggle Pricelist",
trigger: '.o_pricelist_dropdown > .dropdown-toggle',
run: 'click',
},
{
content: `Activate Pricelist ${pricelistName}`,
trigger: `.dropdown-item:contains(${pricelistName})`,
run: 'click',
expectUnloadPage: true,
},
{
content: 'Wait for pricelist to load',
trigger: `.dropdown-toggle:contains(${pricelistName})`,
},
];
}
function checkPriceEvent(eventName, price, close = true) {
const steps = [
{
content: "Go to page Event",
trigger: '.nav-link:contains("Event")',
run: "click",
expectUnloadPage: true,
},
{
content: "Open the Pycon event",
trigger: `.o_wevent_events_list a:contains(${eventName})`,
run: "click",
expectUnloadPage: true,
},
{
content: "Open the ticket picking modal",
trigger: `button:contains("Register")`,
run: "click",
},
{
content: "Verify Price",
trigger: `.oe_currency_value:contains(${price})`,
},
];
if (close) {
steps.push(closeModal);
}
function checkPriceEvent(eventName, price) {
return [
{
content: "Go to page Event",
trigger: '.nav-link:contains("Event")',
},
{
content: "Open the Pycon event",
trigger: `.o_wevent_events_list a:contains(${eventName})`,
},
{
content: "Verify Price",
trigger: `.oe_currency_value:contains(${price})`,
run: function () {}, // it's a check
},
]
}
function checkPriceDiscountEvent(eventName, price, discount) {
return [
...checkPriceEvent(eventName, price),
{
content: "Verify Price before discount",
trigger: `del:contains(${discount})`,
run: function () {}, // it's a check
},
]
}
function checkPriceCart(price) {
return [
{
content: "Go to page Cart",
trigger: '.fa-shopping-cart',
},
{
content: "Verify Price",
trigger: `[id=order_total] .oe_currency_value:contains(${price})`,
run: function () {}, // it's a check
},
]
}
const getPriceListChecksSteps = function ({pricelistName, eventName, price, priceBeforeDiscount=false}) {
const checkPriceSteps = priceBeforeDiscount ? checkPriceDiscountEvent(eventName, price, priceBeforeDiscount) : checkPriceEvent(eventName, price);
return [
...changePricelist(pricelistName),
...checkPriceSteps,
...checkPriceCart(price),
]
}
return { getPriceListChecksSteps, changePricelist, checkPriceCart }
});
return steps;
}
function checkPriceDiscountEvent(eventName, price, discount) {
return [
...checkPriceEvent(eventName, price, false),
{
content: "Verify Price before discount",
trigger: `del:contains(${discount})`,
},
closeModal,
];
}
export function checkPriceCart(price) {
return [
wsTourUtils.goToCart(),
...wsTourUtils.assertCartAmounts({total: price}),
]
}
export const getPriceListChecksSteps = function ({pricelistName, eventName, price, priceBeforeDiscount=false}) {
const checkPriceSteps = priceBeforeDiscount ? checkPriceDiscountEvent(eventName, price, priceBeforeDiscount) : checkPriceEvent(eventName, price);
return [
...changePricelist(pricelistName),
...checkPriceSteps,
...checkPriceCart(price),
]
}
export default { getPriceListChecksSteps, changePricelist, checkPriceCart }

View file

@ -1,89 +1,122 @@
odoo.define('website_event_sale.tour', function (require) {
'use strict';
import { registry } from "@web/core/registry";
import * as wsTourUtils from "@website_sale/js/tours/tour_utils";
var tour = require('web_tour.tour');
tour.register('event_buy_tickets', {
test: true,
url: '/event',
},
[
registry.category("web_tour.tours").add("event_buy_tickets", {
url: "/event",
steps: () => [
{
content: "Go to the `Events` page",
trigger: 'a[href*="/event"]:contains("Conference for Architects TEST"):first',
run: "click",
expectUnloadPage: true,
},
{
content: "Select 1 unit of `Standard` ticket type",
extra_trigger: '#wrap:not(:has(a[href*="/event"]:contains("Conference for Architects")))',
trigger: 'select:eq(0)',
run: 'text 1',
content: "Open the register modal",
trigger: 'button:contains("Register")',
run: "click",
},
{
content: "Select 2 units of `VIP` ticket type",
extra_trigger: 'select:eq(0):has(option:contains(1):propSelected)',
trigger: 'select:eq(1)',
run: 'text 2',
trigger: '#wrap:not(:has(a[href*="/event"]:contains("Conference for Architects")))',
},
{
content: "Try reaching maximum `Standard` ticket orderable",
trigger: ".modal input:eq(1)",
run: "edit 1234",
},
{
// The input number should be changed to EVENT_MAX_TICKETS without particular conditions (EVENT_MAX_TICKETS < 1234)
trigger: "div.o_wevent_ticket_selector:contains('Max.') input.form-control",
},
{
content: "Reset to 0",
trigger: ".modal input:eq(1)",
run: "edit 0"
},
{
content: "Add 1 unit of `Standard` ticket type thanks to the spinner",
trigger: "button[data-increment-type*='plus']",
run: "click",
},
{
content: "Try reaching maximum `VIP` ticket orderable",
trigger: ".modal input:eq(2)",
run: "edit 2002",
},
{
// The input number should be changed to min(limit per order, seats available) (11 < 12 < 2002)
trigger: "div.o_wevent_ticket_selector:contains('VIP'):contains('11') input.form-control",
},
{
content: "Edit 2 units of `VIP` ticket type",
trigger: ".modal input:eq(2)",
run: "edit 2",
},
{
content: "Click on `Order Now` button",
extra_trigger: 'select:eq(1):has(option:contains(2):propSelected)',
trigger: '.btn-primary:contains("Register")',
trigger: '.modal .btn-primary:contains("Register")',
run: "click",
},
{
content: "Fill attendees details",
trigger: 'form[id="attendee_registration"] .btn:contains("Continue")',
run: function () {
$("input[name='1-name']").val("Att1");
$("input[name='1-phone']").val("111 111");
$("input[name='1-email']").val("att1@example.com");
$("input[name='2-name']").val("Att2");
$("input[name='2-phone']").val("222 222");
$("input[name='2-email']").val("att2@example.com");
$("input[name='3-name']").val("Att3");
$("input[name='3-phone']").val("333 333");
$("input[name='3-email']").val("att3@example.com");
},
content: "Wait the modal is shown before continue",
trigger: ".modal.modal_shown.show form[id=attendee_registration]",
},
{
trigger: ".modal#modal_attendees_registration input[name*='1-email']",
run: "edit att1@example.com",
},
{
trigger: ".modal#modal_attendees_registration input[name*='1-phone']",
run: "edit 111 111",
},
{
trigger: ".modal#modal_attendees_registration input[name*='2-name']",
run: "edit Att2",
},
{
trigger: ".modal#modal_attendees_registration input[name*='2-phone']",
run: "edit 222 222",
},
{
trigger: ".modal#modal_attendees_registration input[name*='2-email']",
run: "edit att2@example.com",
},
{
trigger: ".modal#modal_attendees_registration input[name*='1-name']",
run: "edit Att1",
},
{
trigger: ".modal#modal_attendees_registration input[name*='3-name']",
run: "edit Att3",
},
{
trigger: ".modal#modal_attendees_registration input[name*='3-phone']",
run: "edit 333 333",
},
{
trigger: ".modal#modal_attendees_registration input[name*='3-email']",
run: "edit att3@example.com",
},
{
trigger:
".modal#modal_attendees_registration input[name*='1-name'], .modal#modal_attendees_registration input[name*='2-name'], .modal#modal_attendees_registration input[name*='3-name']",
},
{
trigger: "input[name*='1-name'], input[name*='2-name'], input[name*='3-name']",
},
{
content: "Validate attendees details",
extra_trigger: "input[name='1-name'], input[name='2-name'], input[name='3-name']",
trigger: 'button:contains("Continue")',
trigger: ".modal#modal_attendees_registration button[type=submit]",
run: "click",
expectUnloadPage: true,
},
{
content: "Check that the cart contains exactly 3 triggers",
trigger: 'a:has(.my_cart_quantity:containsExact(3)),.o_extra_menu_items .fa-plus',
run: function () {}, // it's a check
trigger: ".oe_cart:contains(payment method)",
},
{
content: "go to cart",
trigger: 'a:contains(Return to Cart)',
},
{
content: "Now click on `Process Checkout`",
extra_trigger: 'a:has(.my_cart_quantity):contains(3),#cart_products input.js_quantity[value="3"]',
trigger: '.btn-primary:contains("Process Checkout")'
},
{
content: "Check that the subtotal is 4,000.00 USD", // this test will fail if the currency of the main company is not USD
trigger: '#order_total_untaxed .oe_currency_value:contains("4,000.00")',
run: function () {}, // it's a check
},
{
content: "Select `Wire Transfer` payment method",
trigger: '#payment_method label:contains("Wire Transfer")',
},
{
content: "Pay",
//Either there are multiple payment methods, and one is checked, either there is only one, and therefore there are no radio inputs
// extra_trigger: '#payment_method input:checked,#payment_method:not(:has("input:radio:visible"))',
trigger: 'button[name="o_payment_submit_button"]:visible:not(:disabled)',
},
{
content: "Last step",
trigger: '.oe_website_sale_tx_status:contains("Please use the following transfer details")',
timeout: 30000,
}
]
);
wsTourUtils.goToCart({ quantity: 3 }),
wsTourUtils.goToCheckout(),
...wsTourUtils.assertCartAmounts({
untaxed: "4,000.00",
}),
...wsTourUtils.payWithTransfer({ expectUnloadPage: true, waitFinalizeYourPayment: true }),
],
});

View file

@ -1,92 +1,73 @@
odoo.define('website_event_sale.tour.last_ticket', function (require) {
'use strict';
import { registry } from "@web/core/registry";
import * as wsTourUtils from "@website_sale/js/tours/tour_utils";
var tour = require('web_tour.tour');
tour.register('event_buy_last_ticket', {
test: true,
registry.category("web_tour.tours").add('event_buy_last_ticket', {
url: '/event',
},[{
steps: () => [{
content: "Open the Last ticket test event page",
trigger: '.o_wevent_events_list a:contains("Last ticket test")',
run: "click",
expectUnloadPage: true,
},
{
content: "Show available Tickets",
trigger: '.btn-primary:contains("Register")',
content: "Open Registration Modal",
trigger: ".btn-primary:contains(Register)",
run: "click",
},
{
content: "Select 2 units of `VIP` ticket type",
extra_trigger: '#wrap:not(:has(a[href*="/event"]:contains("Last ticket test")))',
trigger: 'select:eq(0)',
run: 'text 2',
content: "Check the modal Tickets is opened",
trigger: "body:has(.modal:contains(Tickets))",
},
{
content: "Click on `Order Now` button",
extra_trigger: 'select:eq(0):has(option:contains(2):propSelected)',
trigger: '.a-submit:contains("Register")',
trigger: '#wrap:not(:has(a[href*="/event"]:contains("Last ticket test")))',
},
{
content: "Edit 2 units of `VIP` ticket type",
trigger: ".modal input:eq(1)",
run: "edit 2",
},
{
content: "Click on `Register` button",
trigger: ".modal .modal-footer button.btn-primary.a-submit:contains(Register)",
run: "click",
},
{
content: "Check the modal Attendees is opened",
trigger: ".modal:contains(Attendees):contains(Ticket #1):contains(Ticket #2)",
},
{
content: "Fill attendees details",
trigger: 'form[id="attendee_registration"] .btn:contains("Continue")',
trigger: 'form[id="attendee_registration"] .btn[type=submit]',
run: function () {
$("input[name='1-name']").val("Att1");
$("input[name='1-phone']").val("111 111");
$("input[name='1-email']").val("att1@example.com");
$("input[name='2-name']").val("Att2");
$("input[name='2-phone']").val("222 222");
$("input[name='2-email']").val("att2@example.com");
document.querySelector("input[name*='1-name']").value = "Att1";
document.querySelector("input[name*='1-phone']").value = "111 111";
document.querySelector("input[name*='1-email']").value = "att1@example.com";
document.querySelector("input[name*='2-name']").value = "Att2";
document.querySelector("input[name*='2-phone']").value = "222 222";
document.querySelector("input[name*='2-email']").value = "att2@example.com";
},
},
{
content: "Validate attendees details",
extra_trigger: "input[name='1-name'], input[name='2-name']",
trigger: 'button:contains("Continue")',
trigger: ".modal:contains(Attendees) button[type=submit]:contains(Go to Payment)",
run: "click",
expectUnloadPage: true,
},
{
content: "Fill address",
trigger: 'form.checkout_autoformat',
run: function () {
$("input[name='name']").val("test1");
$("input[name='email']").val("test@example.com");
$("input[name='phone']").val("111 111");
$("input[name='street']").val("street test 1");
$("input[name='city']").val("testCity");
$("input[name='zip']").val("123");
$('#country_id option:eq(1)').attr('selected', true);
...wsTourUtils.fillAdressForm(
{
name: "John Doe",
phone: "123456789",
email: "johndoe@gmail.com",
street: "1 rue de la paix",
city: "Paris",
zip: "75000",
},
},
{
content: "Validate address",
trigger: '.btn-primary:contains("Next")',
},
{
// if the seats_available checking logic is not correct,
// the shopping cart will be cleared when selling the last ticket
// the tour test will be failed here
content: "Select `Wire Transfer` payment method",
trigger: '#payment_method label:contains("Wire Transfer")',
},
// following steps are based on the website_sale_buy.js
{
content: "Pay",
//Either there are multiple payment methods, and one is checked, either there is only one, and therefore there are no radio inputs
extra_trigger: '#payment_method label:contains("Wire Transfer") input:checked,#payment_method:not(:has("input:radio:visible"))',
trigger: 'button[name="o_payment_submit_button"]:visible:not(:disabled)',
},
{
content: "payment finish",
trigger: '.oe_website_sale:contains("Please use the following transfer details")',
// Leave /shop/confirmation to prevent RPC loop to /shop/payment/get_status.
// The RPC could be handled in python while the tour is killed (and the session), leading to crashes
run: function () {
window.location.href = '/contactus'; // Redirect in JS to avoid the RPC loop (20x1sec)
},
timeout: 30000,
},
{
content: "wait page loaded",
trigger: 'h1:contains("Contact us")',
run: function () {}, // it's a check
},
]);
true,
),
...wsTourUtils.payWithTransfer({
redirect: true,
expectUnloadPage: true,
waitFinalizeYourPayment: true,
}),
],
});

View file

@ -1,57 +1,73 @@
odoo.define('website_event_sale.tour.event_sale_pricelists_different_currencies', function (require) {
'use strict';
import { registry } from "@web/core/registry";
import { getPriceListChecksSteps } from "@website_event_sale/../tests/tours/helpers/WebsiteEventSaleTourMethods";
const tour = require('web_tour.tour');
const { getPriceListChecksSteps } = require('website_event_sale.tour.WebsiteEventSaleTourMethods');
tour.register('event_sale_pricelists_different_currencies', {
test: true,
url: '/event',
},[
registry.category("web_tour.tours").add("event_sale_pricelists_different_currencies", {
url: "/event",
steps: () => [
// Register for tickets
{
content: "Open the Pycon event",
trigger: '.o_wevent_events_list a:contains("Pycon")',
run: "click",
expectUnloadPage: true,
},
{
content: "Register",
trigger: '.btn-primary:contains("Register")',
content: "Open the register modal",
trigger: 'button:contains("Register")',
run: "click",
},
{
content: "Fill attendees details",
trigger: 'form[id="attendee_registration"] .btn:contains("Continue")',
run: function () {
$("input[name='1-name']").val("Great Name");
$("input[name='1-phone']").val("111 111");
$("input[name='1-email']").val("great@name.com");
},
content: "Click on Register button inside modal",
trigger: '.modal .modal-footer button:contains("Register")',
run: "click",
},
{
content: "Wait the modal is shown before continue",
trigger: ".modal.modal_shown.show form[id=attendee_registration]",
},
{
trigger:
".modal#modal_attendees_registration:not(.o_inactive_modal) input[name*='1-name']",
run: "edit Great Name",
},
{
trigger:
".modal#modal_attendees_registration:not(.o_inactive_modal) input[name*='1-phone']",
run: "edit 111 111",
},
{
trigger:
".modal#modal_attendees_registration:not(.o_inactive_modal) input[name*='1-email']",
run: "edit great@name.com",
},
{
trigger:
".modal#modal_attendees_registration input[name*='1-name'], .modal#modal_attendees_registration input[name*='2-name']",
},
{
trigger: "input[name*='1-name'], input[name*='2-name']",
},
{
content: "Validate attendees details",
extra_trigger: "input[name='1-name'], input[name='2-name']",
trigger: 'button:contains("Continue")',
trigger:
".modal#modal_attendees_registration:not(.o_inactive_modal) button[type=submit]",
run: "click",
expectUnloadPage: true,
},
{
trigger: "body:not(:has(.modal#modal_attendees_registration))",
},
...getPriceListChecksSteps({
pricelistName: "EUR With Discount Included",
eventName: "Pycon",
price: "90.00",
}),
...getPriceListChecksSteps({
pricelistName: "EUR Without Discount Included",
eventName: "Pycon",
price: "90.00",
priceBeforeDiscount: "100.00",
}),
...getPriceListChecksSteps({
pricelistName: "EX With Discount Included",
eventName: "Pycon",
price: "900.00",
}),
...getPriceListChecksSteps({
pricelistName: "EX Without Discount Included",
eventName: "Pycon",
price: "900.00",
priceBeforeDiscount: "1,000.00",
}),
]);
],
});