435 lines
16 KiB
JavaScript
435 lines
16 KiB
JavaScript
import {
|
|
defineDocumentSpreadsheetModels,
|
|
getDocumentBasicData,
|
|
} from "@documents_spreadsheet/../tests/helpers/data";
|
|
import { getEnrichedSearchArch } from "@documents/../tests/helpers/views/search";
|
|
import { mockActionService } from "@documents_spreadsheet/../tests/helpers/spreadsheet_test_utils";
|
|
import { describe, expect, test } from "@odoo/hoot";
|
|
import { click, dblclick, queryFirst, select, press } from "@odoo/hoot-dom";
|
|
import { animationFrame } from "@odoo/hoot-mock";
|
|
import { makeDocumentsSpreadsheetMockEnv } from "@documents_spreadsheet/../tests/helpers/model";
|
|
import { contains, mountView } from "@web/../tests/web_test_helpers";
|
|
|
|
describe.current.tags("desktop");
|
|
defineDocumentSpreadsheetModels();
|
|
|
|
const kanbanArch = /* xml */ `
|
|
<kanban js_class="documents_kanban">
|
|
<templates>
|
|
<field name="id"/>
|
|
<field name="available_embedded_actions_ids"/>
|
|
<field name="access_token"/>
|
|
<field name="mimetype"/>
|
|
<field name="folder_id"/>
|
|
<field name="owner_id"/>
|
|
<field name="active"/>
|
|
<field name="type"/>
|
|
<field name="attachment_id"/>
|
|
<t t-name="card">
|
|
<div><field name="name"/></div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`;
|
|
|
|
const TEST_TEMPLATES = [
|
|
{ id: 3, name: "Template 3", spreadsheet_data: "{}" },
|
|
{ id: 4, name: "Template 4", spreadsheet_data: "{}" },
|
|
{ id: 5, name: "Template 5", spreadsheet_data: "{}" },
|
|
{ id: 6, name: "Template 6", spreadsheet_data: "{}" },
|
|
{ id: 7, name: "Template 7", spreadsheet_data: "{}" },
|
|
{ id: 8, name: "Template 8", spreadsheet_data: "{}" },
|
|
{ id: 9, name: "Template 9", spreadsheet_data: "{}" },
|
|
{ id: 10, name: "Template 10", spreadsheet_data: "{}" },
|
|
{ id: 11, name: "Template 11", spreadsheet_data: "{}" },
|
|
{ id: 12, name: "Template 12", spreadsheet_data: "{}" },
|
|
];
|
|
|
|
/**
|
|
* @typedef InitArgs
|
|
* @property {Object} [serverData]
|
|
* @property {Array} [additionalTemplates]
|
|
* @property {Function} [mockRPC]
|
|
*/
|
|
|
|
/**
|
|
* @param {InitArgs} args
|
|
*/
|
|
async function initTestEnvWithKanban(args = {}) {
|
|
const data = args.serverData || getDocumentBasicData({});
|
|
data.models["spreadsheet.template"].records = data.models[
|
|
"spreadsheet.template"
|
|
].records.concat(args.additionalTemplates || []);
|
|
await makeDocumentsSpreadsheetMockEnv({ ...args, serverData: data });
|
|
return mountView({
|
|
type: "kanban",
|
|
resModel: "documents.document",
|
|
arch: kanbanArch,
|
|
searchViewArch: getEnrichedSearchArch(),
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @param {InitArgs} params
|
|
*/
|
|
async function initTestEnvWithBlankSpreadsheet(params = {}) {
|
|
const serverData = getDocumentBasicData();
|
|
serverData.models["documents.document"] = {
|
|
records: [
|
|
{
|
|
name: "Folder 1",
|
|
description: "Folder",
|
|
type: "folder",
|
|
id: 1,
|
|
available_embedded_actions_ids: [],
|
|
},
|
|
],
|
|
};
|
|
serverData.models["documents.document"] = {
|
|
record: [
|
|
{
|
|
name: "My spreadsheet",
|
|
spreadsheet_data: "{}",
|
|
is_favorited: false,
|
|
folder_id: 1,
|
|
handler: "spreadsheet",
|
|
},
|
|
],
|
|
};
|
|
return initTestEnvWithKanban({ serverData, ...params });
|
|
}
|
|
|
|
async function openTemplateDialog() {
|
|
await contains(`.o_control_panel_main_buttons .dropdown-toggle`).click();
|
|
await contains(`.o-dropdown--menu .dropdown-item.o_documents_kanban_spreadsheet`).click();
|
|
}
|
|
|
|
const dialogSelector = ".o-spreadsheet-templates-dialog";
|
|
|
|
test("Create spreadsheet from kanban view opens a modal", async function () {
|
|
await initTestEnvWithKanban();
|
|
await openTemplateDialog();
|
|
|
|
expect(".o-spreadsheet-templates-dialog").toHaveCount(1, {
|
|
message: "should have opened the template modal",
|
|
});
|
|
expect(".o-spreadsheet-templates-dialog .modal-body .o_searchview").toHaveCount(1, {
|
|
message: "The Modal should have a search view",
|
|
});
|
|
});
|
|
|
|
test("Create spreadsheet from list view opens a modal", async function () {
|
|
const serverData = getDocumentBasicData();
|
|
await makeDocumentsSpreadsheetMockEnv({ serverData });
|
|
await mountView({
|
|
resModel: "documents.document",
|
|
type: "list",
|
|
arch: `<list js_class="documents_list"></list>`,
|
|
searchViewArch: getEnrichedSearchArch(),
|
|
});
|
|
await openTemplateDialog();
|
|
|
|
expect(".o-spreadsheet-templates-dialog").toHaveCount(1, {
|
|
message: "should have opened the template modal",
|
|
});
|
|
expect(".o-spreadsheet-templates-dialog .modal-body .o_searchview").toHaveCount(1, {
|
|
message: "The Modal should have a search view",
|
|
});
|
|
});
|
|
|
|
test("Can search template in modal with searchbar", async function () {
|
|
await initTestEnvWithKanban();
|
|
await openTemplateDialog();
|
|
|
|
expect(`${dialogSelector} .o-spreadsheet-grid:not(.o-spreadsheet-grid-ghost-item)`).toHaveCount(
|
|
3
|
|
);
|
|
expect(`${dialogSelector} .o-spreadsheet-grid:first`).toHaveText("Blank spreadsheet");
|
|
|
|
await contains(`${dialogSelector} .o_searchview_input`).edit("Template 1");
|
|
await press("Enter");
|
|
await animationFrame();
|
|
expect(`${dialogSelector} .o-spreadsheet-grid:not(.o-spreadsheet-grid-ghost-item)`).toHaveCount(
|
|
2
|
|
);
|
|
expect(`${dialogSelector} .o-spreadsheet-grid:first`).toHaveText("Blank spreadsheet");
|
|
});
|
|
|
|
test("Can fetch next templates", async function () {
|
|
let fetch = 0;
|
|
const mockRPC = async function (route, args) {
|
|
if (args.method === "web_search_read" && args.model === "spreadsheet.template") {
|
|
fetch++;
|
|
expect(args.kwargs.limit).toBe(9);
|
|
expect.step("fetch_templates");
|
|
if (fetch === 1) {
|
|
expect(args.kwargs.offset).toBe(0);
|
|
} else if (fetch === 2) {
|
|
expect(args.kwargs.offset).toBe(9);
|
|
}
|
|
}
|
|
if (args.method === "search_read" && args.model === "ir.model") {
|
|
return [{ name: "partner" }];
|
|
}
|
|
};
|
|
await initTestEnvWithKanban({ additionalTemplates: TEST_TEMPLATES, mockRPC });
|
|
await openTemplateDialog();
|
|
|
|
expect(`${dialogSelector} .o-spreadsheet-grid:not(.o-spreadsheet-grid-ghost-item)`).toHaveCount(
|
|
10
|
|
);
|
|
await contains(`${dialogSelector} .o_pager_next`).click();
|
|
expect.verifySteps(["fetch_templates", "fetch_templates"]);
|
|
});
|
|
|
|
test("Can create a blank spreadsheet without access to the template model", async function () {
|
|
const mockRPC = async function (route, args) {
|
|
if (args.model === "spreadsheet.template" && args.method === "has_access") {
|
|
return false;
|
|
}
|
|
};
|
|
await initTestEnvWithKanban({ additionalTemplates: TEST_TEMPLATES, mockRPC });
|
|
await openTemplateDialog();
|
|
|
|
expect(`${dialogSelector} .o-spreadsheet-grid:not(.o-spreadsheet-grid-ghost-item)`).toHaveCount(
|
|
1
|
|
);
|
|
});
|
|
|
|
test("Disable create button if no template is selected", async function () {
|
|
await initTestEnvWithKanban({ additionalTemplates: TEST_TEMPLATES });
|
|
await openTemplateDialog();
|
|
|
|
// select template
|
|
await click(`${dialogSelector} .o-spreadsheet-grid-image:eq(1)`);
|
|
|
|
// change page; no template should be selected
|
|
await contains(`${dialogSelector} .o_pager_next`).click();
|
|
expect(".o-spreadsheet-grid-selected").toHaveCount(0);
|
|
expect(`${dialogSelector} .o-spreadsheet-create`).toHaveAttribute("disabled");
|
|
});
|
|
|
|
test("Can create a blank spreadsheet from template dialog", async function () {
|
|
const mockDoAction = (action) => {
|
|
expect.step("redirect");
|
|
expect(action.tag).toBe("action_open_spreadsheet");
|
|
};
|
|
await initTestEnvWithBlankSpreadsheet({
|
|
mockRPC: async function (route, args) {
|
|
if (
|
|
args.model === "documents.document" &&
|
|
args.method === "action_open_new_spreadsheet"
|
|
) {
|
|
expect(args.args[0].folder_id).toBe(false);
|
|
expect.step("action_open_new_spreadsheet");
|
|
}
|
|
},
|
|
});
|
|
mockActionService(mockDoAction);
|
|
|
|
// ### With confirm button
|
|
await openTemplateDialog();
|
|
|
|
// select blank spreadsheet
|
|
await click(`${dialogSelector} .o-spreadsheet-grid-image`);
|
|
await contains(`${dialogSelector} .o-spreadsheet-create`).click();
|
|
expect.verifySteps(["action_open_new_spreadsheet", "redirect"]);
|
|
|
|
// ### With double click on image
|
|
await openTemplateDialog();
|
|
|
|
await click(`${dialogSelector} .o-spreadsheet-grid-image`);
|
|
await dblclick(`${dialogSelector} .o-spreadsheet-grid-image`);
|
|
await animationFrame();
|
|
expect.verifySteps(["action_open_new_spreadsheet", "redirect"]);
|
|
});
|
|
|
|
test("Context is transmitted when creating spreadsheet", async function () {
|
|
const serverData = await getDocumentBasicData({
|
|
"documents.document,false,kanban": `
|
|
<kanban js_class="documents_kanban">
|
|
<field name="available_embedded_actions_ids"/>
|
|
<field name="access_token"/>
|
|
<field name="id"/>
|
|
<field name="mimetype"/>
|
|
<field name="folder_id"/>
|
|
<field name="active"/>
|
|
<field name="type"/>
|
|
<field name="attachment_id"/>
|
|
<templates>
|
|
<t t-name="card">
|
|
<field name="name"/>
|
|
</t>
|
|
</templates>
|
|
</kanban>
|
|
`,
|
|
"documents.document,false,search": getEnrichedSearchArch(),
|
|
});
|
|
await makeDocumentsSpreadsheetMockEnv({
|
|
mockRPC: async function (route, args) {
|
|
if (args.method === "action_open_new_spreadsheet") {
|
|
expect.step("action_open_new_spreadsheet");
|
|
expect(args.kwargs.context.default_res_id).toBe(42);
|
|
expect(args.kwargs.context.default_res_model).toBe("test.model");
|
|
}
|
|
},
|
|
serverData,
|
|
});
|
|
await mountView({
|
|
context: {
|
|
default_res_model: "test.model",
|
|
default_res_id: 42,
|
|
},
|
|
resModel: "documents.document",
|
|
type: "kanban",
|
|
searchViewArch: getEnrichedSearchArch(),
|
|
arch: kanbanArch,
|
|
});
|
|
|
|
await openTemplateDialog();
|
|
|
|
// select blank spreadsheet
|
|
await click(`${dialogSelector} .o-spreadsheet-grid-image`);
|
|
await contains(`${dialogSelector} .o-spreadsheet-create`).click();
|
|
expect.verifySteps(["action_open_new_spreadsheet"]);
|
|
});
|
|
|
|
test("Can create a spreadsheet from a template", async function () {
|
|
const mockDoAction = (action) => {
|
|
expect.step("redirect");
|
|
expect(action.tag).toBe("an_action");
|
|
};
|
|
await initTestEnvWithKanban({
|
|
additionalTemplates: TEST_TEMPLATES,
|
|
mockRPC: async function (route, args) {
|
|
if (
|
|
args.model === "spreadsheet.template" &&
|
|
args.method === "action_create_spreadsheet"
|
|
) {
|
|
expect.step("action_create_spreadsheet");
|
|
expect(args.args[1].folder_id).toBe(false);
|
|
const action = {
|
|
type: "ir.actions.client",
|
|
tag: "an_action",
|
|
};
|
|
return action;
|
|
}
|
|
},
|
|
});
|
|
mockActionService(mockDoAction);
|
|
|
|
// ### With confirm button
|
|
await openTemplateDialog();
|
|
|
|
await click(`${dialogSelector} .o-spreadsheet-grid-image:eq(1)`);
|
|
await contains(`${dialogSelector} .o-spreadsheet-create`).click();
|
|
expect.verifySteps(["action_create_spreadsheet", "redirect"]);
|
|
|
|
// ### With double click on image
|
|
await openTemplateDialog();
|
|
await click(`${dialogSelector} .o-spreadsheet-grid-image:eq(1)`);
|
|
await dblclick(`${dialogSelector} .o-spreadsheet-grid-image:eq(1)`);
|
|
await animationFrame();
|
|
expect.verifySteps(["action_create_spreadsheet", "redirect"]);
|
|
});
|
|
|
|
test("The folder selection should not display Trash folder", async function () {
|
|
await initTestEnvWithKanban();
|
|
await openTemplateDialog();
|
|
|
|
expect(
|
|
".o-spreadsheet-templates-dialog .o-spreadsheet-grid-item-name:contains(TRASH)"
|
|
).toHaveCount(0, {
|
|
message: "Trash folder should not be present in the selection",
|
|
});
|
|
});
|
|
|
|
test("Offset reset to zero after searching for template in template dialog", async function () {
|
|
const mockRPC = async function (route, args) {
|
|
if (args.method === "web_search_read" && args.model === "spreadsheet.template") {
|
|
expect.step(
|
|
JSON.stringify({
|
|
offset: args.kwargs.offset,
|
|
limit: args.kwargs.limit,
|
|
})
|
|
);
|
|
}
|
|
};
|
|
|
|
await initTestEnvWithKanban({ additionalTemplates: TEST_TEMPLATES, mockRPC });
|
|
await openTemplateDialog();
|
|
|
|
expect(`${dialogSelector} .o-spreadsheet-grid:not(.o-spreadsheet-grid-ghost-item)`).toHaveCount(
|
|
10
|
|
);
|
|
await contains(`${dialogSelector} .o_pager_next`).click();
|
|
expect.verifySteps([
|
|
JSON.stringify({ offset: 0, limit: 9 }),
|
|
JSON.stringify({ offset: 9, limit: 9 }),
|
|
]);
|
|
|
|
await contains(`${dialogSelector} .o_searchview_input`).edit("Template 1");
|
|
await press("Enter");
|
|
await animationFrame();
|
|
await animationFrame();
|
|
|
|
expect(`${dialogSelector} .o-spreadsheet-grid:not(.o-spreadsheet-grid-ghost-item)`).toHaveCount(
|
|
5
|
|
); // Blank template, Template 1, Template 10, Template 11, Template 12
|
|
expect.verifySteps([JSON.stringify({ offset: 0, limit: 9 })]);
|
|
expect(`${dialogSelector} .o_pager_value `).toHaveText("1-4", {
|
|
message: "Pager should be reset to 1-4 after searching for a template",
|
|
});
|
|
});
|
|
|
|
test("Can navigate through templates with keyboard", async function () {
|
|
await initTestEnvWithKanban({ additionalTemplates: TEST_TEMPLATES });
|
|
await openTemplateDialog();
|
|
|
|
const defaultTemplate = queryFirst(
|
|
`${dialogSelector} .o-spreadsheet-grid.o-blank-spreadsheet-grid .o-spreadsheet-grid-image`
|
|
);
|
|
expect(defaultTemplate).toHaveClass("o-spreadsheet-grid-selected");
|
|
|
|
// Navigate to the next template
|
|
await contains(defaultTemplate).press("ArrowRight");
|
|
expect(defaultTemplate).not.toHaveClass("o-spreadsheet-grid-selected");
|
|
|
|
const firstTemplate = queryFirst(`${dialogSelector} .o-spreadsheet-grid-image[data-id='1']`);
|
|
expect(firstTemplate).toHaveClass("o-spreadsheet-grid-selected");
|
|
|
|
// Navigate back to the previous template
|
|
await contains(defaultTemplate).press("ArrowLeft");
|
|
expect(firstTemplate).not.toHaveClass("o-spreadsheet-grid-selected");
|
|
expect(defaultTemplate).toHaveClass("o-spreadsheet-grid-selected");
|
|
});
|
|
|
|
test("Can create a blank spreadsheet from template dialog in a specific folder", async function () {
|
|
const mockDoAction = (action) => {
|
|
expect.step("redirect");
|
|
expect(action.tag).toBe("action_open_spreadsheet");
|
|
};
|
|
await initTestEnvWithBlankSpreadsheet({
|
|
mockRPC: async function (route, args) {
|
|
if (
|
|
args.model === "documents.document" &&
|
|
args.method === "action_open_new_spreadsheet"
|
|
) {
|
|
expect(args.args[0].folder_id).toBe(1);
|
|
expect.step("action_open_new_spreadsheet");
|
|
}
|
|
},
|
|
});
|
|
mockActionService(mockDoAction);
|
|
|
|
await contains(".o_search_panel_section").click();
|
|
|
|
await openTemplateDialog();
|
|
|
|
await select("1", { target: ".o-spreadsheet-templates-dialog select" });
|
|
|
|
await contains(`${dialogSelector} .o-spreadsheet-grid-image`).click();
|
|
await contains(`${dialogSelector} .o-spreadsheet-create`).click();
|
|
|
|
expect.verifySteps(["action_open_new_spreadsheet", "redirect"]);
|
|
});
|