mirror of
https://github.com/bringout/oca-ocb-core.git
synced 2026-04-21 02:32:03 +02:00
19.0 vanilla
This commit is contained in:
parent
d1963a3c3a
commit
2d3ee4855a
7430 changed files with 2687981 additions and 2965473 deletions
|
|
@ -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')",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -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')",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -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)",
|
||||
},
|
||||
];
|
||||
},
|
||||
});
|
||||
|
|
@ -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 });
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -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']",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -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']",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -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 }),
|
||||
});
|
||||
|
|
@ -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")`,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -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')",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -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']" },
|
||||
],
|
||||
});
|
||||
|
|
@ -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))",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -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)",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -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',
|
||||
}]);
|
||||
|
|
@ -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",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -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")',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -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')",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -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',
|
||||
}]);
|
||||
|
|
@ -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(),
|
||||
],
|
||||
});
|
||||
|
|
@ -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")',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -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")',
|
||||
}]);
|
||||
|
|
@ -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)",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -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))",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -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 });
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue