/** @odoo-module **/
import { nextAnimationFrame, start, startServer } from '@mail/../tests/helpers/test_utils';
import { ROUTES_TO_IGNORE } from '@mail/../tests/helpers/webclient_setup';
import testUtils from 'web.test_utils';
import { patchDate, patchWithCleanup, selectDropdownItem, editInput } from '@web/../tests/helpers/utils';
import { ListController } from "@web/views/list/list_controller";
QUnit.module('mail', {}, function () {
QUnit.module('Chatter');
QUnit.test('list activity widget with no activity', async function (assert) {
assert.expect(4);
const pyEnv = await startServer();
const views = {
'res.users,false,list': '
',
};
const { openView } = await start({
mockRPC: function (route, args) {
if (
args.method !== 'get_views' &&
!['/mail/init_messaging', '/mail/load_message_failures', '/bus/im_status', ...ROUTES_TO_IGNORE].includes(route)
) {
assert.step(route);
}
},
serverData: { views },
session: { uid: pyEnv.currentUserId },
});
await openView({
res_model: 'res.users',
views: [[false, 'list']],
});
assert.containsOnce(document.body, '.o_ActivityButtonView_icon.text-muted');
assert.strictEqual(document.querySelector('.o_ListFieldActivityView_summary').innerText, '');
assert.verifySteps(['/web/dataset/call_kw/res.users/web_search_read']);
});
QUnit.test('list activity widget with activities', async function (assert) {
assert.expect(6);
const pyEnv = await startServer();
const [mailActivityId1, mailActivityId2] = pyEnv['mail.activity'].create([{}, {}]);
const [mailActivityTypeId1, mailActivityTypeId2] = pyEnv['mail.activity.type'].create(
[{ name: 'Type 1' }, { name: 'Type 2' }],
);
pyEnv['res.users'].write([pyEnv.currentUserId], {
activity_ids: [mailActivityId1, mailActivityId2],
activity_state: 'today',
activity_summary: 'Call with Al',
activity_type_id: mailActivityTypeId1,
activity_type_icon: 'fa-phone',
});
pyEnv['res.users'].create({
activity_ids: [mailActivityId2],
activity_state: 'planned',
activity_summary: false,
activity_type_id: mailActivityTypeId2,
});
const views = {
'res.users,false,list': '
',
};
const { openView } = await start({
mockRPC: function (route, args) {
if (
args.method !== 'get_views' &&
!['/mail/init_messaging', '/mail/load_message_failures', '/bus/im_status', ...ROUTES_TO_IGNORE].includes(route)
) {
assert.step(route);
}
},
serverData: { views },
});
await openView({
res_model: 'res.users',
views: [[false, 'list']],
});
const firstRow = document.querySelector('.o_data_row');
assert.containsOnce(firstRow, '.o_ActivityButtonView_icon.text-warning.fa-phone');
assert.strictEqual(firstRow.querySelector('.o_ListFieldActivityView_summary').innerText, 'Call with Al');
const secondRow = document.querySelectorAll('.o_data_row')[1];
assert.containsOnce(secondRow, '.o_ActivityButtonView_icon.text-success.fa-clock-o');
assert.strictEqual(secondRow.querySelector('.o_ListFieldActivityView_summary').innerText, 'Type 2');
assert.verifySteps(['/web/dataset/call_kw/res.users/web_search_read']);
});
QUnit.test('list activity widget with activities, two pages, mark done', async function (assert) {
patchDate(2023, 0, 11, 12, 0, 0);
const pyEnv = await startServer();
const mailActivityTypeId = pyEnv['mail.activity.type'].create({});
const mailActivityId = pyEnv['mail.activity'].create({
display_name: "Meet FP",
date_deadline: moment().add(1, 'day').format("YYYY-MM-DD"), // tomorrow
can_write: true,
state: "planned",
user_id: pyEnv.currentUserId,
create_uid: pyEnv.currentUserId,
activity_type_id: mailActivityTypeId,
});
pyEnv['res.users'].create({ display_name: "User 1"});
pyEnv['res.users'].create({ display_name: "User 2"});
pyEnv['res.users'].create({
display_name: "User 3",
activity_ids: [mailActivityId],
activity_state: 'planned',
activity_summary: "Something to do",
activity_type_id: mailActivityTypeId,
});
const views = {
'res.users,false,list': `
`,
};
const { click, openView } = await start({
serverData: { views },
});
await openView({
res_model: 'res.users',
views: [[false, 'list']],
});
assert.containsOnce(document.body, ".o_list_view");
assert.strictEqual(document.querySelector(".o_cp_pager").innerText, "1-2 / 4");
await click(document.querySelector(".o_pager_next"));
assert.strictEqual(document.querySelector(".o_cp_pager").innerText, "3-4 / 4");
assert.strictEqual(document.querySelectorAll(".o_data_row")[1].querySelector("[name=activity_ids]").innerText, "Something to do");
await click(document.querySelectorAll(".o_ActivityButtonView")[1]);
await click(document.querySelector(".o_ActivityListViewItem_markAsDone"));
await click(document.querySelector(".o_ActivityMarkDonePopoverContent_doneButton"));
assert.strictEqual(document.querySelector(".o_cp_pager").innerText, "3-4 / 4");
assert.strictEqual(document.querySelectorAll(".o_data_row")[1].querySelector("[name=activity_ids]").innerText, "");
});
QUnit.test('list activity widget with exception', async function (assert) {
assert.expect(4);
const pyEnv = await startServer();
const mailActivityId1 = pyEnv['mail.activity'].create({});
const mailActivityTypeId1 = pyEnv['mail.activity.type'].create({});
pyEnv['res.users'].write([pyEnv.currentUserId], {
activity_ids: [mailActivityId1],
activity_state: 'today',
activity_summary: 'Call with Al',
activity_type_id: mailActivityTypeId1,
activity_exception_decoration: 'warning',
activity_exception_icon: 'fa-warning',
});
const views = {
'res.users,false,list': '
',
};
const { openView } = await start({
mockRPC: function (route, args) {
if (
args.method !== 'get_views' &&
!['/mail/init_messaging', '/mail/load_message_failures', '/bus/im_status', ...ROUTES_TO_IGNORE].includes(route)
) {
assert.step(route);
}
},
serverData: { views },
});
await openView({
res_model: 'res.users',
views: [[false, 'list']],
});
assert.containsOnce(document.body, '.o_ActivityButtonView_icon.text-warning.fa-warning');
assert.strictEqual(document.querySelector('.o_ListFieldActivityView_summary').innerText, 'Warning');
assert.verifySteps(['/web/dataset/call_kw/res.users/web_search_read']);
});
QUnit.test('list activity widget: open dropdown', async function (assert) {
assert.expect(9);
const pyEnv = await startServer();
const [mailActivityTypeId1, mailActivityTypeId2] = pyEnv['mail.activity.type'].create([{}, {}]);
const [mailActivityId1, mailActivityId2] = pyEnv['mail.activity'].create([
{
display_name: "Call with Al",
date_deadline: moment().format("YYYY-MM-DD"), // now
can_write: true,
state: "today",
user_id: pyEnv.currentUserId,
create_uid: pyEnv.currentUserId,
activity_type_id: mailActivityTypeId1,
},
{
display_name: "Meet FP",
date_deadline: moment().add(1, 'day').format("YYYY-MM-DD"), // tomorrow
can_write: true,
state: "planned",
user_id: pyEnv.currentUserId,
create_uid: pyEnv.currentUserId,
activity_type_id: mailActivityTypeId2,
}
]);
pyEnv['res.users'].write([pyEnv.currentUserId], {
activity_ids: [mailActivityId1, mailActivityId2],
activity_state: 'today',
activity_summary: 'Call with Al',
activity_type_id: mailActivityTypeId2,
});
const views = {
'res.users,false,list': '
',
};
const { click, openView } = await start({
mockRPC: function (route, args) {
if (
args.method !== 'get_views' &&
!['/mail/init_messaging', '/mail/load_message_failures', '/bus/im_status', ...ROUTES_TO_IGNORE].includes(route)
) {
assert.step(args.method || route);
}
if (args.method === 'action_feedback') {
pyEnv['res.users'].write([pyEnv.currentUserId], {
activity_ids: [mailActivityId2],
activity_state: 'planned',
activity_summary: 'Meet FP',
activity_type_id: mailActivityTypeId1,
});
// random value returned in order for the mock server to know that this route is implemented.
return true;
}
},
serverData: { views },
});
patchWithCleanup(ListController.prototype, {
setup() {
this._super();
const selectRecord = this.props.selectRecord;
this.props.selectRecord = (...args) => {
assert.step(`select_record ${JSON.stringify(args)}`);
return selectRecord(...args);
};
}
});
await openView({
res_model: 'res.users',
views: [[false, 'list']],
});
assert.strictEqual(document.querySelector('.o_ListFieldActivityView_summary').innerText, 'Call with Al');
await click('.o_ActivityButtonView'); // open the popover
await click('.o_ActivityListViewItem_markAsDone'); // mark the first activity as done
await click('.o_ActivityMarkDonePopoverContent_doneButton'); // confirm
assert.strictEqual(document.querySelector('.o_ListFieldActivityView_summary').innerText, 'Meet FP');
assert.verifySteps([
'web_search_read',
'activity_format',
'action_feedback',
'/mail/thread/messages',
'/mail/thread/data',
'web_search_read',
]);
});
QUnit.test('list activity exception widget with activity', async function (assert) {
assert.expect(3);
const pyEnv = await startServer();
const [mailActivityTypeId1, mailActivityTypeId2] = pyEnv['mail.activity.type'].create([{}, {}]);
const [mailActivityId1, mailActivityId2] = pyEnv['mail.activity'].create([
{
display_name: "An activity",
date_deadline: moment().format("YYYY-MM-DD"), // now
can_write: true,
state: "today",
user_id: pyEnv.currentUserId,
create_uid: pyEnv.currentUserId,
activity_type_id: mailActivityTypeId1,
},
{
display_name: "An exception activity",
date_deadline: moment().format("YYYY-MM-DD"), // now
can_write: true,
state: "today",
user_id: pyEnv.currentUserId,
create_uid: pyEnv.currentUserId,
activity_type_id: mailActivityTypeId2,
}
]);
pyEnv['res.users'].write([pyEnv.currentUserId], { activity_ids: [mailActivityId1] });
pyEnv['res.users'].create({
message_attachment_count: 3,
display_name: "second partner",
message_follower_ids: [],
message_ids: [],
activity_ids: [mailActivityId2],
activity_exception_decoration: 'warning',
activity_exception_icon: 'fa-warning',
});
const views = {
'res.users,false,list':
`