[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) <aab@odoo.com>
This commit is contained in:
Francois (fge)
2021-09-24 12:35:21 +00:00
parent 1dcf1b6554
commit 2d8c868363
3 changed files with 48 additions and 3 deletions
@@ -230,7 +230,10 @@ var ServicesMixin = {
action: action,
options: options,
on_success: resolve,
on_fail: reject,
on_fail: (reason) => {
reject(reason);
return "alreadyThrown"
},
});
});
},
+3 -2
View File
@@ -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;
}
});
@@ -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");
});
});
});