mirror of
https://github.com/bringout/oca-ocb-project.git
synced 2026-04-18 21:42:03 +02:00
Initial commit: Project packages
This commit is contained in:
commit
89613c97b0
753 changed files with 496325 additions and 0 deletions
|
|
@ -0,0 +1,232 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import { browser } from "@web/core/browser/browser";
|
||||
import { click, getFixture, patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
import { setupControlPanelServiceRegistry, toggleGroupByMenu, toggleMenuItem, toggleMenuItemOption } from "@web/../tests/search/helpers";
|
||||
import { makeView } from "@web/../tests/views/helpers";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { makeFakeNotificationService, fakeCookieService } from "@web/../tests/helpers/mock_services";
|
||||
import { getFirstElementForXpath } from './project_test_utils';
|
||||
|
||||
const serviceRegistry = registry.category("services");
|
||||
QUnit.module("Project", {}, () => {
|
||||
QUnit.module("Views", (hooks) => {
|
||||
let makeViewParams;
|
||||
let target;
|
||||
hooks.beforeEach(async (assert) => {
|
||||
target = getFixture();
|
||||
const serverData = {
|
||||
models: {
|
||||
burndown_chart: {
|
||||
fields: {
|
||||
date: { string: "Date", type: "date", store: true, sortable: true },
|
||||
project_id: { string: "Project", type: "many2one", relation: "project", store: true, sortable: true },
|
||||
stage_id: { string: "Stage", type: "many2one", relation: "stage", store: true, sortable: true },
|
||||
nb_tasks: { string: "Number of Tasks", type: "integer", store: true, sortable: true, group_operator: "sum" }
|
||||
},
|
||||
records: [
|
||||
{ id: 1, project_id: 1, stage_id: 1, date: "2020-01-01", nb_tasks: 10 },
|
||||
{ id: 2, project_id: 1, stage_id: 2, date: "2020-02-01", nb_tasks: 5 },
|
||||
{ id: 3, project_id: 1, stage_id: 3, date: "2020-03-01", nb_tasks: 2 },
|
||||
],
|
||||
},
|
||||
project: {
|
||||
fields: {
|
||||
name: { string: "Project Name", type: "char" },
|
||||
},
|
||||
records: [{ id: 1, name: "Project A" }]
|
||||
},
|
||||
stage: {
|
||||
fields: {
|
||||
name: { string: "Stage Name", type: "char" },
|
||||
},
|
||||
records: [
|
||||
{ id: 1, name: "Todo" },
|
||||
{ id: 2, name: "In Progress" },
|
||||
{ id: 3, name: "Done" },
|
||||
],
|
||||
}
|
||||
},
|
||||
views: {
|
||||
"burndown_chart,false,graph": `
|
||||
<graph type="line">
|
||||
<field name="date" string="Date" interval="month"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="nb_tasks" type="measure"/>
|
||||
</graph>
|
||||
`,
|
||||
"burndown_chart,false,search": `
|
||||
<search/>
|
||||
`,
|
||||
},
|
||||
};
|
||||
makeViewParams = {
|
||||
serverData,
|
||||
resModel: "burndown_chart",
|
||||
type: "burndown_chart",
|
||||
};
|
||||
setupControlPanelServiceRegistry();
|
||||
const notificationMock = () => {
|
||||
assert.step("notification_triggered");
|
||||
return () => {};
|
||||
};
|
||||
registry.category("services").add("notification", makeFakeNotificationService(notificationMock), {
|
||||
force: true,
|
||||
});
|
||||
serviceRegistry.add("cookie", fakeCookieService);
|
||||
});
|
||||
|
||||
QUnit.module("BurndownChart");
|
||||
|
||||
QUnit.test("check that the sort buttons are invisible", async function (assert) {
|
||||
await makeView(makeViewParams);
|
||||
assert.containsNone(target, '.o_cp_bottom_left:has(.btn-group[role=toolbar][aria-label="Sort graph"])', "The sort buttons are not rendered.");
|
||||
});
|
||||
|
||||
async function makeBurnDownChartWithSearchView(makeViewOverwriteParams = { }) {
|
||||
patchWithCleanup(browser, {
|
||||
setTimeout: (fn) => fn(),
|
||||
clearTimeout: () => {},
|
||||
});
|
||||
await makeView({
|
||||
...makeViewParams,
|
||||
searchViewId: false,
|
||||
searchViewArch: `
|
||||
<search string="Burndown Chart">
|
||||
<filter string="Date" name="date" context="{'group_by': 'date'}" />
|
||||
<filter string="Stage" name="stage" context="{'group_by': 'stage_id'}" />
|
||||
</search>
|
||||
`,
|
||||
searchViewFields: {
|
||||
date: {
|
||||
name: "date",
|
||||
string: "Date",
|
||||
type: "date",
|
||||
store: true,
|
||||
sortable: true,
|
||||
searchable: true,
|
||||
},
|
||||
stage_id: {
|
||||
name: "stage_id",
|
||||
string: "Stage",
|
||||
type: "many2one",
|
||||
store: true,
|
||||
sortable: true,
|
||||
searchable: true,
|
||||
},
|
||||
},
|
||||
context: { ...makeViewParams.context, 'search_default_date': 1, 'search_default_stage': 1 },
|
||||
...makeViewOverwriteParams,
|
||||
});
|
||||
}
|
||||
|
||||
async function testBurnDownChartWithSearchView(stepsTriggeringNotification, assert) {
|
||||
await makeBurnDownChartWithSearchView();
|
||||
await stepsTriggeringNotification();
|
||||
assert.verifySteps(['notification_triggered']);
|
||||
}
|
||||
|
||||
async function openGroupByMainMenu(target) {
|
||||
await toggleGroupByMenu(target);
|
||||
}
|
||||
|
||||
async function openGroupByDateMenu(target) {
|
||||
await openGroupByMainMenu(target);
|
||||
await toggleMenuItem(target, 'Date');
|
||||
}
|
||||
|
||||
async function toggleGroupByStageMenu(target) {
|
||||
await openGroupByMainMenu(target);
|
||||
await toggleMenuItem(target, 'Stage');
|
||||
}
|
||||
|
||||
async function toggleSelectedGroupByDateItem(target) {
|
||||
await openGroupByDateMenu(target);
|
||||
const selectedGroupByDateItemXpath = `//div
|
||||
[contains(@class, 'o_group_by_menu')]
|
||||
//button
|
||||
[contains(@class, 'o_menu_item')]
|
||||
[contains(., 'Date')]
|
||||
/following-sibling::div
|
||||
/span
|
||||
[contains(@class, 'o_item_option')]
|
||||
[contains(@class, 'selected')]`;
|
||||
const selectedGroupByDateItemElement = getFirstElementForXpath(target, selectedGroupByDateItemXpath);
|
||||
await toggleMenuItemOption(target, 'Date', selectedGroupByDateItemElement.innerText);
|
||||
}
|
||||
|
||||
QUnit.test("check that removing the group by 'Date: Month > Stage' in the search bar triggers a notification", async function (assert) {
|
||||
|
||||
const stepsTriggeringNotification = async () => {
|
||||
const removeFilterXpath = `//div[contains(@class, 'o_searchview_facet')]
|
||||
[.//span[@class='o_facet_value']
|
||||
[contains(., 'Date: Month')]]
|
||||
/i[contains(@class, 'o_facet_remove')]`;
|
||||
const removeFilterElement = getFirstElementForXpath(target, removeFilterXpath);
|
||||
await click(removeFilterElement);
|
||||
};
|
||||
await testBurnDownChartWithSearchView(stepsTriggeringNotification, assert);
|
||||
});
|
||||
|
||||
QUnit.test("check that removing the group by 'Date' triggers a notification", async function (assert) {
|
||||
const stepsTriggeringNotification = async () => {
|
||||
await toggleSelectedGroupByDateItem(target);
|
||||
};
|
||||
await testBurnDownChartWithSearchView(stepsTriggeringNotification, assert);
|
||||
});
|
||||
|
||||
QUnit.test("check that removing the group by 'Stage' triggers a notification", async function (assert) {
|
||||
const stepsTriggeringNotification = async () => {
|
||||
await toggleGroupByStageMenu(target);
|
||||
};
|
||||
await testBurnDownChartWithSearchView(stepsTriggeringNotification, assert);
|
||||
});
|
||||
|
||||
QUnit.test("check that adding a group by 'Date' actually toggle it", async function (assert) {
|
||||
await makeBurnDownChartWithSearchView();
|
||||
await openGroupByDateMenu(target);
|
||||
const firstNotSelectedGroupByDateItemXpath = `//div
|
||||
[contains(@class, 'o_group_by_menu')]
|
||||
//button
|
||||
[contains(@class, 'o_menu_item')]
|
||||
[contains(., 'Date')]
|
||||
/following-sibling::div
|
||||
/span
|
||||
[contains(@class, 'o_item_option')]
|
||||
[not(contains(@class, 'selected'))]`;
|
||||
const firstNotSelectedGroupByDateItemElement = getFirstElementForXpath(target, firstNotSelectedGroupByDateItemXpath);
|
||||
await toggleMenuItemOption(target, 'Date', firstNotSelectedGroupByDateItemElement.innerText);
|
||||
const groupByDateSubMenuXpath = `//div
|
||||
[contains(@class, 'o_group_by_menu')]
|
||||
//button
|
||||
[contains(@class, 'o_menu_item')]
|
||||
[contains(., 'Date')]
|
||||
/following-sibling::div`;
|
||||
const groupByDateSubMenuElement = getFirstElementForXpath(target, groupByDateSubMenuXpath);
|
||||
const selectedGroupByDateItemElements = groupByDateSubMenuElement.querySelectorAll('span.o_item_option.selected');
|
||||
assert.equal(selectedGroupByDateItemElements.length, 1, 'There is only one selected item.');
|
||||
assert.equal(firstNotSelectedGroupByDateItemElement.innerText, selectedGroupByDateItemElements[0].innerText, 'The selected item is the one we clicked on.');
|
||||
});
|
||||
|
||||
function checkGroupByOrder(assert) {
|
||||
const dateSearchFacetXpath = `//div[contains(@class, 'o_searchview_facet')]
|
||||
[.//span[@class='o_facet_value']
|
||||
[contains(., 'Date: Month')]]`;
|
||||
const dateSearchFacetElement = getFirstElementForXpath(target, dateSearchFacetXpath);
|
||||
const dateSearchFacetParts = dateSearchFacetElement.querySelectorAll('.o_facet_value');
|
||||
assert.equal(dateSearchFacetParts.length, 2);
|
||||
assert.equal(dateSearchFacetParts[0].innerText, 'Date: Month');
|
||||
assert.equal(dateSearchFacetParts[1].innerText, 'Stage');
|
||||
}
|
||||
|
||||
QUnit.test("check that the group by is always sorted 'Date' first, 'Stage' second", async function (assert) {
|
||||
await makeBurnDownChartWithSearchView({context: {...makeViewParams.context, 'search_default_date': 1, 'search_default_stage': 1}});
|
||||
checkGroupByOrder(assert);
|
||||
});
|
||||
|
||||
QUnit.test("check that the group by is always sorted 'Date' first, 'Stage' second", async function (assert) {
|
||||
await makeBurnDownChartWithSearchView({context: {...makeViewParams.context, 'search_default_stage': 1, 'search_default_date': 1}});
|
||||
checkGroupByOrder(assert);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { makeTestEnv } from "@web/../tests/helpers/mock_env";
|
||||
import {
|
||||
editInput,
|
||||
getFixture,
|
||||
mount,
|
||||
patchWithCleanup,
|
||||
} from "@web/../tests/helpers/utils";
|
||||
import { PortalFileInput } from "@project/project_sharing/components/portal_file_input/portal_file_input";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { session } from "@web/session";
|
||||
import { makeFakeLocalizationService } from "@web/../tests/helpers/mock_services";
|
||||
|
||||
const serviceRegistry = registry.category("services");
|
||||
|
||||
let target;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
async function createFileInput({ mockPost, mockAdd, props }) {
|
||||
serviceRegistry.add("notification", {
|
||||
start: () => ({
|
||||
add: mockAdd || (() => {}),
|
||||
}),
|
||||
});
|
||||
serviceRegistry.add("http", {
|
||||
start: () => ({
|
||||
post: mockPost || (() => {}),
|
||||
}),
|
||||
});
|
||||
const env = await makeTestEnv();
|
||||
await mount(PortalFileInput, target, { env, props });
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Tests
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
QUnit.module("Project", ({ beforeEach }) => {
|
||||
beforeEach(() => {
|
||||
patchWithCleanup(odoo, { csrf_token: "dummy" });
|
||||
|
||||
target = getFixture();
|
||||
});
|
||||
|
||||
QUnit.module("PortalComponents");
|
||||
|
||||
QUnit.test("uploading a file that is too heavy in portal will send a notification", async (assert) => {
|
||||
serviceRegistry.add("localization", makeFakeLocalizationService());
|
||||
patchWithCleanup(session, { max_file_upload_size: 2 });
|
||||
await createFileInput({
|
||||
props: {
|
||||
onUpload(files) {
|
||||
assert.deepEqual(files, [null]);
|
||||
},
|
||||
},
|
||||
mockAdd: (message) => {
|
||||
assert.step("notification");
|
||||
assert.strictEqual(
|
||||
message,
|
||||
"The selected file (4B) is over the maximum allowed file size (2B)."
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const file = new File(["test"], "fake_file.txt", { type: "text/plain" });
|
||||
await editInput(target, ".o_file_input input", file);
|
||||
assert.verifySteps(
|
||||
["notification"],
|
||||
"Only the notification will be triggered and the file won't be uploaded."
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import { getFixture } from "@web/../tests/helpers/utils";
|
||||
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
|
||||
|
||||
let makeViewParams, target;
|
||||
|
||||
QUnit.module("Project", (hooks) => {
|
||||
hooks.beforeEach(() => {
|
||||
makeViewParams = {
|
||||
type: "form",
|
||||
resModel: "project.project",
|
||||
serverData: {
|
||||
models: {
|
||||
"project.project": {
|
||||
fields: {
|
||||
id: { string: "Id", type: "integer" },
|
||||
},
|
||||
records: [{ id: 1, display_name: "First record" }],
|
||||
},
|
||||
},
|
||||
},
|
||||
arch: `<form js_class="project_form"><field name="display_name"/></form>`,
|
||||
};
|
||||
target = getFixture();
|
||||
setupViewRegistries();
|
||||
});
|
||||
QUnit.module("Form");
|
||||
QUnit.test("project form view", async function (assert) {
|
||||
await makeView(makeViewParams);
|
||||
assert.containsOnce(target, ".o_form_view");
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import { getFixture, click } from "@web/../tests/helpers/utils";
|
||||
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
|
||||
|
||||
let makeViewParams, target;
|
||||
|
||||
QUnit.module("Project", (hooks) => {
|
||||
hooks.beforeEach(() => {
|
||||
makeViewParams = {
|
||||
type: "kanban",
|
||||
resModel: "project.project",
|
||||
serverData: {
|
||||
models: {
|
||||
"project.project": {
|
||||
fields: {
|
||||
id: {string: "Id", type: "integer"},
|
||||
last_update_status: {
|
||||
string: "Status",
|
||||
type: "selection",
|
||||
selection: [
|
||||
["on_track", "On Track"],
|
||||
["at_risk", "At Risk"],
|
||||
["off_track", "Off Track"],
|
||||
["on_hold", "On Hold"],
|
||||
["to_define", "Set Status"],
|
||||
],
|
||||
},
|
||||
last_update_color: {
|
||||
string: "Update State Color",
|
||||
type: "integer",
|
||||
},
|
||||
},
|
||||
records: [
|
||||
{id: 1, last_update_status: "on_track", last_update_color: 20},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
arch: `
|
||||
<kanban class="o_kanban_test">
|
||||
<field name="last_update_status"/>
|
||||
<field name="last_update_color"/>
|
||||
<template>
|
||||
<t t-name="kanban-box">
|
||||
<div>
|
||||
<field name="last_update_status" widget="project_state_selection" options="{'color_field': 'last_update_color'}"/>
|
||||
</div>
|
||||
</t>
|
||||
</template>
|
||||
</kanban>`,
|
||||
};
|
||||
target = getFixture();
|
||||
setupViewRegistries();
|
||||
});
|
||||
QUnit.module("Components", (hooks) => {
|
||||
QUnit.module("ProjectStateSelectionField");
|
||||
QUnit.test("Check that ProjectStateSelectionField does not propose `Set Status`", async function (assert) {
|
||||
await makeView(makeViewParams);
|
||||
await click(target, 'div[name="last_update_status"] button.dropdown-toggle');
|
||||
assert.containsNone(target, 'div[name="last_update_status"] .dropdown-menu .dropdown-item:contains("Set Status")');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
/** @odoo-module */
|
||||
|
||||
export function getFirstElementForXpath(target, xpath) {
|
||||
const xPathResult = document.evaluate(xpath, target, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
|
||||
return xPathResult.singleNodeValue;
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import tour from 'web_tour.tour';
|
||||
|
||||
tour.register('personal_stage_tour', {
|
||||
test: true,
|
||||
url: '/web',
|
||||
},
|
||||
[tour.stepUtils.showAppsMenuItem(), {
|
||||
trigger: '.o_app[data-menu-xmlid="project.menu_main_pm"]',
|
||||
}, {
|
||||
content: "Open Pig Project",
|
||||
trigger: '.o_kanban_record:contains("Pig")',
|
||||
}, {
|
||||
// Default is grouped by stage, user should not be able to create/edit a column
|
||||
content: "Check that there is no create column",
|
||||
trigger: "body:not(.o_column_quick_create)",
|
||||
run: function () {},
|
||||
}, {
|
||||
content: "Check that there is no create column",
|
||||
trigger: "body:not(.o_column_edit)",
|
||||
run: function () {},
|
||||
}, {
|
||||
content: "Check that there is no create column",
|
||||
trigger: "body:not(.o_column_delete)",
|
||||
run: function () {},
|
||||
}, {
|
||||
content: "Go to my tasks", // My tasks is grouped by personal stage by default
|
||||
trigger: 'a[data-menu-xmlid="project.menu_project_management"]',
|
||||
}, {
|
||||
content: "Check that we can create a new stage",
|
||||
trigger: '.o_column_quick_create .o_quick_create_folded'
|
||||
}, {
|
||||
content: "Create a new personal stage",
|
||||
trigger: 'input.form-control.o_input',
|
||||
run: 'text Never',
|
||||
}, {
|
||||
content: "Confirm create",
|
||||
trigger: '.o_kanban_add',
|
||||
}, {
|
||||
content: "Check that column exists",
|
||||
trigger: '.o_kanban_header:contains("Never")',
|
||||
run: function () {},
|
||||
}, {
|
||||
content: 'Open column edit dropdown',
|
||||
trigger: '.o_kanban_header:eq(0)',
|
||||
run: function () {
|
||||
document.querySelector('.o_kanban_config.dropdown .dropdown-toggle').dispatchEvent(new Event('click'));
|
||||
},
|
||||
}, {
|
||||
content: "Try editing inbox",
|
||||
trigger: ".dropdown-item.o_column_edit",
|
||||
}, {
|
||||
content: "Change title",
|
||||
trigger: 'div.o_field_char[name="name"] input',
|
||||
run: 'text (Todo)',
|
||||
}, {
|
||||
content: "Save changes",
|
||||
trigger: '.btn-primary:contains("Save")',
|
||||
}, {
|
||||
content: "Check that column was updated",
|
||||
trigger: '.o_kanban_header:contains("Todo")',
|
||||
}]);
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import tour from 'web_tour.tour';
|
||||
|
||||
tour.register('burndown_chart_tour', {
|
||||
test: true,
|
||||
url: '/web',
|
||||
},
|
||||
[tour.stepUtils.showAppsMenuItem(), {
|
||||
trigger: '.o_app[data-menu-xmlid="project.menu_main_pm"]',
|
||||
}, {
|
||||
content: 'Open "Burndown Chart Test" project menu',
|
||||
trigger: '.o_kanban_record:contains("Burndown Chart Test") .o_kanban_manage_toggle_button',
|
||||
}, {
|
||||
content: `Open "Burndown Chart Test" project's "Burndown Chart" view`,
|
||||
trigger: '.o_kanban_record:contains("Burndown Chart Test") .o_kanban_manage_reporting div[role="menuitem"] a:contains("Burndown Chart")',
|
||||
}, {
|
||||
content: 'The sort buttons are not rendered',
|
||||
trigger: '.o_cp_bottom_left:not(:has(.btn-group[role=toolbar][aria-label="Sort graph"]))',
|
||||
extra_trigger: '.o_graph_renderer',
|
||||
}, {
|
||||
content: 'Remove the project search "Burndown Chart Test"',
|
||||
trigger: '.o_searchview_facet:contains("Burndown Chart Test") .o_facet_remove',
|
||||
}, {
|
||||
content: 'Search Burndown Chart',
|
||||
trigger: 'input.o_searchview_input',
|
||||
run: `text Burndown`,
|
||||
}, {
|
||||
content: 'Validate search',
|
||||
trigger: '.o_searchview_autocomplete .o_menu_item:contains("Project")',
|
||||
}, {
|
||||
content: 'Remove the group by "Date: Month > Stage"',
|
||||
trigger: '.o_searchview_facet:contains("Date: Month") .o_facet_remove',
|
||||
}, {
|
||||
content: 'A "The Burndown Chart must be grouped by Date and Stage" notification is shown when trying to remove the group by "Date: Month > Stage"',
|
||||
trigger: '.o_notification_manager .o_notification:contains("The Burndown Chart must be grouped by Date and Stage") button.o_notification_close',
|
||||
}, {
|
||||
content: 'Open the group by menu',
|
||||
trigger: '.o_group_by_menu button',
|
||||
}, {
|
||||
content: 'The Stage group menu item is invisible',
|
||||
trigger: '.o_group_by_menu:not(:has(.o_menu_item:contains("Stage")))',
|
||||
}, {
|
||||
content: 'Open the Date group by sub menu',
|
||||
trigger: '.o_group_by_menu button.o_menu_item:contains("Date")',
|
||||
run: function () {
|
||||
this.$anchor[0].dispatchEvent(new Event('mouseenter'));
|
||||
},
|
||||
}, {
|
||||
content: 'Click on the selected Date sub menu',
|
||||
trigger: '.o_group_by_menu button.o_menu_item:contains("Date") + * .dropdown-item.selected',
|
||||
run: function () {
|
||||
this.$anchor[0].dispatchEvent(new Event('click'));
|
||||
},
|
||||
}, {
|
||||
content: 'A "The Burndown Chart must be grouped by Date" notification is shown when trying to remove the group by "Date: Month > Stage"',
|
||||
trigger: '.o_notification_manager .o_notification:contains("The Burndown Chart must be grouped by Date") button.o_notification_close',
|
||||
}, {
|
||||
content: 'Open the filter menu',
|
||||
trigger: '.o_filter_menu button',
|
||||
}, {
|
||||
content: 'Open the Date filter sub menu',
|
||||
trigger: '.o_filter_menu button.o_menu_item:contains("Date")',
|
||||
run: function () {
|
||||
this.$anchor[0].dispatchEvent(new Event('mouseenter'));
|
||||
},
|
||||
}, {
|
||||
content: 'Click on the first Date filter sub menu',
|
||||
trigger: '.o_filter_menu .o_menu_item:contains("Date") + * .dropdown-item:first-child',
|
||||
run: function () {
|
||||
this.$anchor[0].dispatchEvent(new Event('click'));
|
||||
},
|
||||
}, {
|
||||
content: 'Close the Date filter menu',
|
||||
trigger: '.o_graph_renderer',
|
||||
}, {
|
||||
content: 'The comparison menu is not rendered',
|
||||
trigger: '.o_search_options:not(:has(.o_comparison_menu))',
|
||||
}]);
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import tour from 'web_tour.tour';
|
||||
|
||||
const projectSharingSteps = [...tour.stepUtils.goToAppSteps("project.menu_main_pm", 'Go to the Project App.'), {
|
||||
trigger: '.oe_kanban_global_click :contains("Project Sharing") button.o_dropdown_kanban',
|
||||
content: 'Open the project dropdown.'
|
||||
}, {
|
||||
trigger: '.o_kanban_record:contains("Project Sharing") .dropdown-menu a:contains("Share")',
|
||||
content: 'Start editing the project.',
|
||||
}, {
|
||||
trigger: 'div.o_field_radio[name="access_mode"] div.o_radio_item > input[data-value="edit"]',
|
||||
content: 'Select "Edit" as Access mode in the "Share Project" wizard.',
|
||||
}, {
|
||||
trigger: '.o_field_many2many_tags_email[name=partner_ids]',
|
||||
content: 'Select the user portal as collaborator to the "Project Sharing" project.',
|
||||
run: function (actions) {
|
||||
actions.text('Georges', this.$anchor.find('input'));
|
||||
},
|
||||
}, {
|
||||
trigger: '.ui-autocomplete a.dropdown-item:contains("Georges")',
|
||||
in_modal: false,
|
||||
}, {
|
||||
trigger: 'footer > button[name="action_send_mail"]',
|
||||
content: 'Confirm the project sharing with this portal user.',
|
||||
}, {
|
||||
trigger: '.o_web_client',
|
||||
content: 'Go to project portal view to select the "Project Sharing" project',
|
||||
run: function () {
|
||||
window.location.href = window.location.origin + '/my/projects';
|
||||
},
|
||||
}, {
|
||||
id: 'project_sharing_feature',
|
||||
trigger: 'table > tbody > tr a:has(span:contains(Project Sharing))',
|
||||
content: 'Select "Project Sharing" project to go to project sharing feature for this project.',
|
||||
}, {
|
||||
trigger: '.o_project_sharing',
|
||||
content: 'Wait the project sharing feature be loaded',
|
||||
run: function () {},
|
||||
}, {
|
||||
trigger: 'button.o-kanban-button-new',
|
||||
content: 'Click "Create" button',
|
||||
run: 'click',
|
||||
}, {
|
||||
trigger: '.o_kanban_quick_create .o_field_widget[name="name"] input',
|
||||
content: 'Create Task',
|
||||
run: 'text Test Create Task',
|
||||
}, {
|
||||
trigger: '.o_kanban_quick_create .o_kanban_edit',
|
||||
content: 'Go to the form view of this new task',
|
||||
}, {
|
||||
trigger: 'div[name="stage_id"] div.o_statusbar_status button[aria-checked="false"]:contains(Done)',
|
||||
content: 'Change the stage of the task.',
|
||||
}, {
|
||||
trigger: '.o_portal_chatter_composer_input .o_portal_chatter_composer_body textarea',
|
||||
content: 'Write a message in the chatter of the task',
|
||||
run: 'text I create a new task for testing purpose.',
|
||||
}, {
|
||||
trigger: '.o_portal_chatter_composer_input .o_portal_chatter_composer_body button[name="send_message"]',
|
||||
content: 'Send the message',
|
||||
}, {
|
||||
trigger: 'ol.breadcrumb > li.o_back_button > a:contains(Project Sharing)',
|
||||
content: 'Go back to the kanban view',
|
||||
}, {
|
||||
trigger: '.o_filter_menu > button',
|
||||
content: 'click on filter menu in the search view',
|
||||
}, {
|
||||
trigger: '.o_filter_menu > .dropdown-menu > .dropdown-item:first-child',
|
||||
content: 'click on the first item in the filter menu',
|
||||
}, {
|
||||
trigger: '.o_group_by_menu > button',
|
||||
content: 'click on group by menu in the search view',
|
||||
}, {
|
||||
trigger: '.o_group_by_menu > .dropdown-menu > .dropdown-item:first-child',
|
||||
content: 'click on the first item in the group by menu',
|
||||
}, {
|
||||
trigger: '.o_favorite_menu > button',
|
||||
content: 'click on the favorite menu in the search view',
|
||||
}, {
|
||||
trigger: '.o_favorite_menu .o_add_favorite > button',
|
||||
content: 'click to "save current search" button in favorite menu',
|
||||
}, {
|
||||
trigger: '.o_filter_menu > button',
|
||||
content: 'click on filter menu in the search view',
|
||||
}, {
|
||||
trigger: '.o_filter_menu > .dropdown-menu > .dropdown-item:first-child',
|
||||
content: 'click on the first item in the filter menu',
|
||||
}, {
|
||||
trigger: '.o_group_by_menu > button',
|
||||
content: 'click on group by menu in the search view',
|
||||
}, {
|
||||
trigger: '.o_group_by_menu > .dropdown-menu > .dropdown-item:first-child',
|
||||
content: 'click on the first item in the group by menu',
|
||||
}, {
|
||||
trigger: '.o_favorite_menu > button',
|
||||
content: 'click on the favorite menu in the search view',
|
||||
}, {
|
||||
trigger: '.o_favorite_menu .o_add_favorite > button',
|
||||
content: 'click to "save current search" button in favorite menu',
|
||||
}, {
|
||||
trigger: 'button.o_switch_view.o_list',
|
||||
content: 'Go to the list view',
|
||||
}];
|
||||
|
||||
tour.register('project_sharing_tour', {
|
||||
test: true,
|
||||
url: '/web',
|
||||
}, projectSharingSteps);
|
||||
|
||||
// The begining of the project sharing feature
|
||||
const projectSharingStepIndex = projectSharingSteps.findIndex(s => s.id && s.id === 'project_sharing_feature');
|
||||
tour.register('portal_project_sharing_tour', {
|
||||
test: true,
|
||||
url: '/my/projects',
|
||||
}, projectSharingSteps.slice(projectSharingStepIndex, projectSharingSteps.length));
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import tour from 'web_tour.tour';
|
||||
|
||||
function changeFilter(filterName) {
|
||||
return [
|
||||
{
|
||||
trigger: '.o_favorite_menu button:has(i.fa-star)',
|
||||
content: 'click on the favorite menu',
|
||||
},
|
||||
{
|
||||
trigger: `.o_favorite_menu .dropdown-item span:contains("${filterName}")`,
|
||||
},
|
||||
{
|
||||
trigger: '.o_group_by_menu button:has(i.oi-group)',
|
||||
content: 'click on the groupby menu',
|
||||
run: function (actions) {
|
||||
this.$anchor[0].dispatchEvent(new Event('mouseenter'));
|
||||
},
|
||||
},
|
||||
{
|
||||
trigger: '.o_group_by_menu span:contains("Stage")',
|
||||
content: 'click on the stage gb',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
tour.register('project_tags_filter_tour',
|
||||
{
|
||||
test: true,
|
||||
url: '/web',
|
||||
},
|
||||
[
|
||||
tour.stepUtils.showAppsMenuItem(),
|
||||
{
|
||||
trigger: '.o_app[data-menu-xmlid="project.menu_main_pm"]',
|
||||
}, ...changeFilter("Corkscrew tail tag filter"),
|
||||
{
|
||||
trigger: '.o_kanban_group:has(.o_kanban_header:has(span:contains("pig"))) .o_kanban_record:has(span:contains("Pigs"))',
|
||||
extra_trigger: '.o_kanban_group:has(.o_kanban_header:has(span:contains("goat"))):not(:has(.o_kanban_record))',
|
||||
content: 'check that the corkscrew tail filter has taken effect',
|
||||
run: () => {},
|
||||
}, ...changeFilter("horned tag filter"),
|
||||
{
|
||||
trigger: '.o_kanban_group:has(.o_kanban_header:has(span:contains("goat"))) .o_kanban_record:has(span:contains("Goats"))',
|
||||
extra_trigger: '.o_kanban_group:has(.o_kanban_header:has(span:contains("pig"))):not(:has(.o_kanban_record))',
|
||||
content: 'check that the horned filter has taken effect',
|
||||
run: () => {},
|
||||
}, ...changeFilter("4 Legged tag filter"),
|
||||
{
|
||||
trigger: '.o_kanban_group:has(.o_kanban_header:has(span:contains("goat"))) .o_kanban_record:has(span:contains("Goats"))',
|
||||
extra_trigger: '.o_kanban_group:has(.o_kanban_header:has(span:contains("pig"))) .o_kanban_record:has(span:contains("Pigs"))',
|
||||
content: 'check that the 4 legged filter has taken effect',
|
||||
run: () => {},
|
||||
},
|
||||
]);
|
||||
|
|
@ -0,0 +1,180 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import tour from 'web_tour.tour';
|
||||
|
||||
function openProjectUpdateAndReturnToTasks(view, viewClass) {
|
||||
const legacyViewClass = viewClass.replace("o_", "o_legacy_");
|
||||
return [{
|
||||
trigger: '.o_project_updates_breadcrumb',
|
||||
content: 'Open Project Update from view : ' + view,
|
||||
extra_trigger: `.${viewClass}, .${legacyViewClass}`,
|
||||
}, {
|
||||
trigger: ".o-kanban-button-new",
|
||||
content: "Create a new update from project task view : " + view,
|
||||
extra_trigger: '.o_pupdate_kanban',
|
||||
}, {
|
||||
trigger: "button.o_form_button_cancel",
|
||||
content: "Discard project update from project task view : " + view,
|
||||
}, {
|
||||
trigger: ".o_switch_view.o_list",
|
||||
content: "Go to list of project update from view " + view,
|
||||
}, {
|
||||
trigger: '.o_back_button',
|
||||
content: 'Go back to the task view : ' + view,
|
||||
// extra_trigger: '.o_list_view, .o_legacy_list_view', // FIXME: [XBO] uncomment it when the sample data will be displayed after discarding the creation of a project update record.
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
tour.register('project_update_tour', {
|
||||
test: true,
|
||||
url: '/web',
|
||||
},
|
||||
[tour.stepUtils.showAppsMenuItem(), {
|
||||
trigger: '.o_app[data-menu-xmlid="project.menu_main_pm"]',
|
||||
}, {
|
||||
trigger: '.o-kanban-button-new',
|
||||
extra_trigger: '.o_project_kanban',
|
||||
width: 200,
|
||||
}, {
|
||||
trigger: '.o_project_name input',
|
||||
run: 'text New Project'
|
||||
}, {
|
||||
trigger: '.o_open_tasks',
|
||||
run: function (actions) {
|
||||
actions.auto('.modal:visible .btn.btn-primary');
|
||||
},
|
||||
}, {
|
||||
trigger: ".o_kanban_project_tasks .o_column_quick_create .input-group",
|
||||
run: function (actions) {
|
||||
actions.text("New", this.$anchor.find("input"));
|
||||
},
|
||||
}, {
|
||||
trigger: ".o_kanban_project_tasks .o_column_quick_create .o_kanban_add",
|
||||
auto: true,
|
||||
}, {
|
||||
trigger: ".o_kanban_project_tasks .o_column_quick_create .input-group",
|
||||
extra_trigger: '.o_kanban_group',
|
||||
run: function (actions) {
|
||||
actions.text("Done", this.$anchor.find("input"));
|
||||
},
|
||||
}, {
|
||||
trigger: ".o_kanban_project_tasks .o_column_quick_create .o_kanban_add",
|
||||
auto: true,
|
||||
}, {
|
||||
trigger: '.o-kanban-button-new',
|
||||
extra_trigger: '.o_kanban_group:eq(0)'
|
||||
}, {
|
||||
trigger: '.o_kanban_quick_create div.o_field_char[name=name] input',
|
||||
extra_trigger: '.o_kanban_project_tasks',
|
||||
run: 'text New task'
|
||||
}, {
|
||||
trigger: '.o_kanban_quick_create .o_kanban_add',
|
||||
extra_trigger: '.o_kanban_project_tasks'
|
||||
}, {
|
||||
trigger: '.o-kanban-button-new',
|
||||
extra_trigger: '.o_kanban_group:eq(0)'
|
||||
}, {
|
||||
trigger: '.o_kanban_quick_create div.o_field_char[name=name] input',
|
||||
extra_trigger: '.o_kanban_project_tasks',
|
||||
run: 'text Second task'
|
||||
}, {
|
||||
trigger: '.o_kanban_quick_create .o_kanban_add',
|
||||
extra_trigger: '.o_kanban_project_tasks'
|
||||
}, {
|
||||
trigger: '.o_kanban_group:nth-child(2) .o_kanban_header',
|
||||
run: function () {
|
||||
document.querySelector('.o_kanban_group:nth-child(2) .o_kanban_config.dropdown .dropdown-toggle').dispatchEvent(new Event('click'));
|
||||
}
|
||||
}, {
|
||||
trigger: ".dropdown-item.o_column_edit",
|
||||
}, {
|
||||
trigger: ".o_field_widget[name=fold] input",
|
||||
}, {
|
||||
trigger: ".modal-footer button",
|
||||
}, {
|
||||
trigger: ".o_kanban_record .oe_kanban_content",
|
||||
extra_trigger: '.o_kanban_project_tasks',
|
||||
run: "drag_and_drop .o_kanban_group:eq(1) ",
|
||||
}, {
|
||||
trigger: ".o_project_updates_breadcrumb",
|
||||
content: 'Open Updates'
|
||||
}, {
|
||||
trigger: ".o_add_milestone a",
|
||||
content: "Add a first milestone"
|
||||
}, {
|
||||
trigger: "div.o_field_widget[name=name] input",
|
||||
run: 'text New milestone'
|
||||
}, {
|
||||
trigger: "div[name=deadline] .datetimepicker-input",
|
||||
run: 'text 12/12/2099'
|
||||
}, {
|
||||
trigger: ".modal-footer .o_form_button_save"
|
||||
}, {
|
||||
trigger: ".o_add_milestone a",
|
||||
}, {
|
||||
trigger: "div.o_field_widget[name=name] input",
|
||||
run: 'text Second milestone'
|
||||
}, {
|
||||
trigger: "div[name=deadline] .datetimepicker-input",
|
||||
run: 'text 12/12/2022'
|
||||
}, {
|
||||
trigger: ".modal-footer .o_form_button_save"
|
||||
}, {
|
||||
trigger: ".o_rightpanel_milestone:eq(1) .o_milestone_detail",
|
||||
}, {
|
||||
trigger: "div[name=deadline] .datetimepicker-input",
|
||||
run: 'text 12/12/2100'
|
||||
}, {
|
||||
trigger: ".modal-footer .o_form_button_save"
|
||||
}, {
|
||||
trigger: ".o-kanban-button-new",
|
||||
content: "Create a new update"
|
||||
}, {
|
||||
trigger: "div.o_field_widget[name=name] input",
|
||||
run: 'text New update'
|
||||
}, {
|
||||
trigger: ".o_form_button_save"
|
||||
}, {
|
||||
trigger: ".o_field_widget[name='description'] h1:contains('Activities')",
|
||||
run: function () {},
|
||||
}, {
|
||||
trigger: ".o_field_widget[name='description'] h3:contains('Milestones')",
|
||||
run: function () {},
|
||||
}, {
|
||||
trigger: ".o_field_widget[name='description'] div[name='milestone'] ul li:contains('(12/12/2099 => 12/12/2100)')",
|
||||
run: function () {},
|
||||
}, {
|
||||
trigger: ".o_field_widget[name='description'] div[name='milestone'] ul li:contains('(due 12/12/2022)')",
|
||||
run: function () {},
|
||||
}, {
|
||||
trigger: ".o_field_widget[name='description'] div[name='milestone'] ul li:contains('(due 12/12/2100)')",
|
||||
run: function () {},
|
||||
}, {
|
||||
trigger: '.o_back_button',
|
||||
content: 'Go back to the kanban view the project',
|
||||
}, {
|
||||
trigger: '.o_switch_view.o_list',
|
||||
content: 'Open List View of Project Updates',
|
||||
}, {
|
||||
trigger: '.o_back_button',
|
||||
content: 'Go back to the kanban view the project',
|
||||
extra_trigger: '.o_list_view, .o_legacy_list_view',
|
||||
}, {
|
||||
trigger: '.o_switch_view.o_graph',
|
||||
content: 'Open Graph View of Tasks',
|
||||
}, ...openProjectUpdateAndReturnToTasks("Graph", "o_graph_view"), {
|
||||
trigger: '.o_switch_view.o_list',
|
||||
content: 'Open List View of Tasks',
|
||||
extra_trigger: '.o_graph_view',
|
||||
}, ...openProjectUpdateAndReturnToTasks("List", "o_list_view"), {
|
||||
trigger: '.o_switch_view.o_pivot',
|
||||
content: 'Open Pivot View of Tasks',
|
||||
}, ...openProjectUpdateAndReturnToTasks("Pivot", "o_pivot_view"), {
|
||||
trigger: '.o_switch_view.o_calendar',
|
||||
content: 'Open Calendar View of Tasks',
|
||||
}, ...openProjectUpdateAndReturnToTasks("Calendar", "o_calendar_view"), {
|
||||
trigger: '.o_switch_view.o_activity',
|
||||
content: 'Open Activity View of Tasks',
|
||||
}, ...openProjectUpdateAndReturnToTasks("Activity", "o_activity_view"),
|
||||
]);
|
||||
Loading…
Add table
Add a link
Reference in a new issue