From 2d8c868363fa478455081fba572c0cd5ebf1342e Mon Sep 17 00:00:00 2001 From: "Francois (fge)" Date: Thu, 23 Sep 2021 07:56:23 +0000 Subject: [PATCH] [FIX] web: do_action open twice error dialog Before this commit, using a do_action that throws an error opened two error dialogs. To solve this, in the compatibility layer, we check that the error has not already been thrown. To reproduce the problem, you can execute an action using do_action which will return an error. For example, an action performing an rpc and the server returns an error. You can find an example scenario to test the problem on the 2618694. closes odoo/odoo#77148 X-original-commit: 582604990e28c329348475f373b03295903ed77e Signed-off-by: Aaron Bohy (aab) --- .../src/legacy/js/core/service_mixins.js | 5 ++- addons/web/static/src/legacy/utils.js | 5 ++- .../static/tests/legacy/core/mixins_tests.js | 41 +++++++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/addons/web/static/src/legacy/js/core/service_mixins.js b/addons/web/static/src/legacy/js/core/service_mixins.js index de05b0843de..e35f0695ff0 100644 --- a/addons/web/static/src/legacy/js/core/service_mixins.js +++ b/addons/web/static/src/legacy/js/core/service_mixins.js @@ -230,7 +230,10 @@ var ServicesMixin = { action: action, options: options, on_success: resolve, - on_fail: reject, + on_fail: (reason) => { + reject(reason); + return "alreadyThrown" + }, }); }); }, diff --git a/addons/web/static/src/legacy/utils.js b/addons/web/static/src/legacy/utils.js index 75b0c330305..72ee1334671 100644 --- a/addons/web/static/src/legacy/utils.js +++ b/addons/web/static/src/legacy/utils.js @@ -282,10 +282,11 @@ export function makeLegacyCrashManagerService(legacyEnv) { export function wrapSuccessOrFail(promise, { on_success, on_fail } = {}) { return promise.then(on_success || (() => {})).catch((reason) => { + let alreadyThrown = false; if (on_fail) { - on_fail(reason); + alreadyThrown = on_fail(reason) === "alreadyThrown"; } - if (reason instanceof Error) { + if (reason instanceof Error && !alreadyThrown) { throw reason; } }); diff --git a/addons/web/static/tests/legacy/core/mixins_tests.js b/addons/web/static/tests/legacy/core/mixins_tests.js index 8c71a2592ce..c1c2dc80941 100644 --- a/addons/web/static/tests/legacy/core/mixins_tests.js +++ b/addons/web/static/tests/legacy/core/mixins_tests.js @@ -1,9 +1,17 @@ odoo.define('web.mixins_tests', function (require) { "use strict"; +const AbstractAction = require("web.AbstractAction"); +const core = require("web.core"); var testUtils = require('web.test_utils'); var Widget = require('web.Widget'); +const { dialogService } = require('@web/core/dialog/dialog_service'); +const { errorService } = require("@web/core/errors/error_service"); +const { registry } = require('@web/core/registry'); +const { nextTick, patchWithCleanup } = require('@web/../tests/helpers/utils'); +const { createWebClient, doAction } = require('@web/../tests/webclient/helpers'); + QUnit.module('core', {}, function () { QUnit.module('mixins'); @@ -29,7 +37,40 @@ QUnit.module('core', {}, function () { }); }); + QUnit.test('checks that the error generated by a do_action opens one dialog', async function (assert) { + assert.expect(1); + window.addEventListener("unhandledrejection", async (ev) => { + ev.preventDefault(); + }); + patchWithCleanup(QUnit, { + onUnhandledRejection: () => {}, + }); + + const serviceRegistry = registry.category("services"); + serviceRegistry.add("dialog", dialogService); + serviceRegistry.add("error", errorService); + + const TestAction = AbstractAction.extend({ + on_attach_callback() { + this.do_action({ + id: 1, + type: "ir.actions.server", + }) + }, + }); + core.action_registry.add("TestAction", TestAction); + + const mockRPC = (route) => { + if (route === "/web/action/run") { + throw new Error("This error should be throw only once"); + } + }; + const webClient = await createWebClient({mockRPC}); + await doAction(webClient, "TestAction"); + await nextTick(); + assert.containsOnce(webClient, ".o_dialog"); + }); }); });