mirror of
https://github.com/bringout/oca-ocb-technical.git
synced 2026-04-22 10:52:09 +02:00
19.0 vanilla
This commit is contained in:
parent
5faf7397c5
commit
2696f14ed7
721 changed files with 220375 additions and 91221 deletions
|
|
@ -0,0 +1,75 @@
|
|||
import { defineCalendarModels } from "@calendar/../tests/calendar_test_helpers";
|
||||
import {
|
||||
click,
|
||||
contains,
|
||||
openFormView,
|
||||
registerArchs,
|
||||
start,
|
||||
startServer,
|
||||
} from "@mail/../tests/mail_test_helpers";
|
||||
import { test } from "@odoo/hoot";
|
||||
import { preloadBundle } from "@web/../tests/web_test_helpers";
|
||||
|
||||
defineCalendarModels();
|
||||
preloadBundle("web.fullcalendar_lib");
|
||||
|
||||
test("activity click on Reschedule", async () => {
|
||||
registerArchs({ "calendar.event,false,calendar": `<calendar date_start="start"/>` });
|
||||
const pyEnv = await startServer();
|
||||
const resPartnerId = pyEnv["res.partner"].create({});
|
||||
const meetingActivityTypeId = pyEnv["mail.activity.type"].create({
|
||||
icon: "fa-calendar",
|
||||
name: "Meeting",
|
||||
});
|
||||
const calendarAttendeeId = pyEnv["calendar.attendee"].create({
|
||||
partner_id: resPartnerId,
|
||||
});
|
||||
const calendaMeetingId = pyEnv["calendar.event"].create({
|
||||
res_model: "calendar.event",
|
||||
name: "meeting1",
|
||||
start: "2022-07-06 06:30:00",
|
||||
attendee_ids: [calendarAttendeeId],
|
||||
});
|
||||
pyEnv["mail.activity"].create({
|
||||
name: "Small Meeting",
|
||||
activity_type_id: meetingActivityTypeId,
|
||||
can_write: true,
|
||||
res_id: resPartnerId,
|
||||
res_model: "res.partner",
|
||||
calendar_event_id: calendaMeetingId,
|
||||
});
|
||||
await start();
|
||||
await openFormView("res.partner", resPartnerId);
|
||||
await click(".btn", { text: "Reschedule" });
|
||||
await contains(".o_calendar_view");
|
||||
});
|
||||
|
||||
test("Can cancel activity linked to an event", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv["res.partner"].create({ name: "Milan Kundera" });
|
||||
const activityTypeId = pyEnv["mail.activity.type"].create({
|
||||
icon: "fa-calendar",
|
||||
name: "Meeting",
|
||||
});
|
||||
const attendeeId = pyEnv["calendar.attendee"].create({
|
||||
partner_id: partnerId,
|
||||
});
|
||||
const calendaMeetingId = pyEnv["calendar.event"].create({
|
||||
res_model: "calendar.event",
|
||||
name: "meeting1",
|
||||
start: "2022-07-06 06:30:00",
|
||||
attendee_ids: [attendeeId],
|
||||
});
|
||||
pyEnv["mail.activity"].create({
|
||||
name: "Small Meeting",
|
||||
activity_type_id: activityTypeId,
|
||||
can_write: true,
|
||||
res_id: partnerId,
|
||||
res_model: "res.partner",
|
||||
calendar_event_id: calendaMeetingId,
|
||||
});
|
||||
await start();
|
||||
await openFormView("res.partner", partnerId);
|
||||
await click(".o-mail-Activity .btn", { text: "Cancel" });
|
||||
await contains(".o-mail-Activity", { count: 0 });
|
||||
});
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
import { defineCalendarModels } from "@calendar/../tests/calendar_test_helpers";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/mail_test_helpers";
|
||||
import { test } from "@odoo/hoot";
|
||||
import { mockDate } from "@odoo/hoot-mock";
|
||||
import {
|
||||
asyncStep,
|
||||
mockService,
|
||||
preloadBundle,
|
||||
serverState,
|
||||
waitForSteps,
|
||||
} from "@web/../tests/web_test_helpers";
|
||||
|
||||
defineCalendarModels();
|
||||
preloadBundle("web.fullcalendar_lib");
|
||||
|
||||
test("activity menu widget:today meetings", async () => {
|
||||
mockDate(2018, 3, 20, 6, 0, 0);
|
||||
const pyEnv = await startServer();
|
||||
const attendeeId = pyEnv["calendar.attendee"].create({ partner_id: serverState.partnerId });
|
||||
pyEnv["calendar.event"].create([
|
||||
{
|
||||
res_model: "calendar.event",
|
||||
name: "meeting1",
|
||||
start: "2018-04-20 06:30:00",
|
||||
attendee_ids: [attendeeId],
|
||||
},
|
||||
{
|
||||
res_model: "calendar.event",
|
||||
name: "meeting2",
|
||||
start: "2018-04-20 09:30:00",
|
||||
attendee_ids: [attendeeId],
|
||||
},
|
||||
]);
|
||||
mockService("action", {
|
||||
doAction(action) {
|
||||
if (typeof action === "string") {
|
||||
asyncStep(action);
|
||||
}
|
||||
},
|
||||
});
|
||||
await start();
|
||||
await contains(".o_menu_systray i[aria-label='Activities']");
|
||||
await click(".o_menu_systray i[aria-label='Activities']");
|
||||
await contains(".o-mail-ActivityGroup div[name='activityTitle']", { text: "Today's Meetings" });
|
||||
await contains(".o-mail-ActivityGroup .o-calendar-meeting", { count: 2 });
|
||||
await contains(".o-calendar-meeting span.fw-bold", { text: "meeting1" });
|
||||
await contains(".o-calendar-meeting span:not(.fw-bold)", { text: "meeting2" });
|
||||
await click(".o-mail-ActivityMenu .o-mail-ActivityGroup");
|
||||
await waitForSteps(["calendar.action_calendar_event"]);
|
||||
});
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { start, startServer } from '@mail/../tests/helpers/test_utils';
|
||||
|
||||
QUnit.module('calendar', () => {
|
||||
QUnit.module('components', () => {
|
||||
QUnit.module('activity_tests.js');
|
||||
|
||||
QUnit.test('activity click on Reschedule', async function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
const pyEnv = await startServer();
|
||||
const resPartnerId = pyEnv['res.partner'].create({});
|
||||
const meetingActivityTypeId = pyEnv['mail.activity.type'].create({ icon: 'fa-calendar', name: "Meeting" });
|
||||
const calendarAttendeeId = pyEnv['calendar.attendee'].create({ partner_id: resPartnerId });
|
||||
const calendaMeetingId = pyEnv['calendar.event'].create({
|
||||
res_model: "calendar.event",
|
||||
name: "meeting1",
|
||||
start: "2022-07-06 06:30:00",
|
||||
attendee_ids: [calendarAttendeeId],
|
||||
});
|
||||
pyEnv['mail.activity'].create({
|
||||
name: "Small Meeting",
|
||||
activity_type_id: meetingActivityTypeId,
|
||||
can_write: true,
|
||||
res_id: resPartnerId,
|
||||
res_model: 'res.partner',
|
||||
calendar_event_id: calendaMeetingId,
|
||||
});
|
||||
|
||||
const { click, openFormView } = await start();
|
||||
|
||||
await openFormView(
|
||||
{
|
||||
res_model: 'res.partner',
|
||||
res_id: resPartnerId,
|
||||
},
|
||||
);
|
||||
|
||||
await click('.o_Activity_editButton');
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_calendar_view',
|
||||
"should have opened calendar view"
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
import { defineCalendarModels } from "@calendar/../tests/calendar_test_helpers";
|
||||
import {
|
||||
click,
|
||||
contains,
|
||||
openListView,
|
||||
start,
|
||||
startServer,
|
||||
} from "@mail/../tests/mail_test_helpers";
|
||||
import { test } from "@odoo/hoot";
|
||||
import { preloadBundle, serverState } from "@web/../tests/web_test_helpers";
|
||||
import { serializeDateTime } from "@web/core/l10n/dates";
|
||||
|
||||
const { DateTime } = luxon;
|
||||
|
||||
defineCalendarModels();
|
||||
preloadBundle("web.fullcalendar_lib");
|
||||
|
||||
test("list activity widget: reschedule button in dropdown", async () => {
|
||||
const pyEnv = await startServer();
|
||||
const resPartnerId = pyEnv["res.partner"].create({});
|
||||
const activityTypeId = pyEnv["mail.activity.type"].create({
|
||||
icon: "fa-calendar",
|
||||
name: "Meeting",
|
||||
});
|
||||
const tomorrow = serializeDateTime(DateTime.now().plus({ days: 1 }));
|
||||
const attendeeId = pyEnv["calendar.attendee"].create({ partner_id: resPartnerId });
|
||||
const meetingId = pyEnv["calendar.event"].create({
|
||||
res_model: "calendar.event",
|
||||
name: "meeting1",
|
||||
start: tomorrow,
|
||||
attendee_ids: [attendeeId],
|
||||
});
|
||||
const activityId_1 = pyEnv["mail.activity"].create({
|
||||
name: "OXP",
|
||||
activity_type_id: activityTypeId,
|
||||
date_deadline: tomorrow,
|
||||
state: "planned",
|
||||
can_write: true,
|
||||
res_id: resPartnerId,
|
||||
res_model: "res.partner",
|
||||
calendar_event_id: meetingId,
|
||||
summary: "OXP",
|
||||
});
|
||||
pyEnv["res.partner"].write([serverState.partnerId], {
|
||||
activity_ids: [activityId_1],
|
||||
activity_state: "today",
|
||||
});
|
||||
|
||||
// FIXME: Manually trigger recomputation of related fields
|
||||
pyEnv["res.users"]._applyComputesAndValidate();
|
||||
pyEnv["res.users"][0].activity_ids = [activityId_1];
|
||||
|
||||
await start();
|
||||
await openListView("res.users", {
|
||||
arch: `<list>
|
||||
<field name="activity_ids" widget="list_activity"/>
|
||||
</list>`,
|
||||
});
|
||||
await contains(".o-mail-ListActivity-summary", { text: "OXP" });
|
||||
await click(".o-mail-ActivityButton"); // open the popover
|
||||
await contains(".o-mail-ActivityListPopoverItem-editbtn .fa-pencil", { count: 0 });
|
||||
await contains(".o-mail-ActivityListPopoverItem-editbtn .fa-calendar");
|
||||
});
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
import { defineCalendarModels } from "@calendar/../tests/calendar_test_helpers";
|
||||
import { beforeEach, expect, test } from "@odoo/hoot";
|
||||
import { mockDate } from "@odoo/hoot-mock";
|
||||
import {
|
||||
contains,
|
||||
makeMockServer,
|
||||
MockServer,
|
||||
mountView,
|
||||
onRpc,
|
||||
preloadBundle,
|
||||
serverState,
|
||||
} from "@web/../tests/web_test_helpers";
|
||||
import {
|
||||
changeScale,
|
||||
clickEvent,
|
||||
expandCalendarView,
|
||||
findDateColumn,
|
||||
findTimeRow,
|
||||
} from "@web/../tests/views/calendar/calendar_test_helpers";
|
||||
|
||||
defineCalendarModels();
|
||||
preloadBundle("web.fullcalendar_lib");
|
||||
|
||||
const serverData = {};
|
||||
|
||||
const arch = /*xml*/ `
|
||||
<calendar js_class="attendee_calendar"
|
||||
event_open_popup="1"
|
||||
date_start="start"
|
||||
date_stop="stop"
|
||||
all_day="allday"
|
||||
mode="month"
|
||||
>
|
||||
<field name="partner_ids" options="{'block': True, 'icon': 'fa fa-users'}"
|
||||
filters="1" widget="many2manyattendeeexpandable" write_model="calendar.filters"
|
||||
write_field="partner_id" filter_field="partner_checked" avatar_field="avatar_128"/>
|
||||
<field name="partner_id" string="Organizer" options="{'icon': 'fa fa-user-o'}"/>
|
||||
<field name="user_id"/>
|
||||
<field name="start"/>
|
||||
<field name="stop"/>
|
||||
<field name="allday"/>
|
||||
<field name="res_model_name" invisible="not res_model_name"
|
||||
options="{'icon': 'fa fa-link', 'shouldOpenRecord': true}"/>
|
||||
</calendar>
|
||||
`;
|
||||
|
||||
async function selectTimeStart(startDateTime) {
|
||||
const [startDate, startTime] = startDateTime.split(" ");
|
||||
const startCol = findDateColumn(startDate);
|
||||
const startRow = findTimeRow(startTime);
|
||||
await scrollTo(startRow);
|
||||
|
||||
const startColRect = startCol.getBoundingClientRect();
|
||||
const startRowRect = startRow.getBoundingClientRect();
|
||||
await contains(startRow).click({
|
||||
position: {
|
||||
x: startColRect.x + startColRect.width / 2,
|
||||
y: startRowRect.y + 1,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(async () => {
|
||||
mockDate("2016-12-12 08:00:00", 0);
|
||||
const { env: pyEnv } = await makeMockServer();
|
||||
const [partnerId_1, partnerId_2] = pyEnv["res.partner"].create([
|
||||
{ name: "Partner 1" },
|
||||
{ name: "Partner 2" },
|
||||
]);
|
||||
serverData.partnerId_1 = partnerId_1;
|
||||
serverData.partnerId_2 = partnerId_2;
|
||||
serverData.userId = pyEnv["res.users"].create({ name: "User 1", partner_id: partnerId_1 });
|
||||
serverData.attendeeIds = pyEnv["calendar.attendee"].create([
|
||||
{ partner_id: serverState.partnerId },
|
||||
{ partner_id: partnerId_1 },
|
||||
{ partner_id: partnerId_2 },
|
||||
]);
|
||||
pyEnv["calendar.filters"].create([
|
||||
{ partner_id: partnerId_1, partner_checked: true, user_id: serverState.userId },
|
||||
{ partner_id: partnerId_2, partner_checked: true, user_id: serverData.userId },
|
||||
]);
|
||||
pyEnv["calendar.event"].create([
|
||||
{
|
||||
name: "event 1",
|
||||
start: "2016-12-11 00:00:00",
|
||||
stop: "2016-12-11 01:00:00",
|
||||
attendee_ids: serverData.attendeeIds,
|
||||
partner_ids: [serverState.partnerId, partnerId_1, partnerId_2],
|
||||
},
|
||||
{
|
||||
name: "event 2",
|
||||
start: "2016-12-12 10:55:05",
|
||||
stop: "2016-12-12 14:55:05",
|
||||
attendee_ids: [serverData.attendeeIds[0], serverData.attendeeIds[1]],
|
||||
partner_ids: [serverState.partnerId, partnerId_1],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test("Linked record rendering", async () => {
|
||||
const pyEnv = MockServer.current.env;
|
||||
onRpc("res.users", "has_group", () => true);
|
||||
onRpc("res.users", "check_synchronization_status", () => ({}));
|
||||
onRpc("res.partner", "get_attendee_detail", () => []);
|
||||
onRpc("/calendar/check_credentials", () => ({}));
|
||||
const { id: modelId, display_name } = pyEnv["ir.model"].search_read(
|
||||
[["model", "=", "res.partner"]],
|
||||
["display_name"]
|
||||
)[0];
|
||||
const eventId = pyEnv["calendar.event"].create({
|
||||
user_id: serverData.userId,
|
||||
name: "event With record",
|
||||
start: "2016-12-11 09:00:00",
|
||||
stop: "2016-12-11 10:00:00",
|
||||
attendee_ids: serverData.attendeeIds,
|
||||
partner_ids: [serverState.partnerId, serverData.partnerId_1, serverData.partnerId_2],
|
||||
res_model_id: modelId,
|
||||
});
|
||||
await mountView({ type: "calendar", resModel: "calendar.event", arch });
|
||||
expect(".o_calendar_renderer .fc-view").toHaveCount(1);
|
||||
|
||||
await changeScale("week");
|
||||
await clickEvent(eventId);
|
||||
expect(".fa-link").toHaveCount(1, { message: "A link icon should be present" });
|
||||
expect("li a[href='#']").toHaveText(display_name);
|
||||
});
|
||||
|
||||
test("Default duration rendering", async () => {
|
||||
onRpc("res.users", "has_group", () => true);
|
||||
onRpc("res.users", "check_synchronization_status", () => ({}));
|
||||
onRpc("res.partner", "get_attendee_detail", () => []);
|
||||
onRpc("/calendar/check_credentials", () => ({}));
|
||||
await mountView({ type: "calendar", resModel: "calendar.event", arch });
|
||||
expandCalendarView();
|
||||
await changeScale("week");
|
||||
await selectTimeStart("2016-12-15 15:00:00");
|
||||
await contains(".o-calendar-quick-create--input").edit("Event with new duration", {
|
||||
confirm: false,
|
||||
});
|
||||
await contains(".o-calendar-quick-create--create-btn").click();
|
||||
// This new event is the third
|
||||
await clickEvent(3);
|
||||
expect("div[name='start'] div").toHaveText("Dec 15, 3:00 PM");
|
||||
expect("div[name='stop'] div").toHaveText("Dec 15, 6:15 PM", {
|
||||
message: "The duration should be 3.25 hours",
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
import { defineCalendarModels } from "@calendar/../tests/calendar_test_helpers";
|
||||
import { beforeEach, expect, test } from "@odoo/hoot";
|
||||
import { contains, makeMockServer, mountView, onRpc } from "@web/../tests/web_test_helpers";
|
||||
import { getOrigin } from "@web/core/utils/urls";
|
||||
|
||||
defineCalendarModels();
|
||||
|
||||
const serverData = {};
|
||||
|
||||
beforeEach(async () => {
|
||||
const { env: pyEnv } = await makeMockServer();
|
||||
serverData.partnerIds = pyEnv["res.partner"].create([{ name: "Zeus" }, { name: "Azdaha" }]);
|
||||
serverData.eventId = pyEnv["calendar.event"].create({
|
||||
name: "event 1",
|
||||
partner_ids: serverData.partnerIds,
|
||||
});
|
||||
});
|
||||
|
||||
test("Many2ManyAttendee: basic rendering", async () => {
|
||||
onRpc("get_attendee_detail", (request) => {
|
||||
expect.step("get_attendee_detail");
|
||||
expect(request.model).toBe("res.partner");
|
||||
expect(request.args[0]).toEqual(serverData.partnerIds);
|
||||
expect(request.args[1]).toEqual([serverData.eventId]);
|
||||
return [
|
||||
{ id: serverData.partnerIds[0], name: "Zeus", status: "accepted", color: 0 },
|
||||
{ id: serverData.partnerIds[1], name: "Azdaha", status: "tentative", color: 0 },
|
||||
];
|
||||
});
|
||||
await mountView({
|
||||
type: "form",
|
||||
resModel: "calendar.event",
|
||||
resId: serverData.eventId,
|
||||
arch: /*xml*/ `
|
||||
<form>
|
||||
<field name="partner_ids" widget="many2manyattendee"/>
|
||||
</form>
|
||||
`,
|
||||
});
|
||||
expect(".o_field_widget[name='partner_ids'] div.o_field_tags").toHaveCount(1);
|
||||
expect(".o_field_widget[name='partner_ids'] .o_tag").toHaveCount(2);
|
||||
expect(".o_field_widget[name='partner_ids'] .o_tag:eq(0)").toHaveText("Zeus");
|
||||
expect(
|
||||
".o_field_widget[name='partner_ids'] .o_tag:eq(0) .attendee_tag_status.o_attendee_status_accepted"
|
||||
).toHaveCount(1);
|
||||
expect(".o_field_widget[name='partner_ids'] .o_tag:eq(1)").toHaveText("Azdaha");
|
||||
expect(
|
||||
".o_field_widget[name='partner_ids'] .o_tag:eq(1) .attendee_tag_status.o_attendee_status_tentative"
|
||||
).toHaveCount(1);
|
||||
expect(".o_field_widget[name='partner_ids'] .o_tag:eq(0) img").toHaveCount(1);
|
||||
expect(".o_field_widget[name='partner_ids'] .o_tag:eq(0) img").toHaveAttribute(
|
||||
"data-src",
|
||||
`${getOrigin()}/web/image/res.partner/${serverData.partnerIds[0]}/avatar_128`
|
||||
);
|
||||
expect.verifySteps(["get_attendee_detail"]);
|
||||
});
|
||||
|
||||
test("Many2ManyAttendee: remove own attendee", async () => {
|
||||
onRpc("get_attendee_detail", () => [
|
||||
{ id: serverData.partnerIds[0], name: "Zeus", status: "accepted", color: 0 },
|
||||
{ id: serverData.partnerIds[1], name: "Azdaha", status: "tentative", color: 0 },
|
||||
]);
|
||||
await mountView({
|
||||
type: "form",
|
||||
resModel: "calendar.event",
|
||||
resId: serverData.eventId,
|
||||
arch: /*xml*/ `
|
||||
<form>
|
||||
<field name="partner_ids" widget="many2manyattendee"/>
|
||||
</form>
|
||||
`,
|
||||
});
|
||||
expect(".o_field_widget[name='partner_ids'] .o_tag").toHaveCount(2);
|
||||
|
||||
// Attendee must be able to uninvite itself from the event.
|
||||
await contains(".o_field_widget[name='partner_ids'] .o_delete", { visible: false }).click();
|
||||
await contains(".o_form_button_save").click();
|
||||
expect(".o_field_widget[name='partner_ids'] .o_tag").toHaveCount(1);
|
||||
});
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
import { defineCalendarModels } from "@calendar/../tests/calendar_test_helpers";
|
||||
import { click, contains, start, startServer } from "@mail/../tests/mail_test_helpers";
|
||||
import { test } from "@odoo/hoot";
|
||||
import {
|
||||
asyncStep,
|
||||
mockService,
|
||||
onRpc,
|
||||
preloadBundle,
|
||||
serverState,
|
||||
waitForSteps,
|
||||
} from "@web/../tests/web_test_helpers";
|
||||
|
||||
defineCalendarModels();
|
||||
preloadBundle("web.fullcalendar_lib");
|
||||
|
||||
test("can listen on bus and display notifications in DOM and click OK", async () => {
|
||||
const pyEnv = await startServer();
|
||||
onRpc("/calendar/notify_ack", () => asyncStep("notify_ack"));
|
||||
await start();
|
||||
pyEnv["bus.bus"]._sendone(serverState.partnerId, "calendar.alarm", [
|
||||
{
|
||||
alarm_id: 1,
|
||||
event_id: 2,
|
||||
title: "Meeting",
|
||||
message: "Very old meeting message",
|
||||
timer: 0,
|
||||
notify_at: "1978-04-14 12:45:00",
|
||||
},
|
||||
]);
|
||||
await contains(".o_notification", { text: "Meeting. Very old meeting message" });
|
||||
await click(".o_notification_buttons button", { text: "OK" });
|
||||
await contains(".o_notification", { count: 0 });
|
||||
await waitForSteps(["notify_ack"]);
|
||||
});
|
||||
|
||||
test("can listen on bus and display notifications in DOM and click Detail", async () => {
|
||||
mockService("action", {
|
||||
doAction(actionId) {
|
||||
asyncStep(actionId.type);
|
||||
},
|
||||
});
|
||||
const pyEnv = await startServer();
|
||||
await start();
|
||||
pyEnv["bus.bus"]._sendone(serverState.partnerId, "calendar.alarm", [
|
||||
{
|
||||
alarm_id: 1,
|
||||
event_id: 2,
|
||||
title: "Meeting",
|
||||
message: "Very old meeting message",
|
||||
timer: 0,
|
||||
notify_at: "1978-04-14 12:45:00",
|
||||
},
|
||||
]);
|
||||
await contains(".o_notification", { text: "Meeting. Very old meeting message" });
|
||||
await click(".o_notification_buttons button", { text: "Details" });
|
||||
await contains(".o_notification", { count: 0 });
|
||||
await waitForSteps(["ir.actions.act_window"]);
|
||||
});
|
||||
|
||||
test("can listen on bus and display notifications in DOM and click Snooze", async () => {
|
||||
const pyEnv = await startServer();
|
||||
onRpc("/calendar/notify_ack", () => asyncStep("notify_ack"));
|
||||
await start();
|
||||
pyEnv["bus.bus"]._sendone(serverState.partnerId, "calendar.alarm", [
|
||||
{
|
||||
alarm_id: 1,
|
||||
event_id: 2,
|
||||
title: "Meeting",
|
||||
message: "Very old meeting message",
|
||||
timer: 0,
|
||||
notify_at: "1978-04-14 12:45:00",
|
||||
},
|
||||
]);
|
||||
await contains(".o_notification", { text: "Meeting. Very old meeting message" });
|
||||
await click(".o_notification button", { text: "Snooze" });
|
||||
await contains(".o_notification", { count: 0 });
|
||||
await waitForSteps([]);
|
||||
});
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import { startServer } from "@bus/../tests/helpers/mock_python_environment";
|
||||
|
||||
import { calendarNotificationService } from "@calendar/js/services/calendar_notification_service";
|
||||
import { click, contains } from "@web/../tests/utils";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { start } from "@mail/../tests/helpers/test_utils";
|
||||
|
||||
const serviceRegistry = registry.category("services");
|
||||
|
||||
QUnit.module("Calendar Notification", (hooks) => {
|
||||
hooks.beforeEach(() => {
|
||||
serviceRegistry.add("calendarNotification", calendarNotificationService);
|
||||
});
|
||||
|
||||
QUnit.test(
|
||||
"can listen on bus and display notifications in DOM and click OK",
|
||||
async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const mockRPC = (route, args) => {
|
||||
if (route === "/calendar/notify") {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
if (route === "/calendar/notify_ack") {
|
||||
assert.step("notifyAck");
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
};
|
||||
await start({ mockRPC });
|
||||
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "calendar.alarm", [
|
||||
{
|
||||
alarm_id: 1,
|
||||
event_id: 2,
|
||||
title: "Meeting",
|
||||
message: "Very old meeting message",
|
||||
timer: 0,
|
||||
notify_at: "1978-04-14 12:45:00",
|
||||
},
|
||||
]);
|
||||
await contains(".o_notification", { text: "Very old meeting message" });
|
||||
await click(".o_notification_buttons button", { text: "OK" });
|
||||
await contains(".o_notification", { count: 0 });
|
||||
assert.verifySteps(["notifyAck"]);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"can listen on bus and display notifications in DOM and click Detail",
|
||||
async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const mockRPC = (route, args) => {
|
||||
if (route === "/calendar/notify") {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
};
|
||||
const fakeActionService = {
|
||||
name: "action",
|
||||
start() {
|
||||
return {
|
||||
doAction(actionId) {
|
||||
assert.step(actionId.type);
|
||||
return Promise.resolve(true);
|
||||
},
|
||||
loadState(state, options) {
|
||||
return Promise.resolve(true);
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
serviceRegistry.add("action", fakeActionService, { force: true });
|
||||
await start({ mockRPC });
|
||||
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "calendar.alarm", [
|
||||
{
|
||||
alarm_id: 1,
|
||||
event_id: 2,
|
||||
title: "Meeting",
|
||||
message: "Very old meeting message",
|
||||
timer: 0,
|
||||
notify_at: "1978-04-14 12:45:00",
|
||||
},
|
||||
]);
|
||||
await contains(".o_notification", { text: "Very old meeting message" });
|
||||
await click(".o_notification_buttons button", { text: "Details" });
|
||||
await contains(".o_notification", { count: 0 });
|
||||
assert.verifySteps(["ir.actions.act_window"]);
|
||||
}
|
||||
);
|
||||
|
||||
QUnit.test(
|
||||
"can listen on bus and display notifications in DOM and click Snooze",
|
||||
async (assert) => {
|
||||
const pyEnv = await startServer();
|
||||
const mockRPC = (route, args) => {
|
||||
if (route === "/calendar/notify") {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
if (route === "/calendar/notify_ack") {
|
||||
assert.step("notifyAck");
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
};
|
||||
await start({ mockRPC });
|
||||
pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "calendar.alarm", [
|
||||
{
|
||||
alarm_id: 1,
|
||||
event_id: 2,
|
||||
title: "Meeting",
|
||||
message: "Very old meeting message",
|
||||
timer: 0,
|
||||
notify_at: "1978-04-14 12:45:00",
|
||||
},
|
||||
]);
|
||||
await contains(".o_notification", { text: "Very old meeting message" });
|
||||
await click(".o_notification button", { text: "Snooze" });
|
||||
await contains(".o_notification", { count: 0 });
|
||||
assert.verifySteps([], "should only close the notification withtout calling a rpc");
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import { CalendarEvent } from "./mock_server/mock_models/calendar_event";
|
||||
import { CalendarAttendee } from "./mock_server/mock_models/calendar_attendee";
|
||||
import { ResUsers } from "./mock_server/mock_models/res_users";
|
||||
import { MailActivity } from "./mock_server/mock_models/mail_activity";
|
||||
import { CalendarFilters } from "./mock_server/mock_models/calendar_filters";
|
||||
|
||||
import { mailModels } from "@mail/../tests/mail_test_helpers";
|
||||
import { defineModels } from "@web/../tests/web_test_helpers";
|
||||
|
||||
export const calendarModels = {
|
||||
CalendarAttendee,
|
||||
CalendarEvent,
|
||||
CalendarFilters,
|
||||
ResUsers,
|
||||
MailActivity,
|
||||
};
|
||||
|
||||
export function defineCalendarModels() {
|
||||
return defineModels({ ...mailModels, ...calendarModels });
|
||||
}
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { getFixture } from "@web/../tests/helpers/utils";
|
||||
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
|
||||
|
||||
let serverData;
|
||||
let target;
|
||||
|
||||
QUnit.module(
|
||||
"calendar",
|
||||
{
|
||||
beforeEach: function () {
|
||||
target = getFixture();
|
||||
serverData = {
|
||||
models: {
|
||||
event: {
|
||||
fields: {
|
||||
partner_ids: {
|
||||
string: "Partners",
|
||||
type: "many2many",
|
||||
relation: "partner",
|
||||
},
|
||||
},
|
||||
records: [
|
||||
{
|
||||
id: 14,
|
||||
partner_ids: [1, 2],
|
||||
},
|
||||
],
|
||||
},
|
||||
partner: {
|
||||
fields: {
|
||||
name: { string: "Name", type: "char" },
|
||||
},
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
name: "Jesus",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "Mahomet",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
setupViewRegistries();
|
||||
},
|
||||
},
|
||||
function () {
|
||||
QUnit.test("Many2ManyAttendee: basic rendering", async function (assert) {
|
||||
await makeView({
|
||||
type: "form",
|
||||
resModel: "event",
|
||||
serverData,
|
||||
resId: 14,
|
||||
arch: `
|
||||
<form>
|
||||
<field name="partner_ids" widget="many2manyattendee"/>
|
||||
</form>`,
|
||||
mockRPC(route, args) {
|
||||
if (args.method === "get_attendee_detail") {
|
||||
assert.step(args.method);
|
||||
assert.strictEqual(
|
||||
args.model,
|
||||
"res.partner",
|
||||
"the method should only be called on res.partner"
|
||||
);
|
||||
assert.deepEqual(
|
||||
args.args[0],
|
||||
[1, 2],
|
||||
"the partner ids should be passed as argument"
|
||||
);
|
||||
assert.deepEqual(
|
||||
args.args[1],
|
||||
[14],
|
||||
"the event id should be passed as argument"
|
||||
);
|
||||
return Promise.resolve([
|
||||
{ id: 1, name: "Jesus", status: "accepted", color: 0 },
|
||||
{ id: 2, name: "Mahomet", status: "tentative", color: 0 },
|
||||
]);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
assert.hasClass(
|
||||
target.querySelector('.o_field_widget[name="partner_ids"] div'),
|
||||
"o_field_tags"
|
||||
);
|
||||
assert.containsN(
|
||||
target,
|
||||
'.o_field_widget[name="partner_ids"] .badge',
|
||||
2,
|
||||
"there should be 2 tags"
|
||||
);
|
||||
const badges = target.querySelectorAll('.o_field_widget[name="partner_ids"] .badge');
|
||||
assert.strictEqual(
|
||||
badges[0].textContent.trim(),
|
||||
"Jesus",
|
||||
"the tag should be correctly named"
|
||||
);
|
||||
assert.hasClass(
|
||||
badges[0].querySelector("img"),
|
||||
"o_attendee_border_accepted",
|
||||
"Jesus should attend the meeting"
|
||||
);
|
||||
assert.strictEqual(
|
||||
badges[1].textContent.trim(),
|
||||
"Mahomet",
|
||||
"the tag should be correctly named"
|
||||
);
|
||||
assert.hasClass(
|
||||
badges[1].querySelector("img"),
|
||||
"o_attendee_border_tentative",
|
||||
"Mohamet should still confirm his attendance to the meeting"
|
||||
);
|
||||
assert.containsOnce(badges[0], "img", "should have img tag");
|
||||
assert.hasAttrValue(
|
||||
badges[0].querySelector("img"),
|
||||
"data-src",
|
||||
"/web/image/partner/1/avatar_128",
|
||||
"should have correct avatar image"
|
||||
);
|
||||
assert.verifySteps(["get_attendee_detail"]);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
// ensure mail override is applied first.
|
||||
import '@mail/../tests/helpers/mock_server';
|
||||
|
||||
import { patch } from '@web/core/utils/patch';
|
||||
import { MockServer } from '@web/../tests/helpers/mock_server';
|
||||
|
||||
import { datetime_to_str } from 'web.time';
|
||||
|
||||
patch(MockServer.prototype, 'calendar', {
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
async _performRPC(route, args) {
|
||||
// mail.activity methods
|
||||
if (args.model === 'mail.activity' && args.method === 'action_create_calendar_event') {
|
||||
return {
|
||||
type: 'ir.actions.act_window',
|
||||
name: "Meetings",
|
||||
res_model: 'calendar.event',
|
||||
view_mode: 'calendar',
|
||||
views: [[false, 'calendar']],
|
||||
target: 'current',
|
||||
};
|
||||
}
|
||||
// calendar.event methods
|
||||
if (args.model === 'calendar.event' && args.method === 'check_access_rights') {
|
||||
return true;
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private Mocked Methods
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Simulates `_systray_get_calendar_event_domain` on `res.users`.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_mockResUsers_SystrayGetCalendarEventDomain() {
|
||||
const startDate = new Date();
|
||||
startDate.setUTCHours(0, 0, 0, 0);
|
||||
const endDate = new Date();
|
||||
endDate.setUTCHours(23, 59, 59, 999);
|
||||
const currentPartnerAttendeeIds = this.pyEnv['calendar.attendee'].search([['partner_id', '=', this.currentPartnerId]]);
|
||||
return [
|
||||
'&',
|
||||
'|',
|
||||
'&',
|
||||
'|',
|
||||
['start', '>=', datetime_to_str(startDate)],
|
||||
['stop', '>=', datetime_to_str(startDate)],
|
||||
['start', '<=', datetime_to_str(endDate)],
|
||||
'&',
|
||||
['allday', '=', true],
|
||||
['start_date', '=', datetime_to_str(startDate)],
|
||||
['attendee_ids', 'in', currentPartnerAttendeeIds],
|
||||
];
|
||||
},
|
||||
|
||||
/**
|
||||
* Simulates `systray_get_activities` on `res.users`.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
_mockResUsersSystrayGetActivities() {
|
||||
const activities = this._super(...arguments);
|
||||
const meetingsLines = this.pyEnv['calendar.event'].searchRead(
|
||||
this._mockResUsers_SystrayGetCalendarEventDomain(),
|
||||
{
|
||||
fields: ['id', 'start', 'name', 'allday', 'attendee_status'],
|
||||
order: 'start',
|
||||
}
|
||||
).filter(meetingLine => meetingLine['attendee_status'] !== 'declined');
|
||||
if (meetingsLines.length) {
|
||||
activities.unshift({
|
||||
id: 'calendar.event', // for simplicity
|
||||
meetings: meetingsLines,
|
||||
model: 'calendar.event',
|
||||
name: 'Today\'s Meetings',
|
||||
type: 'meeting',
|
||||
});
|
||||
}
|
||||
return activities;
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import { patch } from "@web/core/utils/patch";
|
||||
import { MockServer } from '@web/../tests/helpers/mock_server';
|
||||
|
||||
patch(MockServer.prototype, {
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
async _performRPC(route, args) {
|
||||
// calendar.event methods
|
||||
if (args.model === 'calendar.event' && args.method === 'has_access') {
|
||||
return true;
|
||||
}
|
||||
return super._performRPC(...arguments);
|
||||
},
|
||||
});
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { addModelNamesToFetch } from '@bus/../tests/helpers/model_definitions_helpers';
|
||||
|
||||
addModelNamesToFetch(['calendar.event', 'calendar.attendee']);
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { registry } from '@web/core/registry';
|
||||
|
||||
const viewArchsRegistry = registry.category('bus.view.archs');
|
||||
const calendarArchsRegistry = viewArchsRegistry.category('calendar');
|
||||
|
||||
calendarArchsRegistry.add('default', '<calendar date_start="start"/>');
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import FormView from "web.FormView";
|
||||
import testUtils from "web.test_utils";
|
||||
|
||||
var createView = testUtils.createView;
|
||||
|
||||
QUnit.module(
|
||||
"Legacy calendar",
|
||||
{
|
||||
beforeEach: function () {
|
||||
this.data = {
|
||||
event: {
|
||||
fields: {
|
||||
partner_ids: { string: "Partners", type: "many2many", relation: "partner" },
|
||||
},
|
||||
records: [
|
||||
{
|
||||
id: 14,
|
||||
partner_ids: [1, 2],
|
||||
},
|
||||
],
|
||||
},
|
||||
partner: {
|
||||
fields: {
|
||||
name: { string: "Name", type: "char" },
|
||||
},
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
name: "Jesus",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "Mahomet",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
function () {
|
||||
QUnit.test("many2manyattendee widget: basic rendering", async function (assert) {
|
||||
assert.expect(12);
|
||||
|
||||
var form = await createView({
|
||||
View: FormView,
|
||||
model: "event",
|
||||
data: this.data,
|
||||
res_id: 14,
|
||||
debug: 1,
|
||||
arch:
|
||||
"<form>" + '<field name="partner_ids" widget="many2manyattendee"/>' + "</form>",
|
||||
mockRPC: function (route, args) {
|
||||
if (args.method === "get_attendee_detail") {
|
||||
assert.strictEqual(
|
||||
args.model,
|
||||
"res.partner",
|
||||
"the method should only be called on res.partner"
|
||||
);
|
||||
assert.deepEqual(
|
||||
args.args[0],
|
||||
[1, 2],
|
||||
"the partner ids should be passed as argument"
|
||||
);
|
||||
assert.deepEqual(
|
||||
args.args[1],
|
||||
[14],
|
||||
"the event id should be passed as argument"
|
||||
);
|
||||
return Promise.resolve([
|
||||
{ id: 1, name: "Jesus", status: "accepted", color: 0 },
|
||||
{ id: 2, name: "Mahomet", status: "tentative", color: 0 },
|
||||
]);
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
|
||||
assert.hasClass(form.$('.o_field_widget[name="partner_ids"]'), "o_field_many2manytags");
|
||||
assert.containsN(
|
||||
form,
|
||||
'.o_field_widget[name="partner_ids"] .badge',
|
||||
2,
|
||||
"there should be 2 tags"
|
||||
);
|
||||
assert.strictEqual(
|
||||
form.$('.o_field_widget[name="partner_ids"] .badge:first').text().trim(),
|
||||
"Jesus",
|
||||
"the tag should be correctly named"
|
||||
);
|
||||
assert.hasClass(
|
||||
form.$('.o_field_widget[name="partner_ids"] .badge:first img'),
|
||||
"o_attendee_border_accepted",
|
||||
"Jesus should attend the meeting"
|
||||
);
|
||||
assert.strictEqual(
|
||||
form.$('.o_field_widget[name="partner_ids"] .badge[data-id="2"]').text().trim(),
|
||||
"Mahomet",
|
||||
"the tag should be correctly named"
|
||||
);
|
||||
assert.hasClass(
|
||||
form.el.querySelector(
|
||||
'.o_field_widget[name="partner_ids"] .badge[data-id="2"] img'
|
||||
),
|
||||
"o_attendee_border_tentative",
|
||||
"Mohamet should still confirm his attendance to the meeting"
|
||||
);
|
||||
assert.hasClass(
|
||||
form.el.querySelector(".o_field_many2manytags"),
|
||||
"avatar",
|
||||
"should have avatar class"
|
||||
);
|
||||
assert.containsOnce(
|
||||
form,
|
||||
".o_field_many2manytags.avatar.o_field_widget .badge:first img",
|
||||
"should have img tag"
|
||||
);
|
||||
assert.hasAttrValue(
|
||||
form.$(".o_field_many2manytags.avatar.o_field_widget .badge:first img"),
|
||||
"data-src",
|
||||
"/web/image/partner/1/avatar_128",
|
||||
"should have correct avatar image"
|
||||
);
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import { models } from "@web/../tests/web_test_helpers";
|
||||
|
||||
export class CalendarAttendee extends models.ServerModel {
|
||||
_name = "calendar.attendee";
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
import { models, fields, serverState } from "@web/../tests/web_test_helpers";
|
||||
|
||||
export class CalendarEvent extends models.ServerModel {
|
||||
_name = "calendar.event";
|
||||
|
||||
user_id = fields.Generic({ default: serverState.userId });
|
||||
partner_id = fields.Generic({ default: serverState.partnerId });
|
||||
partner_ids = fields.Generic({ default: [[6, 0, [serverState.partnerId]]] });
|
||||
|
||||
has_access() {
|
||||
return true;
|
||||
}
|
||||
|
||||
get_default_duration() {
|
||||
return 3.25;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import { models } from "@web/../tests/web_test_helpers";
|
||||
|
||||
export class CalendarFilters extends models.ServerModel {
|
||||
_name = "calendar.filters";
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
import { mailModels, openView } from "@mail/../tests/mail_test_helpers";
|
||||
import { fields } from "@web/../tests/web_test_helpers";
|
||||
|
||||
export class MailActivity extends mailModels.MailActivity {
|
||||
name = fields.Char();
|
||||
|
||||
async action_create_calendar_event() {
|
||||
await openView({
|
||||
res_model: "calendar.event",
|
||||
views: [[false, "calendar"]],
|
||||
});
|
||||
return {
|
||||
type: "ir.actions.act_window",
|
||||
name: "Meetings",
|
||||
res_model: "calendar.event",
|
||||
view_mode: "calendar",
|
||||
views: [[false, "calendar"]],
|
||||
target: "current",
|
||||
};
|
||||
}
|
||||
unlink_w_meeting() {
|
||||
const eventIds = this.map((act) => act.calendar_event_id);
|
||||
const res = this.unlink(arguments[0]);
|
||||
this.env["calendar.event"].unlink(eventIds);
|
||||
return res;
|
||||
}
|
||||
|
||||
/** @param {number[]} ids */
|
||||
_to_store(store) {
|
||||
super._to_store(...arguments);
|
||||
for (const activity of this) {
|
||||
if (activity.calendar_event_id) {
|
||||
store._add_record_fields(this.browse(activity.id), {
|
||||
calendar_event_id: activity.calendar_event_id,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
import { mailModels } from "@mail/../tests/mail_test_helpers";
|
||||
import { serverState } from "@web/../tests/web_test_helpers";
|
||||
import { serializeDateTime } from "@web/core/l10n/dates";
|
||||
const { DateTime } = luxon;
|
||||
|
||||
export class ResUsers extends mailModels.ResUsers {
|
||||
/**
|
||||
* Simulates `_systray_get_calendar_event_domain` on `res.users`.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_systray_get_calendar_event_domain() {
|
||||
const startDate = DateTime.fromObject({
|
||||
hours: 0,
|
||||
minutes: 0,
|
||||
seconds: 0,
|
||||
milliseconds: 0,
|
||||
});
|
||||
const endDate = DateTime.fromObject({
|
||||
hours: 23,
|
||||
minutes: 59,
|
||||
seconds: 59,
|
||||
milliseconds: 999,
|
||||
});
|
||||
|
||||
const currentPartnerAttendeeIds = this.env["calendar.attendee"].search([
|
||||
["partner_id", "=", serverState.partnerId],
|
||||
["state", "!=", "declined"],
|
||||
]);
|
||||
return [
|
||||
"&",
|
||||
"|",
|
||||
"&",
|
||||
"|",
|
||||
["start", ">=", serializeDateTime(startDate)],
|
||||
["stop", ">=", serializeDateTime(startDate)],
|
||||
["start", "<=", serializeDateTime(endDate)],
|
||||
// FIXME: Makes "activity_menu.test.js" fail
|
||||
// "&",
|
||||
// ["allday", "=", true],
|
||||
// ["start_date", "=", serializeDateTime(startDate)],
|
||||
["attendee_ids", "in", [...currentPartnerAttendeeIds]],
|
||||
];
|
||||
}
|
||||
|
||||
/** @override */
|
||||
_get_activity_groups() {
|
||||
const activities = super._get_activity_groups();
|
||||
const meetingsLines = this.env["calendar.event"].search_read(
|
||||
this._systray_get_calendar_event_domain(),
|
||||
{
|
||||
fields: ["id", "start", "name", "allday"],
|
||||
order: "start",
|
||||
}
|
||||
);
|
||||
if (meetingsLines.length) {
|
||||
activities.unshift({
|
||||
id: "calendar.event", // for simplicity
|
||||
meetings: meetingsLines,
|
||||
model: "calendar.event",
|
||||
name: "Today's Meetings",
|
||||
type: "meeting",
|
||||
});
|
||||
}
|
||||
return activities;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { start, startServer } from '@mail/../tests/helpers/test_utils';
|
||||
|
||||
import { patchDate, patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
|
||||
QUnit.module('calendar', {}, function () {
|
||||
QUnit.module('ActivityMenu');
|
||||
|
||||
QUnit.test('activity menu widget:today meetings', async function (assert) {
|
||||
assert.expect(6);
|
||||
|
||||
patchDate(2018, 3, 20, 6, 0, 0);
|
||||
const pyEnv = await startServer();
|
||||
const calendarAttendeeId1 = pyEnv['calendar.attendee'].create({ partner_id: pyEnv.currentPartnerId });
|
||||
pyEnv['calendar.event'].create([
|
||||
{
|
||||
res_model: "calendar.event",
|
||||
name: "meeting1",
|
||||
start: "2018-04-20 06:30:00",
|
||||
attendee_ids: [calendarAttendeeId1],
|
||||
},
|
||||
{
|
||||
res_model: "calendar.event",
|
||||
name: "meeting2",
|
||||
start: "2018-04-20 09:30:00",
|
||||
attendee_ids: [calendarAttendeeId1],
|
||||
},
|
||||
]);
|
||||
const { click, env } = await start();
|
||||
assert.containsOnce(document.body, '.o_ActivityMenuView', 'should contain an instance of widget');
|
||||
|
||||
await click('.dropdown-toggle[title="Activities"]');
|
||||
|
||||
patchWithCleanup(env.services.action, {
|
||||
doAction(action) {
|
||||
assert.strictEqual(action, "calendar.action_calendar_event", 'should open meeting calendar view in day mode');
|
||||
},
|
||||
});
|
||||
|
||||
assert.ok(document.querySelector('.o_meeting_filter'), "should be a meeting");
|
||||
assert.containsN(document.body, '.o_meeting_filter', 2, 'there should be 2 meetings');
|
||||
assert.hasClass(document.querySelector('.o_meeting_filter'), 'o_meeting_bold', 'this meeting is yet to start');
|
||||
assert.doesNotHaveClass(document.querySelectorAll('.o_meeting_filter')[1], 'o_meeting_bold', 'this meeting has been started');
|
||||
|
||||
await click('.o_ActivityMenuView_activityGroup');
|
||||
});
|
||||
});
|
||||
|
|
@ -1,155 +1,132 @@
|
|||
/** @odoo-module **/
|
||||
import tour from 'web_tour.tour';
|
||||
import { registry } from "@web/core/registry";
|
||||
import { stepUtils } from "@web_tour/tour_utils";
|
||||
|
||||
const todayDate = function() {
|
||||
let now = new Date();
|
||||
let year = now.getFullYear();
|
||||
let month = String(now.getMonth() + 1).padStart(2, '0');
|
||||
let day = String(now.getDate()).padStart(2, '0');
|
||||
const todayDate = function () {
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(now.getDate()).padStart(2, "0");
|
||||
|
||||
return `${month}/${day}/${year} 10:00:00`;
|
||||
};
|
||||
|
||||
tour.register('calendar_appointments_hour_tour', {
|
||||
url: '/web',
|
||||
test: true,
|
||||
}, [
|
||||
tour.stepUtils.showAppsMenuItem(),
|
||||
{
|
||||
trigger: '.o_app[data-menu-xmlid="calendar.mail_menu_calendar"]',
|
||||
content: 'Open Calendar',
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
trigger: '.o-calendar-button-new',
|
||||
content: 'Create a new event',
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
trigger: '#name',
|
||||
content: 'Give a name to the new event',
|
||||
run: 'text TEST EVENT',
|
||||
},
|
||||
{
|
||||
trigger: '#start',
|
||||
content: 'Give a date to the new event',
|
||||
run: `text ${todayDate()}`,
|
||||
},
|
||||
{
|
||||
trigger: '.fa-cloud-upload',
|
||||
content: 'Save the new event',
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
trigger: '.dropdown-item:contains("Calendar")',
|
||||
content: 'Go back to Calendar view',
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
trigger: '.dropdown-toggle:contains("Week")',
|
||||
content: 'Click to change calendar view',
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
trigger: '.dropdown-item:contains("Month")',
|
||||
content: 'Change the calendar view to Month',
|
||||
run: 'click',
|
||||
},
|
||||
{
|
||||
trigger: '.fc-day-header:contains("Monday")',
|
||||
content: 'Change the calendar view to week',
|
||||
},
|
||||
{
|
||||
trigger: '.fc-time:contains("10:00")',
|
||||
content: 'Check the time is properly displayed',
|
||||
},
|
||||
{
|
||||
trigger: '.o_event_title:contains("TEST EVENT")',
|
||||
content: 'Check the event title',
|
||||
},
|
||||
]);
|
||||
registry.category("web_tour.tours").add("calendar_appointments_hour_tour", {
|
||||
url: "/odoo",
|
||||
steps: () => [
|
||||
stepUtils.showAppsMenuItem(),
|
||||
{
|
||||
trigger: '.o_app[data-menu-xmlid="calendar.mail_menu_calendar"]',
|
||||
content: "Open Calendar",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o-calendar-button-new",
|
||||
content: "Create a new event",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "#name_0",
|
||||
content: "Give a name to the new event",
|
||||
run: "edit TEST EVENT",
|
||||
},
|
||||
{
|
||||
trigger: "div[name='start'] button",
|
||||
content: "Open the date picker",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: "#start_0",
|
||||
content: "Give a date to the new event",
|
||||
run: `edit ${todayDate()}`,
|
||||
},
|
||||
{
|
||||
trigger: "#duration_0",
|
||||
content: "Give a duration to the new event",
|
||||
run: "edit 02:00",
|
||||
},
|
||||
{
|
||||
trigger: ".fa-cloud-upload",
|
||||
content: "Save the new event",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".o_back_button",
|
||||
content: "Go back to Calendar view",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".scale_button_selection",
|
||||
content: "Click to change calendar view",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: '.dropdown-item:contains("Month")',
|
||||
content: "Change the calendar view to Month",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: ".fc-col-header-cell.fc-day.fc-day-mon",
|
||||
content: "Check the day is properly displayed",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: '.fc-time:contains("10:00")',
|
||||
content: "Check the time is properly displayed",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
trigger: '.o_event_title:contains("TEST EVENT")',
|
||||
content: "Check the event title",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
tour.register('test_calendar_delete_tour', {
|
||||
test: true,
|
||||
},
|
||||
[
|
||||
{
|
||||
content: 'Select filter (everybody)',
|
||||
trigger: 'div[data-value="all"] input',
|
||||
},
|
||||
{
|
||||
content: 'Click on the event (focus + waiting)',
|
||||
trigger: 'a .fc-content:contains("Test Event")',
|
||||
async run() {
|
||||
$('a .fc-content:contains("Test Event")').click();
|
||||
await new Promise((r) => setTimeout(r, 1000));
|
||||
$('a .fc-content:contains("Test Event")').click();
|
||||
const clickOnTheEvent = {
|
||||
content: "Click on the event (focus + waiting)",
|
||||
trigger: 'a .fc-event-main:contains("Test Event")',
|
||||
async run(actions) {
|
||||
await actions.click();
|
||||
await new Promise((r) => setTimeout(r, 1000));
|
||||
const custom = document.querySelector(".o_cw_custom_highlight");
|
||||
if (custom) {
|
||||
custom.click();
|
||||
}
|
||||
},
|
||||
{
|
||||
content: 'Delete the event',
|
||||
trigger: '.o_cw_popover_delete',
|
||||
},
|
||||
{
|
||||
content: 'Validate the deletion',
|
||||
trigger:'button:contains("Ok")',
|
||||
async run() {
|
||||
$('button:contains("Ok")').click();
|
||||
await new Promise((r) => setTimeout(r, 1000));
|
||||
}
|
||||
},
|
||||
]);
|
||||
};
|
||||
|
||||
tour.register('test_calendar_decline_tour', {
|
||||
test: true,
|
||||
},
|
||||
[
|
||||
{
|
||||
content: 'Click on the event (focus + waiting)',
|
||||
trigger: 'a .fc-content:contains("Test Event")',
|
||||
async run() {
|
||||
$('a .fc-content:contains("Test Event")').click();
|
||||
await new Promise((r) => setTimeout(r, 1000));
|
||||
$('a .fc-content:contains("Test Event")').click();
|
||||
}
|
||||
},
|
||||
{
|
||||
content: 'Delete the event',
|
||||
trigger: '.o_cw_popover_delete',
|
||||
},
|
||||
{
|
||||
content: 'Wait declined status',
|
||||
trigger: '.o_attendee_status_declined',
|
||||
},
|
||||
]);
|
||||
registry.category("web_tour.tours").add("test_calendar_delete_tour", {
|
||||
steps: () => [
|
||||
clickOnTheEvent,
|
||||
{
|
||||
trigger: ".o_cw_popover",
|
||||
},
|
||||
{
|
||||
content: "Delete the event",
|
||||
trigger: ".o_cw_popover_delete",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Validate the deletion",
|
||||
trigger: 'button:contains("Delete")',
|
||||
run: "click",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
tour.register('test_calendar_decline_with_everybody_filter_tour', {
|
||||
test: true,
|
||||
},
|
||||
[
|
||||
{
|
||||
content: 'Select filter (everybody)',
|
||||
trigger: 'div[data-value="all"] input',
|
||||
},
|
||||
{
|
||||
content: 'Click on the event (focus + waiting)',
|
||||
trigger: 'a .fc-content:contains("Test Event")',
|
||||
async run() {
|
||||
$('a .fc-content:contains("Test Event")').click();
|
||||
await new Promise((r) => setTimeout(r, 1000));
|
||||
$('a .fc-content:contains("Test Event")').click();
|
||||
}
|
||||
},
|
||||
{
|
||||
content: 'Delete the event',
|
||||
trigger: '.o_cw_popover_delete',
|
||||
},
|
||||
{
|
||||
content: 'Select filter (everybody)',
|
||||
trigger: 'div[data-value="all"] input',
|
||||
},
|
||||
{
|
||||
content: 'Wait declined status',
|
||||
trigger: '.o_attendee_status_declined',
|
||||
},
|
||||
]);
|
||||
registry.category("web_tour.tours").add("test_calendar_decline_tour", {
|
||||
steps: () => [
|
||||
clickOnTheEvent,
|
||||
{
|
||||
trigger: ".o_cw_popover",
|
||||
},
|
||||
{
|
||||
content: "Delete the event",
|
||||
trigger: ".o_cw_popover_delete",
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: "Wait declined status",
|
||||
trigger: ".o_attendee_status_declined",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue