import { expect, test, beforeEach, describe } from "@odoo/hoot"; import { mockDate, animationFrame, runAllTimers } from "@odoo/hoot-mock"; import { click, queryAllTexts, queryFirst, queryOne, waitFor } from "@odoo/hoot-dom"; import { contains, mountView, onRpc } from "@web/../tests/web_test_helpers"; import { defineProjectModels, ProjectTask } from "./project_models"; import { serializeDateTime } from "@web/core/l10n/dates"; describe.current.tags("desktop"); defineProjectModels(); beforeEach(() => { mockDate("2024-01-03 12:00:00", +0); ProjectTask._views["form"] = `
`; ProjectTask._records = [ { id: 1, name: "Task-1", date_deadline: "2024-01-09 07:00:00", create_date: "2024-01-03 12:00:00", project_id: 1, stage_id: 1, state: "01_in_progress", user_ids: [], display_name: "Task-1", }, { id: 10, name: "Task-10", project_id: 1, stage_id: 1, state: "01_in_progress", user_ids: [], display_name: "Task-10", }, { id: 11, name: "Task-11", project_id: 1, stage_id: 1, state: "1_done", user_ids: [], display_name: "Task-11", is_closed: true, }, ]; onRpc("has_access", () => true); }); const calendarMountParams = { resModel: "project.task", type: "calendar", arch: ` `, }; test("test Project Task Calendar Popover with task_stage_with_state_selection widget", async () => { await mountView(calendarMountParams); await click("a.fc-daygrid-event"); // Skipping setTimeout while clicking event in calendar for calendar popover to appear. // There is a timeout set in the useCalendarPopover. await runAllTimers(); expect(queryOne(".o_field_task_stage_with_state_selection > div").childElementCount).toBe(2); }); test("test task_stage_with_state_selection widget with non-editable state", async () => { await mountView({ ...calendarMountParams, arch: ` `, }); await click("a.fc-daygrid-event"); // Skipping setTimeout while clicking event in calendar for calendar popover to appear. // There is a timeout set in the useCalendarPopover. await runAllTimers(); await click("button[title='In Progress']"); expect(".project_task_state_selection_menu").toHaveCount(0); }); test("test task_stage_with_state_selection widget with editable state", async () => { await mountView({ ...calendarMountParams, arch: ` `, }); await click("a.fc-daygrid-event"); // Skipping setTimeout while clicking event in calendar for calendar popover to appear. // There is a timeout set in the useCalendarPopover. await runAllTimers(); await click(".o-dropdown div[title='In Progress']"); await animationFrame(); expect(".project_task_state_selection_menu").toHaveCount(1); await click(".o_status_green"); // Checking if click on the state in selection menu works(changes in record) await animationFrame(); expect(".o-dropdown .o_status").toHaveStyle({ color: "rgb(0, 136, 24)" }); }); test("Display closed tasks as past event", async () => { ProjectTask._records.push({ id: 2, name: "Task-2", date_deadline: "2024-01-09 07:00:00", create_date: "2024-01-03 12:00:00", project_id: 1, stage_id: 1, state: "1_done", user_ids: [], display_name: "Task-2", }); ProjectTask._records.push({ id: 3, name: "Task-3", date_deadline: "2024-01-09 07:00:00", create_date: "2024-01-03 12:00:00", project_id: 1, stage_id: 1, state: "1_canceled", user_ids: [], display_name: "Task-3", }); ProjectTask._records.push({ id: 4, name: "Task-4", date_deadline: "2024-01-09 07:00:00", create_date: "2024-01-03 12:00:00", project_id: 1, stage_id: 1, state: "1_canceled", user_ids: [], display_name: "Task-4", is_closed: true, }); await mountView(calendarMountParams); expect(".o_event").toHaveCount(4); expect(".o_event.o_past_event").toHaveCount(3); }); test("tasks to schedule should not be visible in the sidebar if no default project set in the context", async () => { onRpc("project.task", "search_read", ({ method }) => { expect.step(method); }); onRpc("project.task", "web_search_read", () => { expect.step("fetch tasks to schedule"); }); await mountView(calendarMountParams); expect(".o_calendar_view").toHaveCount(1); expect(".o_task_to_plan_draggable").toHaveCount(0); expect.verifySteps(["search_read"]); }); test("tasks to plan should be visible in the sidebar when `default_project_id` is set in the context", async () => { onRpc("project.task", "search_read", ({ method }) => { expect.step(method); }); onRpc("project.task", "web_search_read", () => { expect.step("fetch tasks to schedule"); }); await mountView({ ...calendarMountParams, context: { default_project_id: 1 }, }); expect(".o_calendar_view").toHaveCount(1); expect(".o_task_to_plan_draggable").toHaveCount(2); expect(queryAllTexts(".o_task_to_plan_draggable")).toEqual(['Task-10', 'Task-11']); expect(".o_calendar_view .o_calendar_sidebar h5").toHaveText("Drag Tasks to Schedule"); expect.verifySteps(["search_read", "fetch tasks to schedule"]); }); test("search domain should be taken into account in Tasks to Schedule", async () => { onRpc("project.task", "search_read", ({ method }) => { expect.step(method); }); onRpc("project.task", "web_search_read", ({ method }) => { expect.step("fetch tasks to schedule"); }); await mountView({ ...calendarMountParams, context: { default_project_id: 1 }, domain: [['is_closed', '=', false]], }); expect(".o_calendar_view").toHaveCount(1); expect(".o_task_to_plan_draggable").toHaveCount(1); expect(".o_task_to_plan_draggable").toHaveText('Task-10'); expect(".o_calendar_view .o_calendar_sidebar h5").toHaveText("Drag Tasks to Schedule"); expect.verifySteps(["search_read", "fetch tasks to schedule"]); }); test("planned dates used in search domain should not be taken into account in Tasks to Schedule", async () => { onRpc("project.task", "search_read", ({ method }) => { expect.step(method); }); onRpc("project.task", "web_search_read", ({ method }) => { expect.step("fetch tasks to schedule"); }); await mountView({ ...calendarMountParams, context: { default_project_id: 1 }, domain: [['is_closed', '=', false], ['date_deadline', '!=', false], ['planned_date_begin', '!=', false]], }); expect(".o_calendar_view").toHaveCount(1); expect(".o_task_to_plan_draggable").toHaveCount(1); expect(".o_task_to_plan_draggable").toHaveText('Task-10'); expect(".o_calendar_view .o_calendar_sidebar h5").toHaveText("Drag Tasks to Schedule"); expect.verifySteps(["search_read", "fetch tasks to schedule"]); }); test("test drag and drop a task to schedule in calendar view in month scale", async () => { let expectedDate = null; onRpc("project.task", "search_read", ({ method }) => { expect.step(method); }); onRpc("project.task", "web_search_read", ({ method }) => { expect.step("fetch tasks to schedule"); }); onRpc("project.task", "plan_task_in_calendar", ({ args }) => { const [taskIds, vals] = args; expect(taskIds).toEqual([10]); const expectedDateDeadline = serializeDateTime(expectedDate.set({ hours: 19 })); expect(vals).toEqual({ date_deadline: expectedDateDeadline, }); expect.step("plan task"); }); await mountView({ ...calendarMountParams, context: { default_project_id: 1 }, }); expect(".o_task_to_plan_draggable").toHaveCount(2); const { drop, moveTo } = await contains(".o_task_to_plan_draggable:first").drag(); const dateCell = queryFirst(".fc-day.fc-day-today.fc-daygrid-day"); expectedDate = luxon.DateTime.fromISO(dateCell.dataset.date); await moveTo(dateCell); expect(dateCell).toHaveClass("o-highlight"); await drop(); expect.verifySteps(["search_read", "fetch tasks to schedule", "plan task", "search_read"]); expect(".o_task_to_plan_draggable").toHaveCount(1); expect(".o_task_to_plan_draggable").toHaveText("Task-11"); }); test("project.task (calendar): toggle sub-tasks", async () => { ProjectTask._records = [ { id: 1, project_id: 1, name: "Task 1", stage_id: 1, display_in_project: true, date_deadline: "2024-01-09 07:00:00", create_date: "2024-01-03 12:00:00", }, { id: 2, project_id: 1, name: "Task 2", stage_id: 1, display_in_project: false, date_deadline: "2024-01-09 07:00:00", create_date: "2024-01-03 12:00:00", } ]; await mountView(calendarMountParams); expect(".o_event").toHaveCount(1); expect(".o_control_panel_navigation button i.fa-sliders").toHaveCount(1); await click(".o_control_panel_navigation button i.fa-sliders"); await waitFor("span.o-dropdown-item"); expect("span.o-dropdown-item").toHaveText("Show Sub-Tasks"); await click("span.o-dropdown-item"); await animationFrame(); expect(".o_event").toHaveCount(2); });