390 lines
14 KiB
JavaScript
390 lines
14 KiB
JavaScript
|
/* @odoo-module */
|
||
|
|
||
|
import { startServer } from "@bus/../tests/helpers/mock_python_environment";
|
||
|
|
||
|
import { start } from "@mail/../tests/helpers/test_utils";
|
||
|
|
||
|
import { patchWithCleanup } from "@web/../tests/helpers/utils";
|
||
|
import { click, contains, scroll } from "@web/../tests/utils";
|
||
|
|
||
|
QUnit.module("follower list menu");
|
||
|
|
||
|
QUnit.test("base rendering not editable", async () => {
|
||
|
const { openView } = await start();
|
||
|
openView(
|
||
|
{
|
||
|
res_model: "res.partner",
|
||
|
views: [[false, "form"]],
|
||
|
},
|
||
|
{ mode: "edit" }
|
||
|
);
|
||
|
await contains(".o-mail-Followers");
|
||
|
await contains(".o-mail-Followers-button:disabled");
|
||
|
await contains(".o-mail-Followers-dropdown", { count: 0 });
|
||
|
await click(".o-mail-Followers-button");
|
||
|
await contains(".o-mail-Followers-dropdown", { count: 0 });
|
||
|
});
|
||
|
|
||
|
QUnit.test("base rendering editable", async (assert) => {
|
||
|
const pyEnv = await startServer();
|
||
|
const partnerId = pyEnv["res.partner"].create({});
|
||
|
const { openView } = await start({
|
||
|
async mockRPC(route, args, performRPC) {
|
||
|
if (route === "/mail/thread/data") {
|
||
|
// mimic user with write access
|
||
|
const res = await performRPC(route, args);
|
||
|
res["hasWriteAccess"] = true;
|
||
|
return res;
|
||
|
}
|
||
|
},
|
||
|
});
|
||
|
openView({
|
||
|
res_id: partnerId,
|
||
|
res_model: "res.partner",
|
||
|
views: [[false, "form"]],
|
||
|
});
|
||
|
await contains(".o-mail-Followers");
|
||
|
await contains(".o-mail-Followers-button");
|
||
|
assert.notOk($(".o-mail-Followers-button")[0].disabled);
|
||
|
await contains(".o-mail-Followers-dropdown", { count: 0 });
|
||
|
|
||
|
await click(".o-mail-Followers-button");
|
||
|
await contains(".o-mail-Followers-dropdown");
|
||
|
});
|
||
|
|
||
|
QUnit.test('click on "add followers" button', async (assert) => {
|
||
|
const pyEnv = await startServer();
|
||
|
const [partnerId_1, partnerId_2, partnerId_3] = pyEnv["res.partner"].create([
|
||
|
{ name: "Partner1" },
|
||
|
{ name: "François Perusse" },
|
||
|
{ name: "Partner3" },
|
||
|
]);
|
||
|
pyEnv["mail.followers"].create({
|
||
|
partner_id: partnerId_2,
|
||
|
email: "bla@bla.bla",
|
||
|
is_active: true,
|
||
|
res_id: partnerId_1,
|
||
|
res_model: "res.partner",
|
||
|
});
|
||
|
|
||
|
const { env, openView } = await start({
|
||
|
async mockRPC(route, args, performRPC) {
|
||
|
if (route === "/mail/thread/data") {
|
||
|
// mimic user with write access
|
||
|
const res = await performRPC(route, args);
|
||
|
res["hasWriteAccess"] = true;
|
||
|
return res;
|
||
|
}
|
||
|
},
|
||
|
});
|
||
|
openView({
|
||
|
res_id: partnerId_1,
|
||
|
res_model: "res.partner",
|
||
|
views: [[false, "form"]],
|
||
|
});
|
||
|
patchWithCleanup(env.services.action, {
|
||
|
doAction(action, options) {
|
||
|
assert.step("action:open_view");
|
||
|
assert.strictEqual(action.context.default_res_model, "res.partner");
|
||
|
assert.strictEqual(action.context.default_res_id, partnerId_1);
|
||
|
assert.strictEqual(action.res_model, "mail.wizard.invite");
|
||
|
assert.strictEqual(action.type, "ir.actions.act_window");
|
||
|
pyEnv["mail.followers"].create({
|
||
|
partner_id: partnerId_3,
|
||
|
email: "bla@bla.bla",
|
||
|
is_active: true,
|
||
|
name: "Wololo",
|
||
|
res_id: partnerId_1,
|
||
|
res_model: "res.partner",
|
||
|
});
|
||
|
options.onClose();
|
||
|
},
|
||
|
});
|
||
|
await contains(".o-mail-Followers");
|
||
|
await contains(".o-mail-Followers-counter", { text: "1" });
|
||
|
await click(".o-mail-Followers-button");
|
||
|
await contains(".o-mail-Followers-dropdown");
|
||
|
await click("a", { text: "Add Followers" });
|
||
|
await contains(".o-mail-Followers-dropdown", { count: 0 });
|
||
|
assert.verifySteps(["action:open_view"]);
|
||
|
await contains(".o-mail-Followers-counter", { text: "2" });
|
||
|
await click(".o-mail-Followers-button");
|
||
|
await contains(".o-mail-Follower", { count: 2 });
|
||
|
await contains(":nth-child(1 of .o-mail-Follower)", { text: "François Perusse" });
|
||
|
await contains(":nth-child(2 of .o-mail-Follower)", { text: "Partner3" });
|
||
|
});
|
||
|
|
||
|
QUnit.test("click on remove follower", async (assert) => {
|
||
|
const pyEnv = await startServer();
|
||
|
const [partnerId_1, partnerId_2] = pyEnv["res.partner"].create([
|
||
|
{ name: "Partner1" },
|
||
|
{ name: "Partner2" },
|
||
|
]);
|
||
|
pyEnv["mail.followers"].create({
|
||
|
partner_id: partnerId_2,
|
||
|
email: "bla@bla.bla",
|
||
|
is_active: true,
|
||
|
name: "Wololo",
|
||
|
res_id: partnerId_1,
|
||
|
res_model: "res.partner",
|
||
|
});
|
||
|
const { openView } = await start({
|
||
|
async mockRPC(route, args, performRPC) {
|
||
|
if (route === "/mail/thread/data") {
|
||
|
// mimic user with write access
|
||
|
const res = await performRPC(route, args);
|
||
|
res["hasWriteAccess"] = true;
|
||
|
return res;
|
||
|
}
|
||
|
if (route.includes("message_unsubscribe")) {
|
||
|
assert.step("message_unsubscribe");
|
||
|
assert.deepEqual(args.args, [[partnerId_1], [partnerId_2]]);
|
||
|
}
|
||
|
},
|
||
|
});
|
||
|
openView({
|
||
|
res_id: partnerId_1,
|
||
|
res_model: "res.partner",
|
||
|
views: [[false, "form"]],
|
||
|
});
|
||
|
|
||
|
await click(".o-mail-Followers-button");
|
||
|
await contains(".o-mail-Follower");
|
||
|
await contains("button[title='Remove this follower']");
|
||
|
|
||
|
await click("button[title='Remove this follower']");
|
||
|
assert.verifySteps(["message_unsubscribe"]);
|
||
|
await contains(".o-mail-Follower", { count: 0 });
|
||
|
});
|
||
|
|
||
|
QUnit.test(
|
||
|
'Hide "Add follower" and subtypes edition/removal buttons except own user on read only record',
|
||
|
async () => {
|
||
|
const pyEnv = await startServer();
|
||
|
const [partnerId_1, partnerId_2] = pyEnv["res.partner"].create([
|
||
|
{ name: "Partner1" },
|
||
|
{ name: "Partner2" },
|
||
|
]);
|
||
|
pyEnv["mail.followers"].create([
|
||
|
{
|
||
|
is_active: true,
|
||
|
partner_id: pyEnv.currentPartnerId,
|
||
|
res_id: partnerId_1,
|
||
|
res_model: "res.partner",
|
||
|
},
|
||
|
{
|
||
|
is_active: true,
|
||
|
partner_id: partnerId_2,
|
||
|
res_id: partnerId_1,
|
||
|
res_model: "res.partner",
|
||
|
},
|
||
|
]);
|
||
|
const { openView } = await start({
|
||
|
async mockRPC(route, args, performRPC) {
|
||
|
if (route === "/mail/thread/data") {
|
||
|
// mimic user with no write access
|
||
|
const res = await performRPC(route, args);
|
||
|
res["hasWriteAccess"] = false;
|
||
|
return res;
|
||
|
}
|
||
|
},
|
||
|
});
|
||
|
openView({
|
||
|
res_id: partnerId_1,
|
||
|
res_model: "res.partner",
|
||
|
views: [[false, "form"]],
|
||
|
});
|
||
|
await click(".o-mail-Followers-button");
|
||
|
await contains("a", { count: 0, text: "Add Followers" });
|
||
|
await contains(":nth-child(1 of .o-mail-Follower)", {
|
||
|
contains: [
|
||
|
["button[title='Edit subscription']"],
|
||
|
["button[title='Remove this follower']"],
|
||
|
],
|
||
|
});
|
||
|
await contains(":nth-child(2 of .o-mail-Follower)", {
|
||
|
contains: [
|
||
|
["button[title='Edit subscription']", { count: 0 }],
|
||
|
["button[title='Remove this follower']", { count: 0 }],
|
||
|
],
|
||
|
});
|
||
|
}
|
||
|
);
|
||
|
|
||
|
QUnit.test("Load 100 followers at once", async () => {
|
||
|
const pyEnv = await startServer();
|
||
|
const partnerIds = pyEnv["res.partner"].create(
|
||
|
[...Array(210).keys()].map((i) => ({ display_name: `Partner${i}`, name: `Partner${i}` }))
|
||
|
);
|
||
|
pyEnv["mail.followers"].create(
|
||
|
[...Array(210).keys()].map((i) => {
|
||
|
return {
|
||
|
is_active: true,
|
||
|
partner_id: i === 0 ? pyEnv.currentPartnerId : partnerIds[i],
|
||
|
res_id: partnerIds[0],
|
||
|
res_model: "res.partner",
|
||
|
};
|
||
|
})
|
||
|
);
|
||
|
const { openFormView } = await start();
|
||
|
await openFormView("res.partner", partnerIds[0]);
|
||
|
await contains("button[title='Show Followers']", { text: "210" });
|
||
|
await click("button[title='Show Followers']");
|
||
|
await contains(".o-mail-Follower", { text: "Mitchell Admin" });
|
||
|
await contains(".o-mail-Follower", { count: 100 });
|
||
|
await contains(".o-mail-Followers-dropdown", { text: "Load more" });
|
||
|
await scroll(".o-mail-Followers-dropdown", "bottom");
|
||
|
await contains(".o-mail-Follower", { count: 200 });
|
||
|
await new Promise(setTimeout); // give enough time for the useVisible hook to register load more as hidden
|
||
|
await scroll(".o-mail-Followers-dropdown", "bottom");
|
||
|
await contains(".o-mail-Follower", { count: 210 });
|
||
|
await contains(".o-mail-Followers-dropdown span", { count: 0, text: "Load more" });
|
||
|
});
|
||
|
|
||
|
QUnit.test("Load 100 recipients at once", async () => {
|
||
|
const pyEnv = await startServer();
|
||
|
const partnerIds = pyEnv["res.partner"].create(
|
||
|
[...Array(210).keys()].map((i) => ({
|
||
|
display_name: `Partner${i}`,
|
||
|
name: `Partner${i}`,
|
||
|
email: `partner${i}@example.com`,
|
||
|
}))
|
||
|
);
|
||
|
pyEnv["mail.followers"].create(
|
||
|
[...Array(210).keys()].map((i) => {
|
||
|
return {
|
||
|
is_active: true,
|
||
|
partner_id: i === 0 ? pyEnv.currentPartnerId : partnerIds[i],
|
||
|
res_id: partnerIds[0],
|
||
|
res_model: "res.partner",
|
||
|
};
|
||
|
})
|
||
|
);
|
||
|
const { openFormView } = await start();
|
||
|
await openFormView("res.partner", partnerIds[0]);
|
||
|
await contains("button[title='Show Followers']", { text: "210" });
|
||
|
await click("button", { text: "Send message" });
|
||
|
await contains(".o-mail-Chatter", {
|
||
|
text: "To: partner1, partner2, partner3, partner4, partner5, …",
|
||
|
});
|
||
|
await contains("button[title='Show all recipients']");
|
||
|
await click("button[title='Show all recipients']");
|
||
|
await contains(".o-mail-RecipientList li", { count: 100 });
|
||
|
await contains(".o-mail-RecipientList", { text: "Load more" });
|
||
|
await scroll(".o-mail-RecipientList", "bottom");
|
||
|
await contains(".o-mail-RecipientList li", { count: 200 });
|
||
|
await new Promise(setTimeout); // give enough time for the useVisible hook to register load more as hidden
|
||
|
await scroll(".o-mail-RecipientList", "bottom");
|
||
|
await contains(".o-mail-RecipientList li", { count: 209 });
|
||
|
await contains(".o-mail-RecipientList span", { count: 0, text: "Load more" });
|
||
|
});
|
||
|
|
||
|
QUnit.test("Load recipient without email", async () => {
|
||
|
const pyEnv = await startServer();
|
||
|
const [partnerId_1, partnerId_2] = pyEnv["res.partner"].create([
|
||
|
{ name: "Luigi" },
|
||
|
{ name: "Mario" },
|
||
|
]);
|
||
|
pyEnv["mail.followers"].create([
|
||
|
{
|
||
|
is_active: true,
|
||
|
partner_id: pyEnv.currentPartnerId,
|
||
|
res_id: partnerId_1,
|
||
|
res_model: "res.partner",
|
||
|
},
|
||
|
{
|
||
|
is_active: true,
|
||
|
partner_id: partnerId_2,
|
||
|
res_id: partnerId_1,
|
||
|
res_model: "res.partner",
|
||
|
},
|
||
|
]);
|
||
|
const { openFormView } = await start();
|
||
|
await openFormView("res.partner", partnerId_1);
|
||
|
await click("button", { text: "Send message" });
|
||
|
await contains("span[title='no email address']", { text: "Mario" });
|
||
|
await click("button[title='Show all recipients']");
|
||
|
await contains(".o-mail-RecipientList li", { text: "[Mario] (no email address)" });
|
||
|
});
|
||
|
|
||
|
QUnit.test(
|
||
|
'Show "Add follower" and subtypes edition/removal buttons on all followers if user has write access',
|
||
|
async () => {
|
||
|
const pyEnv = await startServer();
|
||
|
const [partnerId_1, partnerId_2] = pyEnv["res.partner"].create([
|
||
|
{ name: "Partner1" },
|
||
|
{ name: "Partner2" },
|
||
|
]);
|
||
|
pyEnv["mail.followers"].create([
|
||
|
{
|
||
|
is_active: true,
|
||
|
partner_id: pyEnv.currentPartnerId,
|
||
|
res_id: partnerId_1,
|
||
|
res_model: "res.partner",
|
||
|
},
|
||
|
{
|
||
|
is_active: true,
|
||
|
partner_id: partnerId_2,
|
||
|
res_id: partnerId_1,
|
||
|
res_model: "res.partner",
|
||
|
},
|
||
|
]);
|
||
|
const { openView } = await start({
|
||
|
async mockRPC(route, args, performRPC) {
|
||
|
if (route === "/mail/thread/data") {
|
||
|
// mimic user with write access
|
||
|
const res = await performRPC(...arguments);
|
||
|
res["hasWriteAccess"] = true;
|
||
|
return res;
|
||
|
}
|
||
|
},
|
||
|
});
|
||
|
openView({
|
||
|
res_id: partnerId_1,
|
||
|
res_model: "res.partner",
|
||
|
views: [[false, "form"]],
|
||
|
});
|
||
|
|
||
|
await click(".o-mail-Followers-button");
|
||
|
await contains("a", { text: "Add Followers" });
|
||
|
await contains(":nth-child(1 of .o-mail-Follower)", {
|
||
|
contains: [
|
||
|
["button[title='Edit subscription']"],
|
||
|
["button[title='Remove this follower']"],
|
||
|
],
|
||
|
});
|
||
|
await contains(":nth-child(2 of .o-mail-Follower)", {
|
||
|
contains: [
|
||
|
["button[title='Edit subscription']"],
|
||
|
["button[title='Remove this follower']"],
|
||
|
],
|
||
|
});
|
||
|
}
|
||
|
);
|
||
|
|
||
|
QUnit.test(
|
||
|
'Show "No Followers" dropdown-item if there are no followers and user does not have write access',
|
||
|
async () => {
|
||
|
const pyEnv = await startServer();
|
||
|
const partnerId = pyEnv["res.partner"].create({});
|
||
|
const { openView } = await start({
|
||
|
async mockRPC(route, args, performRPC) {
|
||
|
if (route === "/mail/thread/data") {
|
||
|
// mimic user without write access
|
||
|
const res = await performRPC(route, args);
|
||
|
res["hasWriteAccess"] = false;
|
||
|
return res;
|
||
|
}
|
||
|
},
|
||
|
});
|
||
|
openView({
|
||
|
res_id: partnerId,
|
||
|
res_model: "res.partner",
|
||
|
views: [[false, "form"]],
|
||
|
});
|
||
|
|
||
|
await click(".o-mail-Followers-button");
|
||
|
await contains("div.disabled", { text: "No Followers" });
|
||
|
}
|
||
|
);
|