/** @odoo-module */ import { ormService } from "@web/core/orm_service"; import { registry } from "@web/core/registry"; import { makeTestEnv } from "@web/../tests/helpers/mock_env"; import { DashboardLoader, Status, } from "@spreadsheet_dashboard/bundle/dashboard_action/dashboard_loader"; import { nextTick, patchWithCleanup } from "@web/../tests/helpers/utils"; import { getDashboardServerData } from "../utils/data"; import { waitForDataSourcesLoaded } from "@spreadsheet/../tests/utils/model"; import { getCellValue } from "@spreadsheet/../tests/utils/getters"; import { RPCError } from "@web/core/network/rpc_service"; /** * @param {object} [params] * @param {object} [params.serverData] * @param {function} [params.mockRPC] * @returns {Promise} */ async function createDashboardLoader(params = {}) { registry.category("services").add("orm", ormService); const env = await makeTestEnv({ serverData: params.serverData || getDashboardServerData(), mockRPC: params.mockRPC, }); return new DashboardLoader(env, env.services.orm, async (dashboardId) => { const [record] = await env.services.orm.read( "spreadsheet.dashboard", [dashboardId], ["raw"] ); return { data: record.raw, revisions: [] }; }); } QUnit.module("spreadsheet_dashboard > Dashboard loader"); QUnit.test("load all dashboards of all containers", async (assert) => { const loader = await createDashboardLoader(); loader.load(); assert.deepEqual(loader.getDashboardGroups(), []); await nextTick(); assert.deepEqual(loader.getDashboardGroups(), [ { id: 1, name: "Container 1", dashboards: [ { id: 1, displayName: "Dashboard CRM 1", status: Status.NotLoaded, }, { id: 2, displayName: "Dashboard CRM 2", status: Status.NotLoaded, }, ], }, { id: 2, name: "Container 2", dashboards: [ { id: 3, displayName: "Dashboard Accounting 1", status: Status.NotLoaded, }, ], }, ]); }); QUnit.test("load twice does not duplicate spreadsheets", async (assert) => { const loader = await createDashboardLoader(); await loader.load(); assert.deepEqual(loader.getDashboardGroups()[1].dashboards, [ { id: 3, displayName: "Dashboard Accounting 1", status: Status.NotLoaded }, ]); await loader.load(); assert.deepEqual(loader.getDashboardGroups()[1].dashboards, [ { id: 3, displayName: "Dashboard Accounting 1", status: Status.NotLoaded }, ]); }); QUnit.test("load spreadsheet data", async (assert) => { const loader = await createDashboardLoader(); await loader.load(); const result = loader.getDashboard(3); assert.strictEqual(result.status, Status.Loading); await nextTick(); assert.strictEqual(result.status, Status.Loaded); assert.ok(result.model); }); QUnit.test("load spreadsheet data only once", async (assert) => { const loader = await createDashboardLoader({ mockRPC: function (route, args) { if (args.method === "read") { assert.step(`spreadsheet ${args.args[0]} loaded`); } }, }); await loader.load(); let result = loader.getDashboard(3); await nextTick(); assert.strictEqual(result.status, Status.Loaded); assert.verifySteps(["spreadsheet 1,2,3 loaded", "spreadsheet 3 loaded"]); result = loader.getDashboard(3); await nextTick(); assert.strictEqual(result.status, Status.Loaded); assert.verifySteps([]); }); QUnit.test("don't return empty dashboard group", async (assert) => { const loader = await createDashboardLoader({ mockRPC: async function (route, args) { if (args.method === "search_read" && args.model === "spreadsheet.dashboard.group") { return [ { id: 45, name: "Group A", dashboard_ids: [1], }, { id: 46, name: "Group B", dashboard_ids: [], }, ]; } }, }); await loader.load(); assert.deepEqual(loader.getDashboardGroups(), [ { id: 45, name: "Group A", dashboards: [ { id: 1, displayName: "Dashboard CRM 1", status: Status.NotLoaded, }, ], }, ]); }); QUnit.test("load multiple spreadsheets", async (assert) => { const loader = await createDashboardLoader({ mockRPC: function (route, args) { if (args.method === "read") { assert.step(`spreadsheet ${args.args[0]} loaded`); } }, }); await loader.load(); assert.verifySteps(["spreadsheet 1,2,3 loaded"]); loader.getDashboard(1); await nextTick(); assert.verifySteps(["spreadsheet 1 loaded"]); loader.getDashboard(2); await nextTick(); assert.verifySteps(["spreadsheet 2 loaded"]); loader.getDashboard(1); await nextTick(); assert.verifySteps([]); }); QUnit.test("load spreadsheet data with error", async (assert) => { const loader = await createDashboardLoader({ mockRPC: function (route, args) { if ( args.method === "read" && args.model === "spreadsheet.dashboard" && args.args[1][0] === "raw" ) { const error = new RPCError(); error.data = { message: "Bip" }; throw error; } }, }); await loader.load(); const result = loader.getDashboard(3); assert.strictEqual(result.status, Status.Loading); await result.promise.catch(() => assert.step("error")); assert.strictEqual(result.status, Status.Error); assert.strictEqual(result.error.data.message, "Bip"); assert.verifySteps(["error"], "error is thrown"); }); QUnit.test("async formulas are correctly evaluated", async (assert) => { const spreadsheetData = { sheets: [ { id: "sheet1", cells: { A1: { content: `=ODOO.CURRENCY.RATE("EUR","USD")` }, // an async formula }, }, ], }; const serverData = getDashboardServerData(); const dashboardId = 15; serverData.models["spreadsheet.dashboard"].records = [ { id: dashboardId, raw: JSON.stringify(spreadsheetData), json_data: JSON.stringify(spreadsheetData), name: "Dashboard Accounting 1", dashboard_group_id: 2, }, ]; serverData.models["spreadsheet.dashboard.group"].records = [ { id: 1, name: "Container 1", dashboard_ids: [dashboardId] }, ]; const loader = await createDashboardLoader({ serverData, mockRPC: function (route, args) { if (args.method === "get_rates_for_spreadsheet") { const info = args.args[0][0]; return [{ ...info, rate: 0.9 }]; } }, }); await loader.load(); loader.getDashboard(dashboardId); await nextTick(); const { model } = loader.getDashboard(dashboardId); await waitForDataSourcesLoaded(model); assert.strictEqual(await getCellValue(model, "A1"), 0.9); }); QUnit.test("Model is in dashboard mode", async (assert) => { const loader = await createDashboardLoader(); await loader.load(); loader.getDashboard(3); await nextTick(); const { model } = loader.getDashboard(3); assert.strictEqual(model.config.mode, "dashboard"); }); QUnit.test("Model is in dashboard mode", async (assert) => { patchWithCleanup(DashboardLoader.prototype, { _activateFirstSheet: () => { assert.step("activate sheet"); }, }); const loader = await createDashboardLoader(); await loader.load(); loader.getDashboard(3); await nextTick(); assert.verifySteps(["activate sheet"]); });