diff --git a/addons/web/static/src/webclient/clickbot/clickbot.js b/addons/web/static/src/webclient/clickbot/clickbot.js index 1c48fa13987..4495abe61f7 100644 --- a/addons/web/static/src/webclient/clickbot/clickbot.js +++ b/addons/web/static/src/webclient/clickbot/clickbot.js @@ -23,6 +23,7 @@ const STUDIO_SYSTRAY_ICON_SELECTOR = ".o_web_studio_navbar_item:not(.o_disabled) let isEnterprise; let appsMenusOnly = false; let calledRPC; +let errorRPC; let actionCount; let env; let studioCount; @@ -46,6 +47,7 @@ function setup() { env.bus.addEventListener("RPC:RESPONSE", onRPCResponse); actionCount = 0; calledRPC = {}; + errorRPC = undefined; studioCount = 0; testedApps = []; testedMenus = []; @@ -63,6 +65,9 @@ function onRPCRequest({ detail }) { function onRPCResponse({ detail }) { delete calledRPC[detail.data.id]; + if (detail.error) { + errorRPC = { ...detail }; + } } function uiUpdate() { @@ -128,11 +133,22 @@ async function waitForCondition(stopCondition) { } return size > 0; } - - while (!stopCondition() || hasPendingRPC() || hasScheduledTask()) { + function errorDialog() { if (document.querySelector(".o_error_dialog")) { - throw new Error("Error dialog detected"); + if (errorRPC) { + browser.console.error( + "A RPC in error was detected, maybe it's related to the error dialog : " + + JSON.stringify(errorRPC) + ); + } + throw new Error( + "Error dialog detected" + document.querySelector(".o_error_dialog").innerHTML + ); } + return false; + } + + while (errorDialog() || !stopCondition() || hasPendingRPC() || hasScheduledTask()) { if (timeLimit <= 0) { let msg = `Timeout, the clicked element took more than ${ initialTime / 1000 diff --git a/addons/web/static/tests/helpers/mock_services.js b/addons/web/static/tests/helpers/mock_services.js index 9ea4d1492b1..43f29a0e32e 100644 --- a/addons/web/static/tests/helpers/mock_services.js +++ b/addons/web/static/tests/helpers/mock_services.js @@ -79,7 +79,14 @@ export function makeFakeRPCService(mockRPC) { env.bus.trigger("RPC:RESPONSE", { data, settings, result }); resolve(result); }) - .catch(reject); + .catch((error) => { + env.bus.trigger("RPC:RESPONSE", { + data, + settings, + error, + }); + reject(error); + }); }); rpcProm.abort = (rejectError = true) => { if (rejectError) { diff --git a/addons/web/static/tests/webclient/clickbot_tests.js b/addons/web/static/tests/webclient/clickbot_tests.js index 28d260eaa95..510cd830d68 100644 --- a/addons/web/static/tests/webclient/clickbot_tests.js +++ b/addons/web/static/tests/webclient/clickbot_tests.js @@ -12,6 +12,8 @@ import { import { browser } from "@web/core/browser/browser"; import { ListRenderer } from "@web/views/list/list_renderer"; import { onWillStart, onWillUpdateProps } from "@odoo/owl"; +import { errorService } from "@web/core/errors/error_service"; +import { makeServerError } from "@web/../tests/helpers/mock_server"; let serverData; let clickEverywhereDef; @@ -317,6 +319,67 @@ QUnit.module("clickbot", (hooks) => { ]); }); + QUnit.test("clickbot show rpc error when an error dialog is detected", async (assert) => { + let clickBotStarted = false; + registry.category("services").add("error", errorService); + serverData.actions = { + 1001: { + id: 1, + name: "App1", + res_model: "foo", + type: "ir.actions.act_window", + views: [[false, "list"]], + }, + }; + serverData.menus = { + root: { id: "root", children: [1], name: "root", appID: "root" }, + 1: { id: 1, children: [], name: "App1", appID: 1, actionID: 1001, xmlid: "app1" }, + }; + patchWithCleanup(browser, { + console: { + log: (msg) => { + if (msg === "test successful") { + assert.step(msg); + clickEverywhereDef.resolve(); + } + }, + error: (msg) => { + assert.step(msg.toString()); + clickEverywhereDef.resolve(); + }, + }, + }); + let id = 1; + await createWebClient({ + serverData, + mockRPC: async function (route, args) { + if (args.method === "web_search_read") { + if (clickBotStarted) { + if (id === 3) { + // click on the Second Filter + throw makeServerError({ + message: + "This is a server Error, it should be displayed in an error dialog", + }); + } + id++; + } + } + }, + }); + clickBotStarted = true; + + clickEverywhereDef = makeDeferred(); + window.clickEverywhere(); + await clickEverywhereDef; + await nextTick(); + assert.verifySteps([ + 'A RPC in error was detected, maybe it\'s related to the error dialog : {"data":{"id":6,"jsonrpc":"2.0","method":"call","params":{"model":"foo","method":"web_search_read","args":[],"kwargs":{"specification":{"foo":{}},"offset":0,"order":"","limit":80,"context":{"lang":"en","uid":7,"tz":"taht","bin_size":true},"count_limit":10001,"domain":["|",["bar","=",false],"&",["date",">=","2024-04-01"],["date","<=","2024-04-30"]]}}},"settings":{"silent":false},"error":{"name":"RPC_ERROR","type":"server","code":200,"data":{"name":"odoo.exceptions.UserError","debug":"traceback","arguments":[],"context":{}},"exceptionName":"odoo.exceptions.UserError","message":"This is a server Error, it should be displayed in an error dialog","errorEvent":{"isTrusted":true}}}', + "Error while testing App1 app1", + 'Error: Error dialog detected

An error occurred

Please use the copy button to report the error to your support service.

', + ]); + }); + QUnit.test("clickbot test waiting render after clicking filter", async (assert) => { let clickBotStarted = false; serverData.actions = {