19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:30:27 +01:00
parent d1963a3c3a
commit 2d3ee4855a
7430 changed files with 2687981 additions and 2965473 deletions

View file

@ -0,0 +1,39 @@
import { registry } from "@web/core/registry";
registry.category("web_tour.tours").add("mail_activity_date_format", {
steps: () => [
{
trigger: "button:contains('Activity')",
run: "click",
},
{
trigger: ".o_selection_badge span:contains('To-Do')",
run: "click",
},
{
trigger: "div[name='summary'] input",
run: "edit Go Party",
},
{
trigger: "button:contains('Save')",
run: "click",
},
{
trigger: ".o-mail-Activity:contains('Go Party')",
run: "click",
},
{
trigger: ".o-mail-Activity-info i",
run: "click",
},
// Format expected from the server for 9 AM at the first day of 2024 is date_format = "%d/%b/%y", time_format = "%I:%M:%S %p".
{
trigger:
".o-mail-Activity-details tr:contains('Created') td:contains('01/Jan/24 09:00:00 AM')",
},
{
// Default due date is 5 days after creation date.
trigger: ".o-mail-Activity-details tr:contains('Due on') td:contains('06/Jan/24')",
},
],
});

View file

@ -0,0 +1,29 @@
import { registry } from "@web/core/registry";
registry.category("web_tour.tours").add("can_create_channel_from_form_view", {
steps: () => [
{
trigger: ".o-mail-DiscussSidebarChannel-itemName:contains(OdooBot)",
run: "click",
},
{
trigger: ".o-mail-DiscussContent-threadName[title='OdooBot']",
},
{ trigger: "button[title='View or join channels']:not(:visible)", run: "click" },
{
trigger: ".o_control_panel_main_buttons button:contains('New')",
run: "click",
},
{
trigger: "div[name='name'] input",
run: "edit Test channel",
},
{
trigger: ".breadcrumb-item:contains('OdooBot')",
run: "click",
},
{
trigger: ".o-mail-DiscussSidebarChannel-itemName:contains('Test channel')",
},
],
});

View file

@ -0,0 +1,62 @@
import { ChannelMember } from "@mail/discuss/core/common/channel_member_model";
import { registry } from "@web/core/registry";
import { patchWithCleanup } from "@web/../tests/helpers/utils";
registry.category("web_tour.tours").add("discuss_call_invitation.js", {
steps: () => {
// Call invitation is cancelled after 30s. Increase this delay for the test.
patchWithCleanup(ChannelMember, { CANCEL_CALL_INVITE_DELAY: 1e6 });
return [
{ trigger: ".o-discuss-CallInvitation" },
{
trigger:
".o-mail-CallInvitation-avatar[title='View the bob (base.group_user) and john (base.group_user) channel']",
},
{
trigger:
".o-discuss-CallInvitation-channelName:contains('bob (base.group_user) and john (base.group_user)')",
},
{
trigger:
".o-discuss-CallInvitation-description:contains('Incoming call from bob (base.group_user)')",
},
{
trigger: ".o-discuss-CallInvitation-cameraPreview:not(:visible)",
},
{
trigger: ".o-discuss-CallInvitation button[title='Join Call']",
},
{
trigger: ".o-discuss-CallInvitation button[title='Reject']",
},
{
trigger: ".o-discuss-CallInvitation button[title='Show camera preview']",
run: "click",
},
{
trigger: ".o-discuss-CallInvitation-cameraPreview",
},
{
trigger: ".o-discuss-CallInvitation-cameraPreview button[title='Turn camera on']",
},
{
trigger: ".o-discuss-CallInvitation-cameraPreview button[title='Unmute']",
},
{
trigger: ".o-discuss-CallInvitation-cameraPreview button[title='Video Settings']",
run: "click",
},
{
trigger: "label:contains('Blur background')",
},
{
trigger: ".o-discuss-CallInvitation button[title='Hide camera preview']",
run: "click",
},
{
trigger: ".o-discuss-CallInvitation-cameraPreview:not(:visible)",
},
];
},
});

View file

@ -0,0 +1,43 @@
import { registry } from "@web/core/registry";
import { contains } from "@web/../tests/utils";
registry.category("web_tour.tours").add("discuss_channel_as_guest_tour.js", {
steps: () => [
{
content: "Channel secret token has been hidden on welcome page",
trigger: ".o-mail-WelcomePage",
run() {
if (!window.location.pathname.startsWith("/discuss/channel")) {
console.error("Channel secret token is still present in URL.");
}
},
},
{
content: "Click join",
trigger: "button[title='Join Channel']",
run: "click",
},
{
content: "Check that we are on not in a call",
trigger: "button[name='call']",
},
{
content: "Check that we are on channel page",
trigger: ".o-mail-Thread",
run: "press ctrl+k",
},
{
trigger: ".o_command_palette_search input",
run: "fill @",
},
{
trigger: ".o-mail-DiscussCommand",
async run() {
await contains(".fa-hashtag", {
parent: [".o-mail-DiscussCommand", { text: "Test channel" }],
});
await contains(".fa-user", { count: 0 });
},
},
],
});

View file

@ -0,0 +1,14 @@
import { registry } from "@web/core/registry";
registry.category("web_tour.tours").add("discuss_channel_call_action.js", {
steps: () => [
{
content: "Check that the call has started",
trigger: ".o-discuss-Call",
},
{
content: "Check that current user is in call ('disconnect' button visible)",
trigger: "button[title='Disconnect']",
},
],
});

View file

@ -0,0 +1,30 @@
import { registry } from "@web/core/registry";
registry.category("web_tour.tours").add("discuss_channel_call_public_tour.js", {
steps: () => [
{
content: "The call does not start on the welcome page",
trigger: ".o-mail-WelcomePage",
async run() {
await new Promise((r) => setTimeout(r, 250));
const rtcService = odoo.__WOWL_DEBUG__.root.env.services["discuss.rtc"];
if (rtcService?.selfSession || rtcService?.state.hasPendingRequest) {
console.error("The call should not have started.");
}
},
},
{
content: "Click join",
trigger: "button[title='Join Channel']",
run: "click",
},
{
content: "Check that the call has started",
trigger: ".o-discuss-Call",
},
{
content: "Check that current user is in call ('disconnect' button visible)",
trigger: "button[title='Disconnect']",
},
],
});

View file

@ -0,0 +1,96 @@
import { browser } from "@web/core/browser/browser";
import { registry } from "@web/core/registry";
import { dragenterFiles } from "@web/../tests/utils";
const CLICK_ON_CHAT_STEP = "click-on-chat-action";
function getMeetingViewTourSteps({ inWelcomePage = false } = {}) {
const steps = [
{ trigger: ".o-mail-Meeting" },
{
trigger: ".o-mail-Meeting [title='Invite People']",
run: "click",
},
{ trigger: ".o-mail-Meeting .o-mail-ActionPanel:contains('Invite people')" },
{
trigger: ".o-mail-Meeting [title='Invite People']", // close it
run: "click",
},
{ trigger: ".o-mail-Meeting:not(:has(.o-mail-ActionPanel))" },
{
trigger: ".o-mail-Meeting [title='Invite People']",
run: "click",
},
{ trigger: ".o-mail-Meeting .o-mail-ActionPanel:contains('Invite people')" },
{
trigger: ".o-mail-Meeting [title='Chat']",
run: "click",
content: CLICK_ON_CHAT_STEP,
},
{
trigger:
".o-mail-Meeting .o-mail-ActionPanel .o-mail-Thread:contains('john (base.group_user) and bob (base.group_user)')",
},
{
trigger: ".o-mail-Message[data-persistent]:contains('Hello everyone!')",
run: "hover && click .o-mail-Message-actions button[title='Expand']",
},
{
trigger: ".o-dropdown-item:contains('Mark as Unread')",
run: "click",
},
{ trigger: ".o-mail-Meeting [title='Chat']:has(.badge:contains(1))" },
{
trigger: ".o-mail-Thread-banner span:contains('Mark as Read')",
run: "click",
},
{
trigger: ".o-mail-Meeting [title='Chat']:not(:has(.badge))",
async run({ waitFor }) {
const files = [new File(["hi there"], "file2.txt", { type: "text/plain" })];
await dragenterFiles(".o-mail-Meeting .o-mail-ActionPanel", files);
// Ensure other dropzones such as discuss or chat window dropzones are not active in meeting view.
await waitFor(".o-Dropzone", { only: true });
},
},
{
trigger: ".o-mail-Meeting [title='Close panel']",
run: "click",
},
{ trigger: ".o-mail-Meeting:not(:has(.o-mail-ActionPanel))" },
{
trigger: ".o-mail-Meeting [title='Exit Fullscreen']",
run: "click",
},
{ trigger: "body:not(:has(.o-mail-Meeting))" },
];
if (inWelcomePage) {
steps.unshift({ trigger: "[title='Join Channel']", run: "click" });
}
return steps;
}
registry
.category("web_tour.tours")
.add("discuss.meeting_view_tour", {
steps: () => {
// Avoid starting with mic/camera to prevent an unhandleable browser permission popup.
browser.localStorage.setItem("discuss_call_preview_join_mute", "true");
browser.localStorage.setItem("discuss_call_preview_join_video", "false");
const steps = getMeetingViewTourSteps();
const clickOnChatIndex = steps.find((step) => step.content === CLICK_ON_CHAT_STEP);
steps.splice(
clickOnChatIndex,
0,
{
trigger: ".o-mail-Composer.o-focused .o-mail-Composer-input",
run: "edit Hello everyone!",
},
{ trigger: ".o-mail-Composer button[title='Send']:enabled", run: "click" }
);
return steps;
},
})
.add("discuss.meeting_view_public_tour", {
steps: () => getMeetingViewTourSteps({ inWelcomePage: true }),
});

View file

@ -0,0 +1,205 @@
import { reactive } from "@odoo/owl";
import { registry } from "@web/core/registry";
import { getOrigin } from "@web/core/utils/urls";
import { click, inputFiles } from "@web/../tests/utils";
// The tour is ran twice, ensure the correct message is always targetted.
const messageSelector = ".o-mail-Message:has(.o-mail-Message-body:contains('cheese'))";
const editedMessageSelector = ".o-mail-Message:has(.o-mail-Message-body:contains('vegetables'))";
registry.category("web_tour.tours").add("discuss_channel_public_tour.js", {
steps: () => [
{
trigger: ".o-mail-Discuss",
},
{
trigger: ".o-mail-Thread",
run() {
if (!window.location.pathname.startsWith("/discuss/channel")) {
console.error("Channel secret token is still present in URL.");
}
const errors = odoo.loader.findErrors();
if (Object.keys(errors).length) {
console.error("Couldn't load all JS modules.", errors);
}
document.body.classList.add("o_discuss_channel_public_modules_loaded");
if (
!document.title.includes(
document.querySelector(".o-mail-DiscussContent-threadName")?.value
)
) {
console.error(
`Tab title should match conversation name. Got "${
document.title
}" instead of "${
document.querySelector(".o-mail-DiscussContent-threadName")?.value
}".`
);
}
},
},
{
trigger: ".o_discuss_channel_public_modules_loaded",
},
{
trigger: ".o-mail-Composer-input",
run: "edit cheese",
},
{ trigger: ".o-mail-Composer button[title='More Actions']", run: "click" },
{
trigger: ".dropdown-item:contains('Attach Files')",
async run() {
const text = new File(["hello, world"], "text.txt", { type: "text/plain" });
await inputFiles(".o-mail-Composer .o_input_file", [text]);
},
},
{
trigger: ".o-mail-AttachmentContainer:not(.o-isUploading):contains(text.txt)",
},
{
trigger: ".dropdown-item:contains('Attach Files')",
async run() {
await inputFiles(".o-mail-Composer .o_input_file", [
new File(
[
await (
await fetch(
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2P4v5ThPwAG7wKklwQ/bwAAAABJRU5ErkJggg=="
)
).blob(),
],
"image.png",
{ type: "image/png" }
),
]);
},
},
{
trigger: '.o-mail-AttachmentContainer:not(.o-isUploading)[title="image.png"]',
async run({ waitFor }) {
/** @type {import("models").Store} */
const store = odoo.__WOWL_DEBUG__.root.env.services["mail.store"];
if (store.self_guest) {
const src = this.anchor.querySelector("img").src;
const attachment = store["ir.attachment"].get(
(src.match("/web/image/([0-9]+)") || []).at(-1)
);
if (!attachment) {
throw new Error(`Attachment was not found from src: ${src}`);
}
if (!attachment.raw_access_token) {
await new Promise((resolve) => {
const proxy = reactive(attachment, () => {
if (attachment.raw_access_token) {
resolve();
} else {
void proxy.raw_access_token; // keep observing until a value is received
}
});
void proxy.raw_access_token; // start observing
});
}
await waitFor(
`.o-mail-AttachmentContainer[title="image.png"] img[src="${getOrigin()}/web/image/${
attachment.id
}?access_token=${attachment.raw_access_token}&filename=image.png&unique=${
attachment.checksum
}"]`
);
}
},
},
{ trigger: ".o-mail-Composer button[title='Send']:enabled", run: "click" },
{
trigger: `${messageSelector}[data-persistent]`,
},
{
trigger: `${messageSelector} .o-mail-AttachmentContainer:contains("text.txt")`,
},
{
trigger: messageSelector,
run: `hover && click ${messageSelector} [title='Add a Reaction']`,
},
{
trigger: ".o-mail-QuickReactionMenu",
run: () => click("[title='Toggle Emoji Picker']"),
},
{
trigger: ".o-EmojiPicker .o-Emoji:contains('🙂')",
run: "click",
},
{
trigger: `${messageSelector} .o-mail-MessageReaction:contains('🙂')`,
run: "click",
},
{
trigger: `${messageSelector}:not(:has(.o-mail-MessageReaction:contains('🙂')))`,
},
{
trigger: `${messageSelector}`,
run: `hover && click ${messageSelector} [title='Expand']`,
},
{
trigger: `.o-mail-Message-moreMenu [title='Edit'], ${messageSelector} [title='Edit']`,
run: "click",
},
{
trigger: ".o-mail-Message .o-mail-Composer-input",
run: "edit vegetables",
},
{
trigger: ".o-mail-Message .o-mail-Composer button[title='More Actions']",
run: "click",
},
{
trigger: ".dropdown-item:contains('Attach Files')",
async run() {
const extratxt = new File(["hello 2"], "extra.txt", { type: "text/plain" });
await inputFiles(".o-mail-Message .o_input_file", [extratxt]);
},
},
{
trigger:
".o-mail-Message .o-mail-Composer .o-mail-AttachmentContainer:not(.o-isUploading):contains(extra.txt)",
},
{
trigger: ".o-mail-Message button:contains(save)",
run: "click",
},
{
trigger: editedMessageSelector,
},
{
trigger: `${editedMessageSelector} .o-mail-AttachmentContainer:contains("text.txt")`,
},
{
trigger: `${editedMessageSelector} .o-mail-AttachmentContainer:contains("extra.txt")`,
},
{
trigger: `${editedMessageSelector} .o-mail-AttachmentContainer:contains("extra.txt") .o-mail-Attachment-unlink`,
run: "click",
},
{
trigger: ".modal:contains(Confirmation) .btn:contains(Ok)",
run: "click",
},
{
trigger: `${editedMessageSelector}:not(:has(.o-mail-AttachmentContainer:contains("extra.txt")))`,
},
{
trigger: "button[title='Search Messages']",
run: "click",
},
{
trigger: ".o_searchview_input",
run: "edit text.txt",
},
{
trigger: "button[aria-label='Search button']",
run: "click",
},
{
trigger: `.o-mail-SearchMessagesPanel ${editedMessageSelector} .o-mail-AttachmentContainer:contains("text.txt")`,
},
],
});

View file

@ -0,0 +1,78 @@
import { registry } from "@web/core/registry";
import { stepUtils } from "@web_tour/tour_utils";
registry.category("web_tour.tours").add("discuss_configuration_tour", {
url: "/odoo",
steps: () => [
stepUtils.showAppsMenuItem(),
{
trigger: '.o_app[data-menu-xmlid="mail.menu_root_discuss"]',
run: "click",
},
{
trigger: ".o_main_navbar button:contains('Configuration')",
run: "click",
},
{
trigger: ".dropdown-menu a:contains('Notification')",
run: "click",
},
{
trigger: "button:contains('All Messages')",
run: "click",
},
{
trigger: "button:contains('Mentions Only')",
run: "click",
},
{
trigger: "button:contains('Nothing')",
run: "click",
},
{
trigger: ".modal-header button[aria-label='Close']",
run: "click",
},
{
trigger: ".o_main_navbar button:contains('Configuration')",
run: "click",
},
{
trigger: ".dropdown-menu a:contains('Voice & Video')",
run: "click",
},
{
trigger: "select[name='inputDevice']",
},
{
trigger: "button:contains('Voice Detection')",
run: "click",
},
{
trigger: "span:contains('Voice detection sensitivity')",
},
{
trigger: "button:contains('Push to Talk')",
run: "click",
},
{
trigger: "label:contains('Push-to-talk key')",
},
{
trigger: "label:contains('Delay after releasing push-to-talk')",
},
{
trigger: "input[aria-label='Show video participants only']",
},
{
trigger: "input[aria-label='Blur video background']",
run: "click",
},
{
trigger: "label:contains('Background blur intensity')",
},
{
trigger: "label:contains('Edge blur intensity')",
},
],
});

View file

@ -0,0 +1,11 @@
import { registry } from "@web/core/registry";
registry.category("web_tour.tours").add("discuss_go_back_to_thread_from_breadcrumbs.js", {
steps: () => [
{ trigger: ".o-mail-DiscussContent-threadName[title='Inbox']" },
{ trigger: ".o-mail-DiscussSidebar-item:contains('Starred messages')", run: "click" },
{ trigger: "button[title='View or join channels']:not(:visible)", run: "click" },
{ trigger: ".breadcrumb-item:contains('Starred messages')", run: "click" },
{ trigger: ".o-mail-DiscussContent-threadName[title='Starred messages']" },
],
});

View file

@ -0,0 +1,50 @@
import { registry } from "@web/core/registry";
registry.category("web_tour.tours").add("discuss.invite_by_email", {
steps: () => [
// Wait for the auto-open of the memberlist. Otherwise, it will
// conflict with the opening of the invite panel.
{ trigger: ".o-discuss-ChannelMemberList" },
{
trigger: "button[title='Invite People']",
run: "click",
},
{
trigger: ".o-discuss-ChannelInvitation-search[placeholder='Invite people or email']",
run: "edit john@test.com",
},
{
trigger: ".o-discuss-ChannelInvitation-selectable:contains('john (base.group_user)')",
async run({ waitFor, click }) {
await waitFor(".o-discuss-ChannelInvitation-selectable", {
only: true,
timeout: 5000,
});
await click();
},
},
{
trigger:
".o-discuss-ChannelInvitation-selectedList :contains('john (base.group_user)')",
},
{
trigger: ".o-discuss-ChannelInvitation-search",
run: "edit unknown_email@test.com",
},
{
trigger: ".o-discuss-ChannelInvitation-selectable:contains('unknown_email@test.com')",
run: "click",
},
{
trigger:
".o-discuss-ChannelInvitation-selectedList :contains('unknown_email@test.com')",
},
{
trigger: "button:contains(Invite to Group Chat)",
run: "click",
},
{
trigger: "body:not(:has(.o-mail-ActionPanel))",
},
],
});

View file

@ -0,0 +1,17 @@
import { registry } from "@web/core/registry";
registry.category("web_tour.tours").add("discuss_mention_suggestions_group_restricted_channel.js", {
steps: () => [
{ trigger: ".o-mail-DiscussContent-threadName[title='R&D Channel']" },
{ trigger: ".o-mail-Composer-input", run: "edit @" },
{ trigger: ".o-mail-Composer-suggestion:count(3)" },
{
content: "Suggest channel member not in R&D group",
trigger: ".o-mail-Composer-suggestion strong:text(Consultant User)",
},
{
content: "Suggest non-channel member in R&D group",
trigger: ".o-mail-Composer-suggestion strong:text(Dev User)",
},
],
});

View file

@ -1,30 +0,0 @@
/** @odoo-module **/
import tour from 'web_tour.tour';
tour.register('mail/static/tests/tours/discuss_public_tour.js', {
test: true,
}, [{
trigger: '.o_DiscussPublicView',
extraTrigger: '.o_ThreadView',
}, {
content: "Check that we are on channel page",
trigger: '.o_ThreadView',
run() {
if (!window.location.pathname.startsWith('/discuss/channel')) {
console.error('Did not automatically redirect to channel page');
}
// Wait for modules to be loaded or failed for the next step
odoo.__DEBUG__.didLogInfo.then(() => {
const { missing, failed, unloaded } = odoo.__DEBUG__.jsModules;
if ([missing, failed, unloaded].some(arr => arr.length)) {
console.error("Couldn't load all JS modules.", JSON.stringify({ missing, failed, unloaded }));
}
document.body.classList.add('o_mail_channel_public_modules_loaded');
});
},
extraTrigger: '.o_mail_channel_public_modules_loaded',
}, {
content: "Wait for all modules loaded check in previous step",
trigger: '.o_mail_channel_public_modules_loaded',
}]);

View file

@ -0,0 +1,49 @@
import { registry } from "@web/core/registry";
registry.category("web_tour.tours").add("sidebar_in_public_page_tour", {
steps: () => [
{
trigger: ".o-mail-DiscussContent-header [title='Channel 1']",
},
{
trigger: ".o-mail-DiscussSidebarChannel:contains(Channel 1).o-active",
},
{
trigger: ".o-mail-DiscussSidebarChannel:contains(Channel 2)",
run: "click",
},
{
trigger: ".o-mail-DiscussContent-header [title='Channel 2']",
},
{
trigger: ".o-mail-DiscussSidebarChannel:contains(Channel 2).o-active",
run() {
history.back();
},
},
{
trigger: ".o-mail-DiscussContent-header [title='Channel 1']",
},
{
trigger: ".o-mail-DiscussSidebarChannel:contains(Channel 1).o-active",
run() {
history.forward();
},
},
{
trigger: ".o-mail-DiscussContent-header [title='Channel 2']",
},
{
trigger: ".o-mail-DiscussSidebarChannel:contains(Channel 2).o-active",
},
{
content: "Open channel actions",
trigger: ".o-mail-DiscussSidebarChannel:contains(Channel 2).o-active",
run: "hover && click [title='Channel Actions']",
},
{
trigger: ".o-dropdown-item:contains('Invite People')",
run: "click",
},
],
});

View file

@ -0,0 +1,175 @@
import { SubChannelList } from "@mail/discuss/core/public_web/sub_channel_list";
import { status } from "@odoo/owl";
import { registry } from "@web/core/registry";
import { Deferred } from "@web/core/utils/concurrency";
import { patch } from "@web/core/utils/patch";
import { effect } from "@web/core/utils/reactive";
import { contains, dragenterFiles, dropFiles, scroll } from "@web/../tests/utils";
let waitForLoadMoreToDisappearDef;
registry.category("web_tour.tours").add("test_discuss_sub_channel_search", {
steps: () => [
{
trigger: "body",
run() {
patch(SubChannelList.prototype, {
setup() {
super.setup(...arguments);
effect(
(state) => {
if (status(this) === "destroyed") {
return;
}
if (!state.isVisible) {
waitForLoadMoreToDisappearDef?.resolve();
}
},
[this.loadMoreState]
);
},
});
},
},
{
trigger: "button[title='Threads']",
run: "click",
},
{
trigger: ".o-mail-SubChannelList",
async run() {
// 30 newest sub channels are loaded initially.
for (let i = 99; i > 69; i--) {
await contains(".o-mail-SubChannelPreview", {
text: `Sub Channel ${i}`,
});
await contains(".o-mail-SubChannelPreview", { count: 30 });
}
},
},
{
trigger: ".o-mail-ActionPanel:has(.o-mail-SubChannelList) .o_searchview_input",
run: "edit Sub Channel 10",
},
{
trigger:
".o-mail-ActionPanel:has(.o-mail-SubChannelList) button[aria-label='Search button']",
run: "click",
},
{
trigger: ".o-mail-SubChannelPreview:contains(Sub Channel 10)",
async run() {
await contains(".o-mail-SubChannelPreview", { count: 1 });
waitForLoadMoreToDisappearDef = new Deferred();
},
},
{
trigger: ".o_searchview_input",
run: "clear",
},
{
trigger: ".o-mail-SubChannelPreview:contains(Sub Channel 99)",
async run() {
await contains(".o-mail-SubChannelPreview", { count: 31 });
// Already fetched sub channels are shown in addition to the one
// that was fetched during the search.
for (let i = 99; i > 69; i--) {
await contains(".o-mail-SubChannelPreview", {
text: `Sub Channel ${i}`,
});
}
await contains(".o-mail-SubChannelPreview", { text: `Sub Channel 10` });
// Ensure lazy loading is still working after a search.
await waitForLoadMoreToDisappearDef;
waitForLoadMoreToDisappearDef = new Deferred();
await scroll(".o-mail-ActionPanel:has(.o-mail-SubChannelList)", "bottom");
},
},
{
trigger: ".o-mail-SubChannelPreview:contains(Sub Channel 40)",
async run() {
await contains(".o-mail-SubChannelPreview", { count: 61 });
for (let i = 99; i > 39; i--) {
await contains(".o-mail-SubChannelPreview", {
text: `Sub Channel ${i}`,
});
}
await waitForLoadMoreToDisappearDef;
waitForLoadMoreToDisappearDef = new Deferred();
await scroll(".o-mail-ActionPanel:has(.o-mail-SubChannelList)", "bottom");
},
},
{
trigger: ".o-mail-SubChannelPreview:contains(Sub Channel 11)",
async run() {
await contains(".o-mail-SubChannelPreview", { count: 90 });
for (let i = 99; i > 9; i--) {
await contains(".o-mail-SubChannelPreview", {
text: `Sub Channel ${i}`,
});
}
await waitForLoadMoreToDisappearDef;
await scroll(".o-mail-ActionPanel:has(.o-mail-SubChannelList)", "bottom");
},
},
{
trigger: ".o-mail-SubChannelPreview:contains(Sub Channel 0)",
async run() {
await contains(".o-mail-SubChannelPreview", { count: 100 });
for (let i = 99; i > 0; i--) {
await contains(".o-mail-SubChannelPreview", {
text: `Sub Channel ${i}`,
});
}
},
},
],
});
registry.category("web_tour.tours").add("create_thread_for_attachment_without_body", {
steps: () => [
{
content: "Open general channel",
trigger: '.o-mail-DiscussSidebarChannel-itemName:contains("general")',
run: "click",
},
{
content: "Drop a file",
trigger: ".o-mail-DiscussContent-main",
async run() {
const files = [new File(["hi there"], "file2.txt", { type: "text/plain" })];
await dragenterFiles(".o-mail-DiscussContent-main", files);
await dropFiles(".o-Dropzone", files);
},
},
{
trigger: '.o-mail-AttachmentContainer:not(.o-isUploading):contains("file2.txt")',
},
{
content: "Click on send button",
trigger: ".o-mail-Composer-mainActions [title='Send']:enabled",
run: "click",
},
{
content: "Hover on attachment",
trigger:
'.o-mail-Message:not(:has(.o-mail-Message-pendingProgress)) .o-mail-AttachmentContainer:contains("file2.txt")',
run: "hover",
},
{
content: "Click on expand button",
trigger: '.o-mail-Message [title="Expand"]',
run: "click",
},
{
content: "Create a new thread",
trigger: '.o-dropdown-item:contains("Create Thread")',
run: "click",
},
{
content: "Check a new thread is created",
trigger: '.o-mail-Discuss:contains("New Thread")',
},
],
});

View file

@ -0,0 +1,48 @@
import { registry } from "@web/core/registry";
registry.category("web_tour.tours").add("mail_activity_schedule_from_chatter", {
steps: () => [
{
trigger: "button:contains('Activity')",
run: "click",
},
{
trigger: ".o_selection_badge span:contains('Call')",
run: "click",
},
{
trigger: ".o_selection_badge.active span:contains('Call')",
},
{
trigger: ".o_selection_badge span:contains('To-Do')",
run: "click",
},
{
trigger: "div[name='summary'] input",
run: "edit Play Mario Party",
},
{
trigger: "button:contains('Save')",
run: "click",
},
{
trigger: ".o-mail-Activity:contains('Play Mario Party')",
run: "click",
},
{
trigger: "button:contains('Activity')",
run: "click",
},
{
trigger: "div[name='summary'] input",
run: "edit Play Mario Kart",
},
{
trigger: "button.btn.btn-secondary:contains('Mark Done')",
run: "click",
},
{
trigger: ".o-mail-Message:contains('Play Mario Kart')",
},
],
});

View file

@ -1,31 +0,0 @@
/** @odoo-module **/
import tour from 'web_tour.tour';
tour.register('mail/static/tests/tours/mail_channel_as_guest_tour.js', {
test: true,
}, [{
content: "Click join",
trigger: '.o_WelcomeView_joinButton',
extraTrigger: '.o_ThreadView',
}, {
content: "Check that we are on channel page",
trigger: '.o_ThreadView',
run() {
if (!window.location.pathname.startsWith('/discuss/channel')) {
console.error('Clicking on join button did not redirect to channel page');
}
// Wait for modules to be loaded or failed for the next step
odoo.__DEBUG__.didLogInfo.then(() => {
const { missing, failed, unloaded } = odoo.__DEBUG__.jsModules;
if ([missing, failed, unloaded].some(arr => arr.length)) {
console.error("Couldn't load all JS modules.", JSON.stringify({ missing, failed, unloaded }));
}
document.body.classList.add('o_mail_channel_as_guest_tour_modules_loaded');
});
},
extraTrigger: '.o_mail_channel_as_guest_tour_modules_loaded',
}, {
content: "Wait for all modules loaded check in previous step",
trigger: '.o_mail_channel_as_guest_tour_modules_loaded',
}]);

View file

@ -0,0 +1,44 @@
import { registry } from "@web/core/registry";
import { stepUtils } from "@web_tour/tour_utils";
registry.category("web_tour.tours").add("mail/static/tests/tours/mail_composer_autosave_tour.js", {
steps: () => [
{
content: "Edit the function field",
trigger: ".o_field_widget[name='function'] > .o_input",
run: "edit Director",
},
{
trigger: ".o_form_sheet_bg",
run: "click",
},
{
content: "Click on Send Message",
trigger: ".o-mail-Chatter-sendMessage",
run: "click",
},
{
content: "Open the full composer",
trigger: "[name='open-full-composer']",
run: "click",
},
{
content: "Edit the body",
trigger: ".o-wysiwyg div[contenteditable='true']",
run: "editor Hello-- Mitchell Admin",
},
{
content: "Click on Send Message",
trigger: ".o_mail_send[name='action_send_mail']",
run: "click",
},
{
content: "Check message is shown",
trigger: '.o-mail-Message-body:contains("Hello")',
},
{
trigger: ".o_form_saved",
},
...stepUtils.toggleHomeMenu(),
],
});

View file

@ -0,0 +1,287 @@
import { registry } from "@web/core/registry";
import { contains, dragenterFiles, dropFiles, inputFiles } from "@web/../tests/utils";
/**
* This tour depends on data created by python test in charge of launching it.
* It is not intended to work when launched from interface. It is needed to test
* an action (action manager) which is not possible to test with QUnit.
* @see mail/tests/test_mail_composer.py
*/
registry.category("web_tour.tours").add("mail/static/tests/tours/mail_composer_test_tour.js", {
steps: () => [
{
content: "Wait for the chatter to be fully loaded",
trigger: ".o-mail-Chatter",
async run() {
await contains(".o-mail-Message", { count: 1 });
},
},
{
content: "Click on Send Message",
trigger: "button:contains(Send message)",
run: "click",
},
{
content: "Write something in composer",
trigger: ".o-mail-Composer-input",
run: "edit blahblah @Not && click body",
},
{
content: "Mention a partner",
trigger: ".o-mail-Composer-suggestion:contains(Not A Demo User)",
run: "click",
},
{
content: "Add one file in composer",
trigger: ".o-mail-Composer button[title='Attach Files']",
async run() {
const files = [new File(["hello, world"], "file1.txt", { type: "text/plain" })];
await inputFiles(".o-mail-Composer .o_input_file", files);
},
},
{
trigger: '.o-mail-AttachmentContainer:not(.o-isUploading):contains("file1.txt")',
},
{
content: "Open full composer",
trigger: "button[title='Open Full Composer']",
run: "click",
},
{
content: "Check composer keeps open after pushing Escape",
trigger: ".o_mail_composer_form_view",
run: "press Escape",
},
{
content: "Check the earlier provided attachment is listed",
trigger: ".o_field_mail_composer_attachment_list a:contains(file1.txt)",
},
{
content: "Check subject is autofilled",
trigger: '[name="subject"] input',
run() {
const subjectValue = document.querySelector('[name="subject"] input').value;
if (subjectValue !== "Jane") {
console.error(
`Full composer should have "Jane" in subject input (actual: ${subjectValue})`
);
}
},
},
{
content: "Check composer content is kept and contains the user's signature",
trigger: '.o_field_html[name="body"]',
run() {
const bodyContent = document.querySelector(
'.o_field_html[name="body"]'
).textContent;
if (!bodyContent.includes("blahblah @Not A Demo User")) {
console.error(
`Full composer should contain text from small composer ("blahblah @Not A Demo User") in body input (actual: ${bodyContent})`
);
}
const mentionLink = document.querySelector(
'.o_field_html[name="body"] a'
).textContent;
if (!mentionLink.includes("@Not A Demo User")) {
console.error(
`Full composer should contain mention link from small composer ("@Not A Demo User") in body input)`
);
}
/** When opening the full composer for the first time, the system
* should add the user's signature to the end of the message so
* that the user can edit it. After adding the signature to
* the editor, the server shouldn't automatically add the
* signature to the message (see: Python tests). */
if ((bodyContent.match(/--\nErnest/g) || []).length !== 1) {
console.error("Full composer should contain the user's signature once.");
}
},
},
{
content: "Drop a file on the full composer",
trigger: ".o_mail_composer_form_view",
async run() {
const files = [new File(["hi there"], "file2.txt", { type: "text/plain" })];
await dragenterFiles(".o_mail_composer_form_view .o_form_renderer", files);
await dropFiles(".o-Dropzone", files);
},
},
{
content: "Check the attachment is listed",
trigger: ".o_field_mail_composer_attachment_list a:contains(file2.txt)",
},
{
content: "Click on the mail template selector",
trigger: ".mail-composer-template-dropdown-btn",
run: "click",
},
{
content: "Check a template is listed",
trigger:
'.mail-composer-template-dropdown.popover .o-dropdown-item:contains("Test template")',
},
{
content: "Verify admin template is NOT listed",
trigger: ".mail-composer-template-dropdown.popover",
run() {
const hasAdminTemplate = [...document.querySelectorAll(".o-dropdown-item")].some(
(item) => item.textContent.includes("Test template for admin")
);
if (hasAdminTemplate) {
console.error(
"Template assigned to the admin is visible to a non-assigned user! This should not happen."
);
}
},
},
{
content: "Send message from full composer",
trigger: ".o_mail_send",
run: "click",
},
{
content: "Check message is shown",
trigger: '.o-mail-Message-body:contains("blahblah @Not A Demo User")',
run: "click",
},
{
content: "Click on envelope to see recipients of message",
trigger:
'.o-mail-Message:has(.o-mail-Message-body:contains("blahblah @Not A Demo User")) .o-mail-Message-notification',
run: "click",
},
{
content: "Check message has correct recipients",
trigger:
".o-mail-MessageNotificationPopover:contains('Not A Demo User (NotADemoUser@mail.com) Jane (jane@example.com) Mitchell Admin (test.admin@test.example.com)')",
},
{
content: "Check message contains the first attachment",
trigger: '.o-mail-Message .o-mail-AttachmentContainer:contains("file1.txt")',
},
{
content: "Check message contains the second attachment",
trigger: '.o-mail-Message .o-mail-AttachmentContainer:contains("file2.txt")',
},
// Test the full composer input text is kept on closing
{
content: "Click on Send Message",
trigger: "button:contains(Send message)",
run: "click",
},
{
content: "Open full composer",
trigger: "button[title='Open Full Composer']",
run: "click",
},
{
content: "Check that the composer contains the signature",
trigger: '.o_field_html[name="body"]',
run() {
const bodyContent = document.querySelector(
'.o_field_html[name="body"]'
).textContent;
/** When opening the full composer, the system should add the
* user's signature, as this is a new message and the signature
* has not yet been added to it. */
if ((bodyContent.match(/--\nErnest/g) || []).length !== 1) {
console.log("Full composer should contain the user's signature once.");
}
},
},
{
content: "Write something in full composer",
trigger: ".note-editable",
run: "editor keep the content",
},
{
content: "Close full composer",
trigger: ".btn-close",
run: "click",
},
{
content: "Click on Send Message",
trigger: "button:contains(Send message)",
run: "click",
},
{
content: "Check full composer text is kept",
trigger: ".o-mail-Composer button[title='Open Full Composer'].active",
run({ queryFirst }) {
if (queryFirst(".o-mail-Composer-input").value !== "keep the content") {
console.error(
"Composer in chatter should contain full composer text after discarding."
);
}
},
},
{
content: "Open full composer",
trigger: "button[title='Open Full Composer']",
run: "click",
},
{
content: "Check that the composer doesn't add the user's signature twice",
trigger: ".note-editable",
run() {
const bodyContent = document.querySelector(
'.o_field_html[name="body"]'
).textContent;
/** When re-opening the full composer, the system shouldn't re-add
* the user's signature to the message. As the user deleted the
* signature in the previous steps (see: `editor keep the content`),
* the editor shouldn't contain any signature. */
if ((bodyContent.match(/--\nErnest/g) || []).length !== 0) {
console.error("The composer should not contain the user's signature.");
}
},
},
{
content: "Close full composer",
trigger: ".btn-close",
run: "click",
},
{
content: "Click on Send Message",
trigger: "button:contains(Send message)",
run: "click",
},
{
content: "Continue Message Composition with Small Composer",
trigger:
".o_popover:contains('Continue with Full Composer?') button:contains('No (Remove formatting)')",
run: "click",
},
{
content: "Send message from chatter",
trigger: ".o-mail-Composer-send:enabled",
run: "click",
},
{
content: "Check message is shown",
trigger: '.o-mail-Message-body:contains("keep the content")',
},
// Test that the server automatically adds the user's signature to the
// email when the user didn't open the full composer.
{
content: "Click on Send Message",
trigger: "button:contains(Send message)",
run: "click",
},
{
content: "Write a message",
trigger: ".o-mail-Composer-input",
run: "edit hello world",
},
{
content: "Send message from chatter",
trigger: ".o-mail-Composer-send:enabled",
run: "click",
},
{
content: "Check message is shown",
trigger: '.o-mail-Message-body:contains("hello world")',
},
],
});

View file

@ -1,97 +0,0 @@
/** @odoo-module **/
import {
createFile,
inputFiles,
} from 'web.test_utils_file';
import { contains } from '@web/../tests/utils';
import tour from 'web_tour.tour';
/**
* This tour depends on data created by python test in charge of launching it.
* It is not intended to work when launched from interface. It is needed to test
* an action (action manager) which is not possible to test with QUnit.
* @see mail/tests/test_mail_full_composer.py
*/
tour.register('mail/static/tests/tours/mail_full_composer_test_tour.js', {
test: true,
}, [{
content: "Wait for the chatter to be fully loaded",
trigger: ".o_Chatter",
async run() {
await contains(".o_Message", { count: 1 });
document.body.setAttribute("data-found-message", 1);
},
}, {
content: "Click on Send Message",
trigger: '.o_ChatterTopbar_buttonSendMessage',
extra_trigger: 'body[data-found-message=1]',
}, {
content: "Write something in composer",
trigger: '.o_ComposerTextInput_textarea',
run: 'text blahblah',
}, {
content: "Add one file in composer",
trigger: '.o_Composer_buttonAttachment',
async run() {
const file = await createFile({
content: 'hello, world',
contentType: 'text/plain',
name: 'text.txt',
});
const messaging = await odoo.__DEBUG__.messaging;
const uploader = messaging.models['ComposerView'].all()[0].fileUploader;
inputFiles(
uploader.fileInput,
[file]
);
},
}, {
content: "Open full composer",
trigger: '.o_Composer_buttonFullComposer',
extra_trigger: '.o_AttachmentCard:not(.o-isUploading)' // waiting the attachment to be uploaded
}, {
content: "Check the earlier provided attachment is listed",
trigger: '.o_AttachmentCard[title="text.txt"]',
run() {},
}, {
content: "Check subject is autofilled",
trigger: '[name="subject"] input',
run() {
const subjectValue = document.querySelector('[name="subject"] input').value;
if (subjectValue !== "Re: Jane") {
console.error(
`Full composer should have "Re: Jane" in subject input (actual: ${subjectValue})`
);
}
},
}, {
content: "Check composer content is kept",
trigger: '.o_field_html[name="body"]',
run() {
const bodyContent = document.querySelector('.o_field_html[name="body"]').textContent;
if (!bodyContent.includes("blahblah")) {
console.error(
`Full composer should contain text from small composer ("blahblah") in body input (actual: ${bodyContent})`
);
}
},
}, {
content: "Open templates",
trigger: '.o_field_widget[name="template_id"] input',
}, {
content: "Check a template is listed",
in_modal: false,
trigger: '.ui-autocomplete .ui-menu-item a:contains("Test template")',
run() {},
}, {
content: "Send message",
trigger: '.o_mail_send',
}, {
content: "Check message is shown",
trigger: '.o_Message:contains("blahblah")',
}, {
content: "Check message contains the attachment",
trigger: '.o_Message .o_AttachmentCard_filename:contains("text.txt")',
}]);

View file

@ -0,0 +1,99 @@
import { registry } from "@web/core/registry";
import { contains } from "@web/../tests/utils";
/**
* This tour depends on data created by python test in charge of launching it.
* It is not intended to work when launched from interface. It is needed to test
* an action (action manager) which is not possible to test with QUnit.
* @see mail/tests/test_mail_composer.py
*/
registry.category("web_tour.tours").add("mail/static/tests/tours/mail_html_composer_test_tour.js", {
steps: () => [
{
content: "Wait for the chatter to be fully loaded",
trigger: ".o-mail-Chatter",
async run() {
const composerService = odoo.__WOWL_DEBUG__.root.env.services["mail.composer"];
composerService.setHtmlComposer();
await contains(".o-mail-Message", { count: 1 });
},
},
{
content: "Click on Send Message",
trigger: "button:contains(Send message)",
run: "click",
},
{
content: "Write something in composer",
trigger: ".o-mail-Composer-html.odoo-editor-editable",
run: "editor Hello",
},
{
content: "Select the text",
trigger: ".o-mail-Composer-html.odoo-editor-editable",
run: "dblclick",
},
{
trigger: ".o-we-toolbar",
},
{
content: "Bold the text",
trigger: ".o-we-toolbar button[title='Toggle bold']",
run: "click",
},
{
content: "The bolded text is in the composer",
trigger: ".o-mail-Composer-html.odoo-editor-editable strong:contains(Hello)",
},
{
content: "Open full composer",
trigger: "button[title='Open Full Composer']",
run: "click",
},
{
content: "Check composer keeps the formatted content",
trigger: ".o_mail_composer_message strong:contains(Hello)",
},
{
content: "Focus the text in full composer",
trigger: ".o_mail_composer_message .odoo-editor-editable",
run: "click",
},
{
content: "Select the text in full composer",
trigger: ".o_mail_composer_message .odoo-editor-editable",
run: "dblclick",
},
{
trigger: ".o-we-toolbar",
},
{
content: "Remove the Bold",
trigger: ".o-we-toolbar button[title='Toggle bold']",
run: "click",
},
{
content: "Italicize the text",
trigger: ".o-we-toolbar button[title='Toggle italic']",
run: "click",
},
{
content: "The italicized text is in the full composer",
trigger: ".o_mail_composer_message em:contains(Hello)",
},
{
content: "Close full composer",
trigger: ".btn-close",
run: "click",
},
{
content: "Click on Send Message",
trigger: "button:not(.active):contains(Send message)",
run: "click",
},
{
content: "The italicized text is in the composer",
trigger: ".o-mail-Composer-html.odoo-editor-editable em:contains(Hello)",
},
],
});

View file

@ -0,0 +1,69 @@
import { registry } from "@web/core/registry";
import { contains, scroll } from "@web/../tests/utils";
registry.category("web_tour.tours").add("mail_message_load_order_tour", {
steps: () => [
{
trigger: ".o-mail-DiscussSidebarChannel:contains(MyTestChannel)",
run: "click",
},
{
trigger: ".o-mail-Thread .o-mail-Message",
async run() {
await contains(".o-mail-Thread .o-mail-Message", { count: 30 });
await contains(".o-mail-Thread", { scroll: "bottom" });
},
},
{
trigger: "*[title='Pinned Messages']",
run: "click",
},
{
content: "Click on invisible jump (should hover card to be visible)",
trigger: ".o-mail-MessageCard-jump:not(:visible)",
run: "click",
},
{
// Messages depends on FETCH_LIMIT (currently set to 60) in
// the thread service. Thus, at first load the message range
// will be (31 - 60). This trigger ensures the next messages
// are fetched after jumping to the message.
trigger:
".o-mail-Thread .o-mail-Message:first .o-mail-Message-textContent:not(:contains(31))",
async run() {
await contains(".o-mail-Thread .o-mail-Message", { count: 31 });
await contains(".o-mail-Thread", { scroll: 0 });
// ensure 1 - 31 are loaded in order: 30 below and the
// one we're loading messages around.
const messages = Array.from(
document.querySelectorAll(".o-mail-Thread .o-mail-Message-content")
).map((el) => el.innerText);
for (let i = 0; i < 31; i++) {
if (messages[i] !== (i + 1).toString()) {
throw new Error("Wrong message order after loading around");
}
}
await scroll(".o-mail-Thread", "bottom");
},
},
{
// After jumping to the pinned message, the message range
// was (1 -31): 30 before (but none were found), 30 after
// and the pinned message itself. This trigger ensures the
// next messages are fetched after scrolling to the bottom.
trigger: ".o-mail-Thread .o-mail-Message .o-mail-Message-textContent:contains(17)",
async run() {
await contains(".o-mail-Thread .o-mail-Message", { count: 60 });
// ensure 1 - 60 are loaded in order.
const messages = Array.from(
document.querySelectorAll(".o-mail-Thread .o-mail-Message-content")
).map((el) => el.innerText);
for (let i = 0; i < 60; i++) {
if (messages[i] !== (i + 1).toString()) {
throw new Error("Wrong message order after loading after");
}
}
},
},
],
});

View file

@ -0,0 +1,228 @@
import { registry } from "@web/core/registry";
import { stepUtils } from "@web_tour/tour_utils";
import { delay } from "@web/core/utils/concurrency";
registry.category("web_tour.tours").add("mail_template_dynamic_placeholder_tour", {
url: "/odoo",
steps: () => [
stepUtils.showAppsMenuItem(),
{
content: 'Go into the Setting "app"',
trigger: '.o_app[data-menu-xmlid="base.menu_administration"]',
run: "click",
},
{
content: "Open email templates",
trigger: 'button[name="open_mail_templates"]',
run: "click",
},
{
content: "Create a new email template",
trigger: "button.o_list_button_add",
run: "click",
},
{
content: 'Insert # inside "Subject" input',
trigger: 'div[name="subject"] input[type="text"]',
run: "edit(no_model_id #)",
},
{
content: 'Select "Contact" model',
trigger: 'div[name="model_id"] input[type="text"]',
run: "edit Contact",
},
{
content: "Wait for the autocomplete RPC",
trigger: 'div[name="model_id"] .ui-autocomplete:contains("Contact")',
run: async () => {
await delay(300);
},
},
{
content: "Click on contact",
trigger: 'div[name="model_id"] .ui-autocomplete',
run: async function () {
const contact = Array.from(
document.querySelectorAll(
'div[name="model_id"] .ui-autocomplete .dropdown-item'
)
).find((el) => el.textContent === "Contact");
await contact.click();
},
},
{
content: "Wait for the drop down to disappear",
trigger: 'div[name="model_id"] .o-autocomplete:not(:has(.ui-autocomplete))',
run: async () => {
// Ensure the system has registered a correct model value before
// we try to open the DPH.
// It seems that the autocomplete validation can be very slow.
await delay(200);
},
},
{
content: 'Retry insert # inside "Subject" input',
trigger: 'div[name="subject"] input[type="text"]',
run: "edit (yes_model_id) && press #",
},
{
content: "Check if the dynamic placeholder popover is opened",
trigger: "div.o_model_field_selector_popover",
},
{
content: "filter the dph result",
trigger: "div.o_model_field_selector_popover_search input[type='text']",
run: "edit name",
},
{
content: "Click on the first entry of the dynamic placeholder",
trigger: 'div.o_model_field_selector_popover button:contains("Company Name")',
run: "click",
},
{
content: "Enter a default value",
trigger:
'div.o_model_field_selector_popover .o_model_field_selector_default_value_input input[type="text"]',
run: "edit defValue",
},
{
content: "Click on the insert button",
trigger: "div.o_model_field_selector_popover button:first-child",
run: "click",
},
{
content: "Wait for the popover to disappear",
trigger: "body:not(:has(.o_model_field_selector_popover))",
run: "click",
},
{
content: "Check if subject value was correctly updated",
trigger: 'div[name="subject"] input[type="text"]',
run() {
const subjectValue = this.anchor.value;
const correctValue = "yes_model_id {{object.company_name|||defValue}}";
if (subjectValue !== correctValue) {
console.error(
`Email template should have "${correctValue}" in subject input (actual: ${subjectValue})`
);
}
},
},
{
content: "Insert text inside editable",
trigger: ".note-editable.odoo-editor-editable",
async run(actions) {
await actions.editor(`/`);
document.querySelector(".note-editable").dispatchEvent(
new InputEvent("input", {
inputType: "insertText",
data: "/",
})
);
},
},
{
content: "Click on the the dynamic placeholder powerBox options",
trigger: "div.o-we-powerbox .o-we-command:contains(Dynamic Placeholder)",
run: "click",
},
{
content: "Check if the dynamic placeholder popover is opened",
trigger: "div.o_model_field_selector_popover",
run: "click",
},
{
content: "filter the dph result",
trigger: "div.o_model_field_selector_popover_search input[type='text']",
run: "edit name",
},
{
content: "Click on the first entry of the dynamic placeholder",
trigger: 'div.o_model_field_selector_popover button:contains("Company Name")',
run: "click",
},
{
content: "Enter a default value",
trigger:
'div.o_model_field_selector_popover .o_model_field_selector_default_value_input input[type="text"]',
run: "edit defValue",
},
{
content: "Click on the insert button",
trigger: "div.o_model_field_selector_popover button:first-child",
run: "click",
},
{
content: "Ensure the editable contain the dynamic placeholder t tag",
trigger: `.note-editable.odoo-editor-editable t[t-out="object.company_name"]:contains("defValue")`,
},
{
content: 'Type "Push Notification Device" model',
trigger: 'div[name="model_id"] input[type="text"]',
run: "edit Push Notification Device",
},
{
content: 'Select "Push Notification Device" model',
trigger: 'a.dropdown-item:contains("Push Notification Device")',
run: "click",
},
{
content: "Insert text inside editable",
trigger: ".note-editable.odoo-editor-editable",
async run(actions) {
await actions.editor(`/`);
document.querySelector(".note-editable").dispatchEvent(
new InputEvent("input", {
inputType: "insertText",
data: "/",
})
);
},
},
{
content: "Click on the the dynamic placeholder powerBox options",
trigger: "div.o-we-powerbox .o-we-command:contains(Dynamic Placeholder)",
run: "click",
},
{
content: "Check if the dynamic placeholder popover is opened",
trigger: "div.o_model_field_selector_popover",
run: "click",
},
{
content: "filter the dph result",
trigger: "div.o_model_field_selector_popover_search input[type='text']",
run: "edit created on",
},
{
content: "Click on the first entry of the dynamic placeholder",
trigger:
'div.o_model_field_selector_popover li:first-child button:contains("Created on")',
run: "click",
},
{
content: "Enter a default value",
trigger:
"div.o_model_field_selector_popover .o_model_field_selector_default_value_input input[type='text']",
run: "edit localTime",
},
{
content: "Click on the insert button",
trigger: "div.o_model_field_selector_popover button:first-child:contains('Insert)",
run: "click",
},
{
content: "Ensure the editable contain the dynamic placeholder t tag",
trigger: `.note-editable.odoo-editor-editable t[t-out="format_datetime(object.create_date, tz=object.partner_id.tz) or 'localTime'"]:contains("localTime")`,
},
{
content: "Discard form changes",
trigger: "button.o_form_button_cancel",
run: "click",
},
{
content: "Wait for the form view to disappear",
trigger: "body:not(:has(.o_form_sheet))",
},
],
});

View file

@ -1,26 +1,40 @@
/** @odoo-module **/
import tour from 'web_tour.tour';
import { registry } from "@web/core/registry";
import { click, contains } from "@web/../tests/utils";
/**
* Verify that a user can modify their own profile information.
*/
tour.register('mail/static/tests/tours/user_modify_own_profile_tour.js', {
test: true,
}, [{
content: 'Open user account menu',
trigger: '.o_user_menu button',
}, {
content: "Open preferences / profile screen",
trigger: '[data-menu=settings]',
}, {
content: "Update the email address",
trigger: 'div[name="email"] input',
run: 'text updatedemail@example.com',
}, {
content: "Save the form",
trigger: 'button[name="preference_save"]',
}, {
content: "Wait until the modal is closed",
trigger: 'body:not(.modal-open)',
}]);
registry.category("web_tour.tours").add("mail/static/tests/tours/user_modify_own_profile_tour.js", {
steps: () => [
{
content: "Open user account menu",
trigger: ".o_user_menu button",
run: "click",
},
{
content: "Open preferences / profile screen",
trigger: "[data-menu=preferences]",
run: "click",
},
{
content: "Update the notification type",
trigger: '.modal div[name="notification_type"] input[data-value="inbox"]',
async run() {
await click('.modal div[name="notification_type"] input[data-value="inbox"]');
await contains(".o_form_dirty", { count: 1 });
},
},
{
content: "Save the form",
trigger: 'button[name="preference_save"]',
run: "click",
},
{
content: "Wait until the modal is closed",
trigger: "body:not(.modal-open)",
async run() {
await contains(".o_form_dirty", { count: 0 });
},
},
],
});