386 lines
17 KiB
JavaScript
386 lines
17 KiB
JavaScript
import { contains, defineModels, mountView, onRpc, serverState } from "@web/../tests/web_test_helpers";
|
|
import { omit } from "@web/core/utils/objects";
|
|
|
|
import { describe, expect, test } from "@odoo/hoot";
|
|
import { waitFor, waitForNone } from "@odoo/hoot-dom";
|
|
import { animationFrame } from "@odoo/hoot-mock";
|
|
|
|
import {
|
|
DocumentsModels,
|
|
getDocumentsTestServerModelsData,
|
|
makeDocumentRecordData,
|
|
} from "@documents/../tests/helpers/data";
|
|
import { makeDocumentsMockEnv } from "@documents/../tests/helpers/model";
|
|
import {
|
|
basicDocumentsKanbanArch,
|
|
mountDocumentsKanbanView,
|
|
} from "@documents/../tests/helpers/views/kanban";
|
|
import { getEnrichedSearchArch } from "@documents/../tests/helpers/views/search";
|
|
|
|
const archWithTags = basicDocumentsKanbanArch.replace(
|
|
'<field name="name"/>',
|
|
/* xml */ `
|
|
<field name="name"/>
|
|
<field name="tag_ids" class="d-block text-wrap" widget="many2many_tags" options="{'color_field': 'color'}"/>
|
|
<field name="alias_domain_id"/>
|
|
<field name="alias_name"/>
|
|
<field name="alias_tag_ids" class="d-block text-wrap" widget="many2many_tags" options="{'color_field': 'color'}"/>
|
|
<field name="create_activity_type_id"/>
|
|
<field name="mail_alias_domain_count"/>
|
|
`
|
|
);
|
|
|
|
/**
|
|
* Shortcut for details panel selector
|
|
* @param selector
|
|
* @return {string} `selector` prefixed with `".o_documents_details_panel "`.
|
|
*/
|
|
const dp = (selector) => `.o_documents_details_panel ${selector}`;
|
|
|
|
const binaryTestedValues = { tag_ids: [1, 2], owner_id: serverState.userId };
|
|
const folderTestedValues = {
|
|
alias_id: 1,
|
|
alias_domain_id: 1,
|
|
alias_name: "alias",
|
|
alias_tag_ids: [1, 2],
|
|
mail_alias_domain_count: 2,
|
|
owner_id: serverState.userId,
|
|
type: "folder",
|
|
create_activity_type_id: 1,
|
|
};
|
|
|
|
describe.current.tags("desktop");
|
|
|
|
defineModels(DocumentsModels);
|
|
|
|
onRpc("ir.model", "display_name_for", ({ args }) =>
|
|
args[0].map((model) => ({ model, display_name: model }))
|
|
);
|
|
onRpc("/documents/touch/<access_token>", () => ({}));
|
|
|
|
test("Details panel rendering for editors", async () => {
|
|
const serverData = getDocumentsTestServerModelsData([
|
|
makeDocumentRecordData(2, "Testing tags", { folder_id: 1, ...binaryTestedValues }),
|
|
makeDocumentRecordData(3, "Testing container", { folder_id: 1, ...folderTestedValues }),
|
|
]);
|
|
await makeDocumentsMockEnv({ serverData });
|
|
await mountDocumentsKanbanView({ arch: archWithTags });
|
|
await contains(".o_kanban_record:contains('Testing tags')").click();
|
|
await contains(".o_control_panel_navigation .fa-info-circle").click();
|
|
await animationFrame();
|
|
expect(dp(".o_documents_details_panel_name input")).toHaveCount(1);
|
|
expect(dp(".o_documents_details_panel_name input")).toHaveValue("Testing tags");
|
|
expect(dp(".o_field_tags input")).toHaveCount(1);
|
|
await contains(dp(".o_field_tags span:contains('Colorless') a")).click();
|
|
await waitForNone(dp(".o_field_tags span:contains('Colorless')"));
|
|
await contains(dp(".o_field_tags span:contains('Colorful') a")).click();
|
|
expect(dp(".o_field_tags input[placeholder='Add tags...']")).toHaveCount(1);
|
|
expect(dp("input[placeholder='No owner']")).toHaveValue("Mitchell Admin");
|
|
|
|
await contains(".o_kanban_record:contains('Testing container')").click();
|
|
expect(dp(".o_documents_details_panel_name input")).toHaveCount(1);
|
|
expect(dp(".o_documents_details_panel_name input")).toHaveValue("Testing container");
|
|
expect(dp("input[placeholder='No activity']")).toHaveValue("Email");
|
|
expect(dp("input[placeholder='Activity assigned to']")).toHaveCount(1);
|
|
|
|
await contains(dp(".o_field_tags span:contains('Colorless') a")).click();
|
|
await waitForNone(dp(".o_field_tags span:contains('Colorless')"));
|
|
await contains(dp(".o_field_tags span:contains('Colorful') a")).click();
|
|
await waitForNone(dp(".o_field_tags span:contains('Colorful')"));
|
|
await waitFor(dp(".o_field_tags input[placeholder='Add an alias tag...']"));
|
|
});
|
|
|
|
test("Details panel rendering for viewers - m2o/m2m values", async () => {
|
|
const serverData = getDocumentsTestServerModelsData([
|
|
makeDocumentRecordData(2, "Testing tags", {
|
|
folder_id: 1,
|
|
...binaryTestedValues,
|
|
user_permission: "view",
|
|
}),
|
|
makeDocumentRecordData(3, "Testing container", {
|
|
folder_id: 1,
|
|
...folderTestedValues,
|
|
user_permission: "view",
|
|
}),
|
|
]);
|
|
await makeDocumentsMockEnv({ serverData });
|
|
await mountDocumentsKanbanView({ arch: archWithTags });
|
|
await contains(".o_kanban_record:contains('Testing tags')").click();
|
|
await contains(".o_control_panel_navigation .fa-info-circle").click();
|
|
await animationFrame();
|
|
|
|
await waitFor(dp(".o_documents_details_panel_name span:contains('Testing Tags')"));
|
|
expect(dp(".o_documents_details_panel_name input")).toHaveCount(0);
|
|
expect(dp(".o_field_tags span:contains('Colorless')")).toHaveCount(1);
|
|
expect(dp(".o_field_tags span:contains('Colorful')")).toHaveCount(1);
|
|
expect(dp("span:contains('Mitchell Admin')")).toHaveCount(1);
|
|
|
|
await contains(".o_kanban_record:contains('Testing container')").click();
|
|
await waitFor(dp(".o_documents_details_panel_name span:contains('Testing Container')"));
|
|
expect(dp(".o_field_tags input")).toHaveCount(0);
|
|
expect(dp(".o_field_tags span:contains('Colorless')")).toHaveCount(1);
|
|
expect(dp(".o_field_tags span:contains('Colorful')")).toHaveCount(1);
|
|
expect(dp("div:contains('alias@odoo.com')")).toHaveCount(3); // nested wrappers
|
|
expect(dp("span:contains('Email')")).toHaveCount(1); // activity type
|
|
expect(dp("span:contains('No activity assignee')")).toHaveCount(1); // activity type
|
|
});
|
|
|
|
test("Details panel rendering for viewers - m2o/m2m pseudo-placeholders", async () => {
|
|
const serverData = getDocumentsTestServerModelsData([
|
|
makeDocumentRecordData(2, "Testing tags", { folder_id: 1, user_permission: "view" }),
|
|
makeDocumentRecordData(3, "Testing container", {
|
|
folder_id: 1,
|
|
...omit(folderTestedValues, "alias_tag_ids"),
|
|
user_permission: "view",
|
|
}),
|
|
]);
|
|
await makeDocumentsMockEnv({ serverData });
|
|
await mountDocumentsKanbanView({ arch: archWithTags });
|
|
await contains(".o_kanban_record:contains('Testing tags')").click();
|
|
await contains(".o_control_panel_navigation .fa-info-circle").click();
|
|
await animationFrame();
|
|
|
|
await waitFor(dp(".o_documents_details_panel_name span:contains('Testing Tags')"));
|
|
expect(dp(".o_field_tags span.o_documents_details_panel_placeholder")).toHaveText("No tags");
|
|
await waitFor(dp("span.o_documents_details_panel_placeholder:contains('No owner')"));
|
|
|
|
await contains(".o_kanban_record:contains('Testing container')").click();
|
|
await waitFor(dp(".o_documents_details_panel_name span:contains('Testing Container')"));
|
|
await waitFor(dp("div:contains('alias@odoo.com')"));
|
|
await waitFor(dp("span:contains('No activity')"));
|
|
expect(dp(".o_field_tags span.o_documents_details_panel_placeholder")).toHaveText(
|
|
"No alias tags"
|
|
);
|
|
});
|
|
|
|
test("Details panel required document name", async () => {
|
|
const serverData = getDocumentsTestServerModelsData([
|
|
makeDocumentRecordData(2, "Testing file", { folder_id: 1 }),
|
|
makeDocumentRecordData(3, "Testing folder", { folder_id: 1 }),
|
|
]);
|
|
await makeDocumentsMockEnv({ serverData });
|
|
await mountDocumentsKanbanView({ arch: archWithTags });
|
|
await contains(".o_control_panel_navigation .fa-info-circle").click();
|
|
for (const documentName of [
|
|
"Folder 1", // Container
|
|
"Testing folder",
|
|
"Testing file",
|
|
]) {
|
|
await contains(`.o_kanban_record:contains('${documentName}')`).click();
|
|
await animationFrame();
|
|
expect(dp(".o_documents_details_panel_name input")).toHaveCount(1);
|
|
expect(dp(".o_documents_details_panel_name input")).toHaveValue(documentName);
|
|
// Set empty name
|
|
await contains(".o_documents_details_panel_name input").edit("");
|
|
await animationFrame();
|
|
expect(".o_notification").toHaveCount(1);
|
|
expect(".o_notification").toHaveText("Name cannot be empty.");
|
|
await contains(".o_notification .o_notification_close").click();
|
|
expect(dp(".o_documents_details_panel_name input")).toHaveValue(documentName);
|
|
}
|
|
});
|
|
|
|
test("Details panel root folder placeholders", async () => {
|
|
const serverData = getDocumentsTestServerModelsData([
|
|
makeDocumentRecordData(2, "In COMPANY (readonly)", { user_permission: "view" }),
|
|
makeDocumentRecordData(3, "In MY DRIVE", { owner_id: serverState.userId }),
|
|
makeDocumentRecordData(4, "In SHARED WITH ME", { owner_id: serverState.odoobotId }),
|
|
makeDocumentRecordData(5, "In COMPANY"),
|
|
]);
|
|
await makeDocumentsMockEnv({ serverData });
|
|
await mountDocumentsKanbanView({ arch: archWithTags });
|
|
await contains(".o_control_panel_navigation .fa-info-circle").click();
|
|
// Edit mode
|
|
for (const [documentName, rootPlaceholder] of [
|
|
["In COMPANY", "Company"],
|
|
["In MY DRIVE", "My Drive"],
|
|
["In SHARED WITH ME", "Shared with me"],
|
|
]) {
|
|
await contains(`.o_kanban_record:contains('${documentName}')`).click();
|
|
await animationFrame();
|
|
expect(dp(".o_documents_details_panel_name input")).toHaveCount(1);
|
|
expect(dp(".o_documents_details_panel_name input")).toHaveValue(documentName);
|
|
expect(dp(".fa-folder + .o_field_many2one input")).toHaveAttribute(
|
|
"placeholder",
|
|
rootPlaceholder,
|
|
{ message: "Document should have correct root folder placeholder (editors)." }
|
|
);
|
|
}
|
|
// Readonly mode
|
|
await contains(".o_kanban_record:contains('In COMPANY (readonly)')").click();
|
|
await animationFrame();
|
|
expect(dp(".o_documents_details_panel_name span")).toHaveCount(1);
|
|
expect(dp(".o_documents_details_panel_name span")).toHaveText("In COMPANY (readonly)");
|
|
expect(dp(".fa-folder + .o_field_many2one .o_documents_details_panel_placeholder")).toHaveText(
|
|
"Company",
|
|
{ message: "Document should have correct root folder placeholder (viewers)." }
|
|
);
|
|
});
|
|
|
|
test("Details panel should be updated when clearing a selection", async function () {
|
|
const serverData = getDocumentsTestServerModelsData([
|
|
makeDocumentRecordData(2, "Test file", { folder_id: 1 }),
|
|
]);
|
|
await makeDocumentsMockEnv({ serverData });
|
|
await mountDocumentsKanbanView({ arch: archWithTags });
|
|
await contains(".o_control_panel_navigation .fa-info-circle").click();
|
|
for (const documentName of ["Folder 1", "Test file"]) {
|
|
await contains(`.o_kanban_record:contains('${documentName}')`).click();
|
|
await animationFrame();
|
|
expect(dp(".o_documents_details_panel_name input")).toHaveCount(1);
|
|
expect(dp(".o_documents_details_panel_name input")).toHaveValue(documentName);
|
|
}
|
|
// Clearing a selection.
|
|
await contains(".o_unselect_all").click();
|
|
expect(dp(".o_documents_details_panel_name input")).toHaveCount(1);
|
|
expect(dp(".o_documents_details_panel_name input")).toHaveValue("Folder 1");
|
|
});
|
|
|
|
test("Details panel changes to folders are immediately saved and visible in the app", async function () {
|
|
await makeDocumentsMockEnv({ serverData: getDocumentsTestServerModelsData() });
|
|
await mountDocumentsKanbanView({ arch: archWithTags });
|
|
await contains(".o_control_panel_navigation .fa-info-circle").click();
|
|
await contains(
|
|
"li.o_search_panel_category_value:contains('COMPANY') button.o_toggle_fold"
|
|
).click();
|
|
let counter = 0;
|
|
onRpc("search_panel_select_range", () => {
|
|
counter++;
|
|
});
|
|
|
|
const renameTwice = async (from) => {
|
|
expect(dp(".o_documents_details_panel_name input")).toHaveCount(1);
|
|
expect(dp(".o_documents_details_panel_name input")).toHaveValue("Folder 1");
|
|
expect("span.o_search_panel_label_title:contains('Folder 1')").toHaveCount(1);
|
|
await contains(dp(".o_documents_details_panel_name input")).edit(
|
|
`Folder Renamed from ${from}`
|
|
);
|
|
await animationFrame();
|
|
expect(dp(".o_documents_details_panel_name input")).toHaveValue(
|
|
`Folder Renamed from ${from}`
|
|
);
|
|
expect(
|
|
`span.o_search_panel_label_title:contains('Folder Renamed from ${from}')`
|
|
).toHaveCount(1);
|
|
await contains(dp(".o_documents_details_panel_name input")).edit("Folder 1");
|
|
await animationFrame();
|
|
expect(dp(".o_documents_details_panel_name input")).toHaveValue("Folder 1");
|
|
expect("span.o_search_panel_label_title:contains('Folder 1')").toHaveCount(1);
|
|
};
|
|
|
|
// From container Record
|
|
await contains(`.o_kanban_record:contains('Folder 1')`).click({ ctrlKey: true });
|
|
await animationFrame();
|
|
await renameTwice("container");
|
|
expect(counter).toBe(2);
|
|
|
|
// From KanbanRecord
|
|
await contains(`.o_kanban_record:contains('Folder 1')`).click();
|
|
await animationFrame();
|
|
await renameTwice("kanban record");
|
|
expect(counter).toBe(4);
|
|
});
|
|
|
|
test("All models should be displayed in the details panel", async function () {
|
|
const serverData = getDocumentsTestServerModelsData([
|
|
makeDocumentRecordData(2, "Test Request", { folder_id: 1 }),
|
|
]);
|
|
await makeDocumentsMockEnv({ serverData });
|
|
await mountDocumentsKanbanView({ arch: archWithTags });
|
|
await contains(".o_kanban_record:contains('Test Request')").click();
|
|
await contains(".o_control_panel_navigation .fa-info-circle").click();
|
|
await animationFrame();
|
|
|
|
await contains(dp("input[placeholder='No linked model']")).click();
|
|
await animationFrame();
|
|
expect(dp("div ul li")).toHaveCount(9);
|
|
expect(dp("div ul li:contains('Start typing...')")).toHaveCount(0);
|
|
});
|
|
|
|
test("Details panel rendering", async function () {
|
|
const serverData = getDocumentsTestServerModelsData([
|
|
makeDocumentRecordData(2, "Testing container", {
|
|
folder_id: 1,
|
|
...folderTestedValues,
|
|
user_permission: "edit",
|
|
}),
|
|
]);
|
|
await makeDocumentsMockEnv({ serverData });
|
|
await mountView({
|
|
type: "list",
|
|
resModel: "documents.document",
|
|
arch: `<list js_class="documents_list">
|
|
<field name="active"/>
|
|
<field name="id"/>
|
|
</list>`,
|
|
searchViewArch: getEnrichedSearchArch(),
|
|
});
|
|
await contains(`.o_data_row td[name="id"]:contains(2)`).click();
|
|
await contains(".o_control_panel_navigation .fa-info-circle").click();
|
|
expect(dp(".o_documents_details_panel_name input")).toHaveValue("Testing container");
|
|
expect(dp(".fa-envelope + div .o_field_char input")).toHaveValue("alias");
|
|
});
|
|
|
|
test("Add from document from log a note", async () => {
|
|
onRpc("ir.model", "display_name_for", ({ args }) =>
|
|
args[0].map((model) => ({ model, display_name: model }))
|
|
);
|
|
onRpc("documents.document", "add_documents_attachment", ({ args }) => {
|
|
expect(args).toEqual([[12], "mail.compose.message", 0]);
|
|
expect.step("add_documents_attachment");
|
|
return [
|
|
{
|
|
id: 1002,
|
|
name: "File 2",
|
|
type: "binary",
|
|
res_id: 0,
|
|
res_model: "mail.compose.message",
|
|
mimetype: "text/plain",
|
|
public: false,
|
|
original_id: [12, "File 2"],
|
|
},
|
|
];
|
|
});
|
|
const serverData = getDocumentsTestServerModelsData([
|
|
makeDocumentRecordData(2, "Folder 2", { type: "folder" }),
|
|
makeDocumentRecordData(11, "File 1", {
|
|
attachment_id: 101,
|
|
user_folder_id: "1",
|
|
type: "binary",
|
|
}),
|
|
makeDocumentRecordData(12, "File 2", {
|
|
attachment_id: 102,
|
|
user_folder_id: "2",
|
|
type: "binary",
|
|
}),
|
|
]);
|
|
serverData["ir.attachment"] = [
|
|
{ id: 101, name: "File 1", mimetype: "text/plain" },
|
|
{ id: 102, name: "File 2", mimetype: "text/plain" },
|
|
];
|
|
await makeDocumentsMockEnv({ serverData });
|
|
await mountDocumentsKanbanView({ arch: archWithTags });
|
|
|
|
await contains(".o_kanban_record:contains('File 1')").click();
|
|
await contains(".o_control_panel_navigation .fa-info-circle").click();
|
|
await waitFor(".o_document_chatter_container button.o-mail-Chatter-logNote:not(:disabled)");
|
|
|
|
await contains(".o_document_chatter_container button.o-mail-Chatter-logNote").click();
|
|
await contains(".o_document_chatter_container button[title='Add from Documents']").click();
|
|
await contains(
|
|
".o_select_create_dialog_content .o_search_panel_label_title:contains('Company')"
|
|
).click();
|
|
await contains(
|
|
".o_select_create_dialog_content .o_search_panel_label_title:contains('Folder 2')"
|
|
).click();
|
|
// As defining a list view interferes with the view behind the modal, we select "File 2" as only child of Folder 2.
|
|
await contains(".o_select_create_dialog_content .o_data_row .o-checkbox input").click();
|
|
await contains(".o_select_create_dialog_content button:contains('Add from Documents')").click();
|
|
|
|
// The attachment has been added in the composer.
|
|
expect(".o-mail-Composer .o-mail-Attachment-hoverImageText:contains('File 2')").toHaveCount(1);
|
|
// But the attachment is not linked to the thread.
|
|
expect(".o-mail-Chatter-topbar .o-mail-Chatter-attachFiles:contains('1')").toHaveCount(0);
|
|
await expect.waitForSteps(["add_documents_attachment"]);
|
|
});
|