mail/static/tests/discuss/call/call_tests.js

253 lines
9.6 KiB
JavaScript
Raw Normal View History

2024-05-03 12:40:35 +03:00
/* @odoo-module */
import { startServer } from "@bus/../tests/helpers/mock_python_environment";
import { Command } from "@mail/../tests/helpers/command";
import { mockGetMedia, start } from "@mail/../tests/helpers/test_utils";
import { browser } from "@web/core/browser/browser";
import { patchWithCleanup } from "@web/../tests/helpers/utils";
import { assertSteps, click, contains, step, triggerEvents } from "@web/../tests/utils";
QUnit.module("call");
QUnit.test("basic rendering", async () => {
mockGetMedia();
const pyEnv = await startServer();
const channelId = pyEnv["discuss.channel"].create({
name: "General",
});
const { openDiscuss } = await start();
openDiscuss(channelId);
await click("[title='Start a Call']");
await contains(".o-discuss-Call");
await contains(".o-discuss-CallParticipantCard[aria-label='Mitchell Admin']");
await contains(".o-discuss-CallActionList");
await contains(".o-discuss-CallMenu-buttonContent");
await contains(".o-discuss-CallActionList button", { count: 5 });
await contains("button[aria-label='Unmute'], button[aria-label='Mute']"); // FIXME depends on current browser permission
await contains(".o-discuss-CallActionList button[aria-label='Deafen']");
await contains(".o-discuss-CallActionList button[aria-label='Turn camera on']");
await contains("[title='More']");
await contains(".o-discuss-CallActionList button[aria-label='Disconnect']");
await click("[title='More']");
await contains("[title='Raise Hand']");
await contains("[title='Share Screen']");
await contains("[title='Enter Full Screen']");
});
QUnit.test("no call with odoobot", async () => {
const pyEnv = await startServer();
const channelId = pyEnv["discuss.channel"].create({
channel_member_ids: [
Command.create({ partner_id: pyEnv.currentPartnerId }),
Command.create({ partner_id: pyEnv.odoobotId }),
],
channel_type: "chat",
});
const { openDiscuss } = await start();
openDiscuss(channelId);
await contains(".o-mail-Discuss-header");
await contains("[title='Start a Call']", { count: 0 });
});
QUnit.test("should not display call UI when no more members (self disconnect)", async () => {
mockGetMedia();
const pyEnv = await startServer();
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
const { openDiscuss } = await start();
openDiscuss(channelId);
await click("[title='Start a Call']");
await contains(".o-discuss-Call");
await click(".o-discuss-CallActionList button[aria-label='Disconnect']");
await contains(".o-discuss-Call", { count: 0 });
});
QUnit.test("show call UI in chat window when in call", async () => {
mockGetMedia();
const pyEnv = await startServer();
pyEnv["discuss.channel"].create({ name: "General" });
await start();
await click(".o_menu_systray i[aria-label='Messages']");
await click(".o-mail-NotificationItem", { text: "General" });
await contains(".o-mail-ChatWindow");
await contains(".o-discuss-Call", { count: 0 });
await click(".o-mail-ChatWindow-command[title='Start a Call']");
await contains(".o-discuss-Call");
await contains(".o-mail-ChatWindow-command[title='Start a Call']", { count: 0 });
});
QUnit.test("should disconnect when closing page while in call", async () => {
mockGetMedia();
const pyEnv = await startServer();
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
const { openDiscuss } = await start();
openDiscuss(channelId);
patchWithCleanup(browser, {
navigator: {
...browser.navigator,
sendBeacon: async (route, data) => {
if (data instanceof Blob && route === "/mail/rtc/channel/leave_call") {
const blobText = await data.text();
const blobData = JSON.parse(blobText);
step(`sendBeacon_leave_call:${blobData.params.channel_id}`);
}
},
},
});
await click("[title='Start a Call']");
await contains(".o-discuss-Call");
// simulate page close
window.dispatchEvent(new Event("pagehide"), { bubble: true });
await assertSteps([`sendBeacon_leave_call:${channelId}`]);
});
QUnit.test("should display invitations", async () => {
const pyEnv = await startServer();
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
const partnerId = pyEnv["res.partner"].create({ name: "InvitationSender" });
const memberId = pyEnv["discuss.channel.member"].create({
channel_id: channelId,
partner_id: partnerId,
});
const sessionId = pyEnv["discuss.channel.rtc.session"].create({
channel_member_id: memberId,
channel_id: channelId,
});
const { env } = await start();
patchWithCleanup(env.services["mail.sound_effects"], {
play(name) {
step(`play - ${name}`);
super.play(...arguments);
},
stop(name) {
step(`stop - ${name}`);
super.stop(...arguments);
},
});
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "mail.record/insert", {
Thread: {
id: channelId,
model: "discuss.channel",
rtcInvitingSession: { id: sessionId, channelMember: { id: memberId } },
},
});
await contains(".o-discuss-CallInvitation");
await assertSteps(["play - incoming-call"]);
// Simulate stop receiving call invitation
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "mail.record/insert", {
Thread: {
id: channelId,
model: "discuss.channel",
rtcInvitingSession: false,
},
});
await contains(".o-discuss-CallInvitation", { count: 0 });
await assertSteps(["stop - incoming-call"]);
});
QUnit.test("can share screen", async () => {
mockGetMedia();
const pyEnv = await startServer();
const channelId = pyEnv["discuss.channel"].create({
name: "General",
});
const { openDiscuss } = await start();
openDiscuss(channelId);
await click("[title='Start a Call']");
await click("[title='More']");
await click("[title='Share Screen']");
await contains("video");
await triggerEvents(".o-discuss-Call-mainCards", ["mousemove"]); // show overlay
await click("[title='More']");
await click("[title='Stop Sharing Screen']");
await contains("video", { count: 0 });
});
QUnit.test("can share user camera", async () => {
mockGetMedia();
const pyEnv = await startServer();
const channelId = pyEnv["discuss.channel"].create({
name: "General",
});
const { openDiscuss } = await start();
openDiscuss(channelId);
await click("[title='Start a Call']");
await click("[title='Turn camera on']");
await contains("video");
await click("[title='Stop camera']");
await contains("video", { count: 0 });
});
QUnit.test("Create a direct message channel when clicking on start a meeting", async () => {
mockGetMedia();
const { openDiscuss } = await start();
openDiscuss();
await click("button", { text: "Start a meeting" });
await contains(".o-mail-DiscussSidebarChannel", { text: "Mitchell Admin" });
await contains(".o-discuss-Call");
await contains(".o-discuss-ChannelInvitation");
});
QUnit.test("Can share user camera and screen together", async () => {
mockGetMedia();
const pyEnv = await startServer();
const channelId = pyEnv["discuss.channel"].create({
name: "General",
});
const { openDiscuss } = await start();
openDiscuss(channelId);
await click("[title='Start a Call']");
await click("[title='More']");
await click("[title='Share Screen']");
await click("[title='Turn camera on']");
await contains("video", { count: 2 });
});
QUnit.test("Click on inset card should replace the inset and active stream together", async () => {
mockGetMedia();
const pyEnv = await startServer();
const channelId = pyEnv["discuss.channel"].create({
name: "General",
});
const { openDiscuss } = await start();
openDiscuss(channelId);
await click("[title='Start a Call']");
await click("[title='More']");
await click("[title='Share Screen']");
await click("[title='Turn camera on']");
await contains("video[type='screen']:not(.o-inset)");
await click("video[type='camera'].o-inset");
await contains("video[type='screen'].o-inset");
await contains("video[type='camera']:not(.o-inset)");
});
QUnit.test("join/leave sounds are only played on main tab", async () => {
mockGetMedia();
const pyEnv = await startServer();
const channelId = pyEnv["discuss.channel"].create({ name: "General" });
const tab1 = await start({ asTab: true });
const tab2 = await start({ asTab: true });
patchWithCleanup(tab1.env.services["mail.sound_effects"], {
play(name) {
step(`tab1 - play - ${name}`);
},
});
patchWithCleanup(tab2.env.services["mail.sound_effects"], {
play(name) {
step(`tab2 - play - ${name}`);
},
});
await tab1.openDiscuss(channelId);
await tab2.openDiscuss(channelId);
await click("[title='Start a Call']", { target: tab1.target });
await contains(".o-discuss-Call", { target: tab1.target });
await contains(".o-discuss-Call", { target: tab2.target });
await assertSteps(["tab1 - play - channel-join"]);
await click("[title='Disconnect']:not([disabled])", { target: tab1.target });
await contains(".o-discuss-Call", { target: tab1.target, count: 0 });
await contains(".o-discuss-Call", { target: tab2.target, count: 0 });
await assertSteps(["tab1 - play - channel-leave"]);
});