/* @odoo-module */
import { startServer } from "@bus/../tests/helpers/mock_python_environment";
import { documentService } from "@documents/core/document_service";
import { getEnrichedSearchArch } from "@documents/../tests/documents_test_utils";
import { start } from "@mail/../tests/helpers/test_utils";
import {
editInput,
triggerEvent,
getFixture,
click,
patchWithCleanup,
nextTick,
} from "@web/../tests/helpers/utils";
import { getBasicData } from "@spreadsheet/../tests/utils/data";
import { mockActionService } from "@documents_spreadsheet/../tests/spreadsheet_test_utils";
import { companyService } from "@web/webclient/company_service";
import { session } from "@web/session";
import { setupViewRegistries } from "@web/../tests/views/helpers";
import { registry } from "@web/core/registry";
import { fileUploadService } from "@web/core/file_upload/file_upload_service";
import { makeFakeSpreadsheetService } from "@spreadsheet_edition/../tests/utils/collaborative_helpers";
const serviceRegistry = registry.category("services");
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: "{}" },
];
async function getDocumentBasicData(views = {}) {
const pyEnv = await startServer();
const documentsFolderId1 = pyEnv["documents.folder"].create({
name: "Workspace1",
description: "Workspace",
has_write_access: true,
});
const mailAliasId1 = pyEnv["mail.alias"].create({ alias_name: "hazard@rmcf.es" });
pyEnv["documents.share"].create({
name: "Share1",
folder_id: documentsFolderId1,
alias_id: mailAliasId1,
});
pyEnv["spreadsheet.template"].create([
{ name: "Template 1", spreadsheet_data: "{}" },
{ name: "Template 2", spreadsheet_data: "{}" },
]);
return {
models: {
...getBasicData(),
...pyEnv.getData(),
},
views,
};
}
/**
* @typedef InitArgs
* @property {Object} serverData
* @property {Array} additionalTemplates
* @property {Function} mockRPC
*/
/**
* @param {InitArgs} args
*/
async function initTestEnvWithKanban(args = {}) {
const data =
args.serverData ||
(await getDocumentBasicData({
"spreadsheet.template,false,search": ``,
}));
data.models["spreadsheet.template"].records = data.models[
"spreadsheet.template"
].records.concat(args.additionalTemplates || []);
Object.assign(data.views, {
"documents.document,false,kanban": `
`,
"documents.document,false,search": getEnrichedSearchArch(),
});
const res = await start({
mockRPC: args.mockRPC || (() => {}),
serverData: data,
});
const { openView } = res;
await openView({
res_model: "documents.document",
views: [[false, "kanban"]],
});
return res;
}
/**
* @param {InitArgs} args
*/
async function initTestEnvWithBlankSpreadsheet(params = {}) {
const pyEnv = await startServer();
const documentsFolderId1 = pyEnv["documents.folder"].create({ has_write_access: true });
pyEnv["documents.document"].create({
name: "My spreadsheet",
spreadsheet_data: "{}",
is_favorited: false,
folder_id: documentsFolderId1,
handler: "spreadsheet",
});
const serverData = {
models: pyEnv.getData(),
views: {
"spreadsheet.template,false,search": ``,
},
};
return await initTestEnvWithKanban({ serverData, ...params });
}
let target;
QUnit.module(
"documents_spreadsheet > create spreadsheet from template modal",
{
beforeEach() {
setupViewRegistries();
target = getFixture();
serviceRegistry.add("document.document", documentService);
serviceRegistry.add("file_upload", fileUploadService);
serviceRegistry.add("documents_pdf_thumbnail", {
start() {
return {
enqueueRecords: () => {},
};
},
});
patchWithCleanup(session.user_companies.allowed_companies[1], {
documents_spreadsheet_folder_id: 1,
});
serviceRegistry.add("company", companyService, { force: true });
},
},
() => {
QUnit.test("Create spreadsheet from kanban view opens a modal", async function (assert) {
await initTestEnvWithKanban();
const menu = target.querySelector(".o_control_panel .d-xl-inline-flex .btn-group");
await click(menu, ".dropdown-toggle");
await click(menu, ".o_documents_kanban_spreadsheet");
assert.containsOnce(
target,
".o-spreadsheet-templates-dialog",
"should have opened the template modal"
);
assert.containsOnce(
target,
".o-spreadsheet-templates-dialog .modal-body .o_searchview",
"The Modal should have a search view"
);
});
QUnit.test("Create spreadsheet from list view opens a modal", async function (assert) {
const serverData = await getDocumentBasicData({
"documents.document,false,list": ``,
"documents.document,false,search": getEnrichedSearchArch(),
});
const { openView } = await start({ serverData });
await openView({
res_model: "documents.document",
views: [[false, "list"]],
});
const menu = target.querySelector(".o_control_panel .d-xl-inline-flex .btn-group");
await click(menu, ".dropdown-toggle");
await click(menu, ".o_documents_kanban_spreadsheet");
assert.containsOnce(
target,
".o-spreadsheet-templates-dialog",
"should have opened the template modal"
);
assert.containsOnce(
target,
".o-spreadsheet-templates-dialog .modal-body .o_searchview",
"The Modal should have a search view"
);
});
QUnit.test("Can search template in modal with searchbar", async function (assert) {
await initTestEnvWithKanban();
const menu = target.querySelector(".o_control_panel .d-xl-inline-flex .btn-group");
await click(menu, ".dropdown-toggle");
await click(menu, ".o_documents_kanban_spreadsheet");
const dialog = target.querySelector(".o-spreadsheet-templates-dialog");
assert.equal(
dialog.querySelectorAll(".o-template:not(.o-template-ghost-item)").length,
3
);
assert.equal(dialog.querySelector(".o-template").textContent, "Blank spreadsheet");
const searchInput = dialog.querySelector(".o_searchview_input");
await editInput(searchInput, null, "Template 1");
await triggerEvent(searchInput, null, "keydown", { key: "Enter" });
assert.equal(
dialog.querySelectorAll(".o-template:not(.o-template-ghost-item)").length,
2
);
assert.equal(dialog.querySelector(".o-template").textContent, "Blank spreadsheet");
});
QUnit.test("Can fetch next templates", async function (assert) {
let fetch = 0;
const mockRPC = async function (route, args) {
if (args.method === "web_search_read" && args.model === "spreadsheet.template") {
fetch++;
assert.equal(args.kwargs.limit, 9);
assert.step("fetch_templates");
if (fetch === 1) {
assert.equal(args.kwargs.offset, 0);
} else if (fetch === 2) {
assert.equal(args.kwargs.offset, 9);
}
}
if (args.method === "search_read" && args.model === "ir.model") {
return [{ name: "partner" }];
}
};
await initTestEnvWithKanban({ additionalTemplates: TEST_TEMPLATES, mockRPC });
const menu = target.querySelector(".o_control_panel .d-xl-inline-flex .btn-group");
await click(menu, ".dropdown-toggle");
await click(menu, ".o_documents_kanban_spreadsheet");
const dialog = document.querySelector(".o-spreadsheet-templates-dialog");
assert.equal(
dialog.querySelectorAll(".o-template:not(.o-template-ghost-item)").length,
10
);
await click(dialog.querySelector(".o_pager_next"));
assert.verifySteps(["fetch_templates", "fetch_templates"]);
});
QUnit.test("Disable create button if no template is selected", async function (assert) {
assert.expect(2);
await initTestEnvWithKanban({ additionalTemplates: TEST_TEMPLATES });
// open template dialog
const menu = target.querySelector(".o_control_panel .d-xl-inline-flex .btn-group");
await click(menu, ".dropdown-toggle");
await click(menu, ".o_documents_kanban_spreadsheet");
const dialog = document.querySelector(".o-spreadsheet-templates-dialog");
// select template
await triggerEvent(dialog.querySelectorAll(".o-template-image")[1], null, "focus");
// change page; no template should be selected
await click(dialog.querySelector(".o_pager_next"));
assert.containsNone(dialog, ".o-template-selected");
const createButton = dialog.querySelector(".o-spreadsheet-create");
assert.ok(createButton.attributes.disabled);
});
QUnit.test("Can create a blank spreadsheet from template dialog", async function (assert) {
const mockDoAction = (action) => {
assert.step("redirect");
assert.equal(action.tag, "action_open_spreadsheet");
};
const { env } = await initTestEnvWithBlankSpreadsheet({
mockRPC: async function (route, args) {
if (
args.model === "documents.document" &&
args.method === "action_open_new_spreadsheet"
) {
assert.strictEqual(args.args[0].folder_id, 1);
assert.step("action_open_new_spreadsheet");
}
},
});
mockActionService(env, mockDoAction);
// ### With confirm button
const menu = target.querySelector(".o_control_panel .d-xl-inline-flex .btn-group");
await click(menu, ".dropdown-toggle");
await click(menu, ".o_documents_kanban_spreadsheet");
let dialog = document.querySelector(".o-spreadsheet-templates-dialog");
// select blank spreadsheet
await triggerEvent(dialog.querySelectorAll(".o-template-image")[0], null, "focus");
await click(dialog.querySelector(".o-spreadsheet-create"));
assert.verifySteps(["action_open_new_spreadsheet", "redirect"]);
// ### With double click on image
await click(menu, ".dropdown-toggle");
await click(menu, ".o_documents_kanban_spreadsheet");
dialog = document.querySelector(".o-spreadsheet-templates-dialog");
await triggerEvent(dialog.querySelectorAll(".o-template-image")[0], null, "focus");
await triggerEvent(dialog.querySelectorAll(".o-template-image")[0], null, "dblclick");
assert.verifySteps(["action_open_new_spreadsheet", "redirect"]);
// ### With enter key
await click(menu, ".o_documents_kanban_spreadsheet");
dialog = document.querySelector(".o-spreadsheet-templates-dialog");
await triggerEvent(dialog.querySelectorAll(".o-template-image")[0], null, "focus");
await triggerEvent(dialog.querySelectorAll(".o-template-image")[0], null, "keydown", {
key: "Enter",
});
assert.verifySteps(["action_open_new_spreadsheet", "redirect"]);
});
QUnit.test("Context is transmitted when creating spreadsheet", async function (assert) {
const serverData = await getDocumentBasicData({
"documents.document,false,kanban": `
`,
"documents.document,false,search": getEnrichedSearchArch(),
});
serviceRegistry.add("spreadsheet_collaborative", makeFakeSpreadsheetService());
const { openView } = await start({
mockRPC: async function (route, args) {
if (args.method === "action_open_new_spreadsheet") {
assert.step("action_open_new_spreadsheet");
assert.strictEqual(args.kwargs.context.default_res_id, 42);
assert.strictEqual(args.kwargs.context.default_res_model, "test.model");
}
},
serverData,
});
await openView({
context: {
default_res_model: "test.model",
default_res_id: 42,
},
res_model: "documents.document",
views: [[false, "kanban"]],
});
const menu = target.querySelector(".o_control_panel .d-xl-inline-flex .btn-group");
await click(menu, ".dropdown-toggle");
await click(menu, ".o_documents_kanban_spreadsheet");
const dialog = document.querySelector(".o-spreadsheet-templates-dialog");
// select blank spreadsheet
await triggerEvent(dialog.querySelectorAll(".o-template-image")[0], null, "focus");
await click(dialog, ".o-spreadsheet-create");
assert.verifySteps(["action_open_new_spreadsheet"]);
});
QUnit.test("Can create a spreadsheet from a template", async function (assert) {
const mockDoAction = (action) => {
assert.step("redirect");
assert.equal(action.tag, "an_action");
};
const { env } = await initTestEnvWithKanban({
additionalTemplates: TEST_TEMPLATES,
mockRPC: async function (route, args) {
if (
args.model === "spreadsheet.template" &&
args.method === "action_create_spreadsheet"
) {
assert.step("action_create_spreadsheet");
assert.strictEqual(args.args[1].folder_id, 1);
const action = {
type: "ir.actions.client",
tag: "an_action",
};
return action;
}
},
});
mockActionService(env, mockDoAction);
// ### With confirm button
const menu = target.querySelector(".o_control_panel .d-xl-inline-flex .btn-group");
await click(menu, ".dropdown-toggle");
await click(menu, ".o_documents_kanban_spreadsheet");
let dialog = document.querySelector(".o-spreadsheet-templates-dialog");
// select blank spreadsheet
await triggerEvent(dialog.querySelectorAll(".o-template-image")[1], null, "focus");
await click(dialog.querySelector(".o-spreadsheet-create"));
assert.verifySteps(["action_create_spreadsheet", "redirect"]);
// ### With double click on image
await click(menu, ".dropdown-toggle");
await click(menu, ".o_documents_kanban_spreadsheet");
dialog = document.querySelector(".o-spreadsheet-templates-dialog");
await triggerEvent(dialog.querySelectorAll(".o-template-image")[1], null, "focus");
await triggerEvent(dialog.querySelectorAll(".o-template-image")[1], null, "dblclick");
assert.verifySteps(["action_create_spreadsheet", "redirect"]);
// ### With enter key
await click(menu, ".o_documents_kanban_spreadsheet");
dialog = document.querySelector(".o-spreadsheet-templates-dialog");
await triggerEvent(dialog.querySelectorAll(".o-template-image")[1], null, "focus");
await triggerEvent(dialog.querySelectorAll(".o-template-image")[1], null, "keydown", {
key: "Enter",
});
assert.verifySteps(["action_create_spreadsheet", "redirect"]);
});
QUnit.test(
"The workspace selection should not display Trash workspace",
async function (assert) {
await initTestEnvWithKanban();
const menu = target.querySelector(
".o_control_panel .btn-group:not(.o_control_panel_collapsed_create .btn-group)"
);
await click(target, ".o_search_panel_category_value:nth-of-type(1) header");
await click(menu, ".dropdown-toggle");
await click(menu, ".o_documents_kanban_spreadsheet");
const selection = target.querySelector(".o-spreadsheet-templates-dialog select");
assert.notOk(
[...selection.options].find((option) => option.value === "TRASH"),
"Trash workspace should not be present in the selection"
);
}
);
QUnit.test(
"Offset reset to zero after searching for template in template dialog",
async function (assert) {
const mockRPC = async function (route, args) {
if (
args.method === "web_search_read" &&
args.model === "spreadsheet.template"
) {
assert.step(
JSON.stringify({
offset: args.kwargs.offset,
limit: args.kwargs.limit,
})
);
}
};
await initTestEnvWithKanban({ additionalTemplates: TEST_TEMPLATES, mockRPC });
const menu = target.querySelector(".o_control_panel .d-xl-inline-flex .btn-group");
await click(menu, ".dropdown-toggle");
await click(menu, ".o_documents_kanban_spreadsheet");
const dialog = document.querySelector(".o-spreadsheet-templates-dialog");
assert.equal(
dialog.querySelectorAll(".o-template:not(.o-template-ghost-item)").length,
10
);
await click(dialog.querySelector(".o_pager_next"));
assert.verifySteps([
JSON.stringify({ offset: 0, limit: 9 }),
JSON.stringify({ offset: 9, limit: 9 }),
]);
const searchInput = dialog.querySelector(".o_searchview_input");
await editInput(searchInput, null, "Template 1");
await triggerEvent(searchInput, null, "keydown", { key: "Enter" });
await nextTick();
assert.equal(
dialog.querySelectorAll(".o-template:not(.o-template-ghost-item)").length,
5
); // Blank template, Template 1, Template 10, Template 11, Template 12
assert.verifySteps([JSON.stringify({ offset: 0, limit: 9 })]);
assert.strictEqual(
target.querySelector(".o_pager_value").textContent,
"1-4",
"Pager should be reset to 1-4 after searching for a template"
);
}
);
}
);