diff --git a/addons/survey/static/tests/components/question_page_one2many_field_tests.js b/addons/survey/static/tests/components/question_page_one2many_field_tests.js
index b78c6182727..7f45cff5bad 100644
--- a/addons/survey/static/tests/components/question_page_one2many_field_tests.js
+++ b/addons/survey/static/tests/components/question_page_one2many_field_tests.js
@@ -2,7 +2,6 @@
import { makeServerError } from "@web/../tests/helpers/mock_server";
import { click, editInput, getFixture, nextTick, triggerHotkey } from "@web/../tests/helpers/utils";
-import { registerCleanup } from "@web/../tests/helpers/cleanup";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
import { errorService } from "@web/core/errors/error_service";
import { registry } from "@web/core/registry";
@@ -174,11 +173,6 @@ QUnit.module("QuestionPageOneToManyField", (hooks) => {
QUnit.test("A validation error from saving parent form notifies and prevents dialog from closing", async (assert) => {
registry.category("services").add("error", errorService);
- // need to preventDefault to remove error from console (so python test pass)
- const handler = (ev) => ev.preventDefault();
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
-
await makeView({
type: "form",
resModel: "survey",
diff --git a/addons/web/static/lib/qunit/qunit-2.9.1.js b/addons/web/static/lib/qunit/qunit-2.9.1.js
index fc886ffaa37..28760e75902 100644
--- a/addons/web/static/lib/qunit/qunit-2.9.1.js
+++ b/addons/web/static/lib/qunit/qunit-2.9.1.js
@@ -3128,7 +3128,7 @@
},
- finish: function finish() {
+ finish: async function finish() {
config.current = this;
// Release the test callback to ensure that anything referenced has been
@@ -3148,7 +3148,13 @@
this.pushFailure("Expected at least one assertion, but none were run - call " + "expect(0) to accept zero assertions.", this.stack);
}
- emit("OdooAfterTestHook", this); // Odoo customization
+ // Odoo customization
+ // wait for the task queue to be fully consummed, s.t. if there has been rejected promises
+ // during the test, the unhandledrejection handlers have been called before the cleanups
+ // have been executed, for the errors to be properly preventDefaulted if necessary (see
+ // qunit.js, Error management section).
+ await new Promise((r) => setTimeout(r, 0));
+ emit("OdooAfterTestHook", this);
var i,
module = this.module,
diff --git a/addons/web/static/src/core/errors/error_handlers.js b/addons/web/static/src/core/errors/error_handlers.js
index ba31c871e9b..292b357c6af 100644
--- a/addons/web/static/src/core/errors/error_handlers.js
+++ b/addons/web/static/src/core/errors/error_handlers.js
@@ -146,7 +146,7 @@ const defaultDialogs = new Map([
* @param {UncaughError} error
* @returns {boolean}
*/
-function defaultHandler(env, error) {
+export function defaultHandler(env, error) {
const DialogComponent = defaultDialogs.get(error.constructor) || ErrorDialog;
env.services.dialog.add(DialogComponent, {
traceback: error.traceback,
diff --git a/addons/web/static/src/core/errors/error_service.js b/addons/web/static/src/core/errors/error_service.js
index 498731efb5f..3e147222594 100644
--- a/addons/web/static/src/core/errors/error_service.js
+++ b/addons/web/static/src/core/errors/error_service.js
@@ -48,21 +48,17 @@ export const errorService = {
while (originalError instanceof Error && "cause" in originalError) {
originalError = originalError.cause;
}
- const services = env.services;
- if (!services.dialog || !services.notification || !services.rpc) {
- // here, the environment is not ready to provide feedback to the user.
- // We simply wait 1 sec and try again, just in case the application can
- // recover.
- if (retry) {
- browser.setTimeout(() => {
- handleError(uncaughtError, false);
- }, 1000);
- }
- return;
- }
- for (const handler of registry.category("error_handlers").getAll()) {
- if (handler(env, uncaughtError, originalError)) {
- break;
+ for (const [name, handler] of registry.category("error_handlers").getEntries()) {
+ try {
+ if (handler(env, uncaughtError, originalError)) {
+ break;
+ }
+ } catch (e) {
+ console.error(
+ `A crash occured in error handler ${name} while handling ${uncaughtError}:`,
+ e
+ );
+ return;
}
}
if (uncaughtError.event && !uncaughtError.event.defaultPrevented) {
diff --git a/addons/web/static/tests/core/code_editor_tests.js b/addons/web/static/tests/core/code_editor_tests.js
index 5cb00ce0422..f11aa035b19 100644
--- a/addons/web/static/tests/core/code_editor_tests.js
+++ b/addons/web/static/tests/core/code_editor_tests.js
@@ -13,8 +13,6 @@ import {
import { Component, markup, useState, xml } from "@odoo/owl";
import { CodeEditor } from "@web/core/code_editor/code_editor";
import { registerCleanup } from "@web/../tests/helpers/cleanup";
-import { registry } from "@web/core/registry";
-import { errorService } from "@web/core/errors/error_service";
QUnit.module("Web Components", (hooks) => {
QUnit.module("Code Editor");
@@ -84,6 +82,8 @@ QUnit.module("Web Components", (hooks) => {
});
QUnit.test("CodeEditor shouldn't accepts markup values", async (assert) => {
+ assert.expectErrors();
+
const _console = window.console;
window.console = Object.assign(Object.create(_console), {
warn(msg) {
@@ -93,18 +93,7 @@ QUnit.module("Web Components", (hooks) => {
registerCleanup(() => {
window.console = _console;
});
- registry.category("services").add("error", errorService);
- const handler = (ev) => {
- assert.step(ev.reason.message);
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
- };
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
- patchWithCleanup(QUnit, {
- onUnhandledRejection: () => {},
- });
class Parent extends Component {
static components = { CodeEditor };
static template = xml``;
@@ -121,10 +110,8 @@ QUnit.module("Web Components", (hooks) => {
const textMarkup = markup`
Some Text
`;
codeEditor.state.value = textMarkup;
await nextTick(); // wait for the errorService to be called
- assert.verifySteps([
- "[Owl] Unhandled error. Destroying the root component",
- "Invalid props for component 'CodeEditor': 'value' is not valid",
- ]);
+ assert.verifySteps(["[Owl] Unhandled error. Destroying the root component"]);
+ assert.verifyErrors(["Invalid props for component 'CodeEditor': 'value' is not valid"]);
});
QUnit.test("onChange props called when code is edited", async (assert) => {
diff --git a/addons/web/static/tests/core/dialog_service_tests.js b/addons/web/static/tests/core/dialog_service_tests.js
index 2685df5de74..5aabb185dd2 100644
--- a/addons/web/static/tests/core/dialog_service_tests.js
+++ b/addons/web/static/tests/core/dialog_service_tests.js
@@ -7,7 +7,6 @@ import { registry } from "@web/core/registry";
import { notificationService } from "@web/core/notifications/notification_service";
import { uiService } from "@web/core/ui/ui_service";
import { hotkeyService } from "@web/core/hotkeys/hotkey_service";
-import { registerCleanup } from "../helpers/cleanup";
import { clearRegistryWithCleanup, makeTestEnv } from "../helpers/mock_env";
import { makeFakeLocalizationService, makeFakeRPCService } from "../helpers/mock_services";
import {
@@ -197,7 +196,8 @@ QUnit.test("Interactions between multiple dialogs", async (assert) => {
});
QUnit.test("dialog component crashes", async (assert) => {
- assert.expect(4);
+ assert.expect(3);
+ assert.expectErrors();
class FailingDialog extends Component {
setup() {
@@ -217,18 +217,6 @@ QUnit.test("dialog component crashes", async (assert) => {
},
});
- const handler = (ev) => {
- assert.step("error");
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
- };
-
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
- patchWithCleanup(QUnit, {
- onUnhandledRejection: () => {},
- });
-
const rpc = makeFakeRPCService();
serviceRegistry.add("rpc", rpc, { force: true });
serviceRegistry.add("notification", notificationService);
@@ -239,7 +227,7 @@ QUnit.test("dialog component crashes", async (assert) => {
env.services.dialog.add(FailingDialog);
await prom;
- assert.verifySteps(["error"]);
assert.containsOnce(target, ".modal");
assert.containsOnce(target, ".modal .o_error_dialog");
+ assert.verifyErrors(["Some Error"]);
});
diff --git a/addons/web/static/tests/core/errors/error_service_tests.js b/addons/web/static/tests/core/errors/error_service_tests.js
index 4790b7e2782..b9b6c048f01 100644
--- a/addons/web/static/tests/core/errors/error_service_tests.js
+++ b/addons/web/static/tests/core/errors/error_service_tests.js
@@ -25,6 +25,7 @@ import {
import { getFixture, makeDeferred, mount, nextTick, patchWithCleanup } from "../../helpers/utils";
import { Component, xml, onError, OwlError, onWillStart } from "@odoo/owl";
+import { defaultHandler } from "@web/core/errors/error_handlers";
const errorDialogRegistry = registry.category("error_dialogs");
const errorHandlerRegistry = registry.category("error_handlers");
const serviceRegistry = registry.category("services");
@@ -251,6 +252,7 @@ QUnit.test("will let handlers from the registry handle errors first", async (ass
assert.strictEqual(originalError, error);
assert.strictEqual(env.someValue, 14);
assert.step("in handler");
+ return true;
});
const testEnv = await makeTestEnv();
testEnv.someValue = 14;
@@ -271,6 +273,7 @@ QUnit.test("originalError is the root cause of the error chain", async (assert)
assert.ok(err.cause instanceof OwlError); // Wrapped by owl
assert.strictEqual(err.cause.cause, originalError); // original error
assert.step("in handler");
+ return true;
});
const testEnv = await makeTestEnv();
testEnv.someValue = 14;
@@ -318,6 +321,7 @@ QUnit.test("originalError is the root cause of the error chain", async (assert)
});
QUnit.test("handle uncaught promise errors", async (assert) => {
+ assert.expectErrors();
class TestError extends Error {}
const error = new TestError();
error.message = "This is an error test";
@@ -340,9 +344,11 @@ QUnit.test("handle uncaught promise errors", async (assert) => {
cancelable: true,
});
await unhandledRejectionCb(errorEvent);
+ assert.verifyErrors(["This is an error test"]);
});
QUnit.test("handle uncaught client errors", async (assert) => {
+ assert.expectErrors();
class TestError extends Error {}
const error = new TestError();
error.message = "This is an error test";
@@ -364,9 +370,11 @@ QUnit.test("handle uncaught client errors", async (assert) => {
cancelable: true,
});
await errorCb(errorEvent);
+ assert.verifyErrors(["This is an error test"]);
});
QUnit.test("handle uncaught CORS errors", async (assert) => {
+ assert.expectErrors();
class TestError extends Error {}
const error = new TestError();
error.message = "This is a cors error";
@@ -382,50 +390,14 @@ QUnit.test("handle uncaught CORS errors", async (assert) => {
// CORS error event has no colno, no lineno and no filename
const errorEvent = new ErrorEvent("error", { error, cancelable: true });
await errorCb(errorEvent);
-});
-
-QUnit.test("check retry", async (assert) => {
- assert.expect(3);
-
- errorHandlerRegistry.add("__test_handler__", () => {
- assert.step("dispatched");
- });
-
- const def = makeDeferred();
- patchWithCleanup(browser, {
- setTimeout(fn) {
- def.then(fn);
- },
- });
-
- serviceRegistry.remove("dialog");
- await makeTestEnv();
-
- class TestError extends Error {}
- const error = new TestError();
- error.message = "This is an error test";
- error.name = "TestError";
-
- const errorEvent = new PromiseRejectionEvent("error", {
- reason: error,
- promise: null,
- cancelable: true,
- });
- await unhandledRejectionCb(errorEvent);
-
- assert.verifySteps([]);
-
- serviceRegistry.add("dialog", dialogService);
- await nextTick();
-
- await def.resolve();
- assert.verifySteps(["dispatched"]);
+ assert.verifyErrors(["This is a cors error"]);
});
QUnit.test("lazy loaded handlers", async (assert) => {
+ assert.expectErrors();
await makeTestEnv();
const errorEvent = new PromiseRejectionEvent("error", {
- reason: new Error(),
+ reason: new Error("error"),
promise: null,
cancelable: true,
});
@@ -435,10 +407,12 @@ QUnit.test("lazy loaded handlers", async (assert) => {
errorHandlerRegistry.add("__test_handler__", () => {
assert.step("in handler");
+ return true;
});
await unhandledRejectionCb(errorEvent);
assert.verifySteps(["in handler"]);
+ assert.verifyErrors(["error"]); // for the first throw, before registering the handler
});
// The following test(s) do not want the preventDefault to be done automatically.
@@ -450,6 +424,10 @@ QUnit.module("Error Service", {
serviceRegistry.add("rpc", makeFakeRPCService());
serviceRegistry.add("localization", makeFakeLocalizationService());
serviceRegistry.add("ui", uiService);
+ // remove the override of the defaultHandler done in qunit.js
+ registry
+ .category("error_handlers")
+ .add("defaultHandler", defaultHandler, { sequence: 100, force: true });
const windowAddEventListener = browser.addEventListener;
browser.addEventListener = (type, cb) => {
if (type === "unhandledrejection") {
diff --git a/addons/web/static/tests/core/main_components_container_tests.js b/addons/web/static/tests/core/main_components_container_tests.js
index 708fa999605..3b26fbf5708 100644
--- a/addons/web/static/tests/core/main_components_container_tests.js
+++ b/addons/web/static/tests/core/main_components_container_tests.js
@@ -2,10 +2,10 @@
import { MainComponentsContainer } from "@web/core/main_components_container";
import { registry } from "@web/core/registry";
import { clearRegistryWithCleanup, makeTestEnv } from "../helpers/mock_env";
-import { patch } from "@web/core/utils/patch";
import { getFixture, mount, nextTick } from "../helpers/utils";
import { Component, useState, xml } from "@odoo/owl";
+import { registerCleanup } from "../helpers/cleanup";
const mainComponentsRegistry = registry.category("main_components");
let target;
@@ -38,6 +38,7 @@ QUnit.module("Components", (hooks) => {
});
QUnit.test("unmounts erroring main component", async function (assert) {
+ assert.expectErrors();
const env = await makeTestEnv();
let compA;
@@ -67,24 +68,18 @@ QUnit.module("Components", (hooks) => {
const handler = (ev) => {
assert.step(ev.reason.message);
assert.step(ev.reason.cause.message);
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
};
window.addEventListener("unhandledrejection", handler);
- // fake error service so that the odoo qunit handlers don't think that they need to handle the error
- registry.category("services").add("error", { start: () => {} });
- const unpatch = patch(QUnit, {
- onUnhandledRejection: () => {},
+ registerCleanup(() => {
+ window.removeEventListener("unhandledrejection", handler);
});
compA.state.shouldThrow = true;
await nextTick();
- window.removeEventListener("unhandledrejection", handler);
- // unpatch QUnit asap so any other errors can be caught by it
- unpatch();
assert.verifySteps([
'An error occured in the owl lifecycle (see this Error\'s "cause" property)',
"BOOM",
]);
+ assert.verifyErrors(["BOOM"]);
assert.equal(
target.querySelector(".o-main-components-container").innerHTML,
@@ -93,6 +88,8 @@ QUnit.module("Components", (hooks) => {
});
QUnit.test("unmounts erroring main component: variation", async function (assert) {
+ assert.expectErrors();
+
const env = await makeTestEnv();
class MainComponentA extends Component {}
@@ -122,24 +119,18 @@ QUnit.module("Components", (hooks) => {
const handler = (ev) => {
assert.step(ev.reason.message);
assert.step(ev.reason.cause.message);
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
};
window.addEventListener("unhandledrejection", handler);
- // fake error service so that the odoo qunit handlers don't think that they need to handle the error
- registry.category("services").add("error", { start: () => {} });
- const unpatch = patch(QUnit, {
- onUnhandledRejection: () => {},
+ registerCleanup(() => {
+ window.removeEventListener("unhandledrejection", handler);
});
compB.state.shouldThrow = true;
await nextTick();
- window.removeEventListener("unhandledrejection", handler);
- // unpatch QUnit asap so any other errors can be caught by it
- unpatch();
assert.verifySteps([
'An error occured in the owl lifecycle (see this Error\'s "cause" property)',
"BOOM",
]);
+ assert.verifyErrors(["BOOM"]);
assert.equal(
target.querySelector(".o-main-components-container").innerHTML,
"MainComponentA"
diff --git a/addons/web/static/tests/qunit.js b/addons/web/static/tests/qunit.js
index bacf1acd6ba..0c6a70c2ccf 100644
--- a/addons/web/static/tests/qunit.js
+++ b/addons/web/static/tests/qunit.js
@@ -1,15 +1,12 @@
/** @odoo-module */
import { isVisible as isElemVisible } from "@web/core/utils/ui";
-import { UncaughtClientError, UncaughtPromiseError } from "@web/core/errors/error_service";
-import {
- completeUncaughtError,
- fullTraceback,
- fullAnnotatedTraceback,
-} from "@web/core/errors/error_utils";
+import { fullTraceback, fullAnnotatedTraceback } from "@web/core/errors/error_utils";
import { registry } from "@web/core/registry";
import { escape } from "@web/core/utils/strings";
+const consoleError = console.error;
+
function setQUnitDebugMode() {
owl.whenReady(() => document.body.classList.add("debug")); // make the test visible to the naked eye
QUnit.config.debug = true; // allows for helper functions to behave differently (logging, the HTML element in which the test occurs etc...)
@@ -207,6 +204,19 @@ export function setupQUnit() {
function isNotVisible(el, msg) {
return _checkVisible(el, false, msg);
}
+ function expectErrors() {
+ QUnit.config.current.expectErrors = true;
+ QUnit.config.current.unverifiedErrors = [];
+ }
+ function verifyErrors(expectedErrors) {
+ if (!QUnit.config.current.expectErrors) {
+ QUnit.pushFailure(`assert.expectErrors() must be called at the beginning of the test`);
+ return;
+ }
+ const unverifiedErrors = QUnit.config.current.unverifiedErrors;
+ QUnit.config.current.assert.deepEqual(unverifiedErrors, expectedErrors, "verifying errors");
+ QUnit.config.current.unverifiedErrors = [];
+ }
QUnit.assert.containsN = containsN;
QUnit.assert.containsNone = containsNone;
QUnit.assert.containsOnce = containsOnce;
@@ -215,6 +225,8 @@ export function setupQUnit() {
QUnit.assert.hasAttrValue = hasAttrValue;
QUnit.assert.isVisible = isVisible;
QUnit.assert.isNotVisible = isNotVisible;
+ QUnit.assert.expectErrors = expectErrors;
+ QUnit.assert.verifyErrors = verifyErrors;
// -----------------------------------------------------------------------------
// QUnit logs
@@ -229,7 +241,7 @@ export function setupQUnit() {
const messages = errorMessages.slice();
errorMessages = [];
const infos = await Promise.all(messages);
- console.error(infos.map((info) => info.error || info).join("\n"));
+ consoleError(infos.map((info) => info.error || info).join("\n"));
// Only log the source of the errors in "info" log level to allow matching the same
// error with its log message, as source contains asset file name which changes
console.info(
@@ -609,12 +621,54 @@ export function setupQUnit() {
document.head.appendChild(el);
});
- const { onUnhandledRejection, onError } = QUnit;
+ // -----------------------------------------------------------------------------
+ // Error management
+ // -----------------------------------------------------------------------------
+
+ QUnit.on("OdooAfterTestHook", (info) => {
+ const { expectErrors, unverifiedErrors } = QUnit.config.current;
+ if (expectErrors && unverifiedErrors.length) {
+ QUnit.pushFailure(
+ `Expected assert.verifyErrors() to be called before end of test. Unverified errors: ${unverifiedErrors}`
+ );
+ }
+ });
+
+ const { onUnhandledRejection } = QUnit;
QUnit.onUnhandledRejection = () => {};
QUnit.onError = () => {};
+
+ console.error = function () {
+ if (QUnit.config.current) {
+ QUnit.pushFailure(`console.error called with "${arguments[0]}"`);
+ } else {
+ consoleError(...arguments);
+ }
+ };
+
+ function onUncaughtErrorInTest(error) {
+ if (!QUnit.config.current.expectErrors) {
+ // we did not expect any error, so notify qunit to add a failure
+ onUnhandledRejection(error);
+ } else {
+ // we expected errors, so store it, it will be checked later (see verifyErrors)
+ while (error instanceof Error && "cause" in error) {
+ error = error.cause;
+ }
+ QUnit.config.current.unverifiedErrors.push(error.message);
+ }
+ }
+
+ // e.g. setTimeout(() => throw new Error()) (event handler crashes synchronously)
window.addEventListener("error", async (ev) => {
- // don't do anything if error service is up and we are in a test
- if (registry.category("services").get("error", false) && QUnit.config.current) {
+ if (!QUnit.config.current) {
+ return; // we are not in a test -> do nothing
+ }
+ // do not log to the console as this will kill python test early
+ ev.preventDefault();
+ // if the error service is deployed, we'll get to the patched default handler below if no
+ // other handler handled the error, so do nothing here
+ if (registry.category("services").get("error", false)) {
return;
}
if (
@@ -623,33 +677,36 @@ export function setupQUnit() {
) {
return;
}
- // Do not log to the console as this will kill python test early
- ev.preventDefault();
- const { error: originalError } = ev;
- const uncaughtError = new UncaughtClientError();
- if (originalError instanceof Error) {
- originalError.errorEvent = ev;
- await completeUncaughtError(uncaughtError, originalError);
- originalError.stacktrace = uncaughtError.traceback;
- }
- onError(originalError);
+ onUncaughtErrorInTest(ev.error);
});
+ // e.g. Promise.resolve().then(() => throw new Error()) (crash in event handler after async boundary)
window.addEventListener("unhandledrejection", async (ev) => {
- // don't do anything if error service is up and we are in a test
- if (registry.category("services").get("error", false) && QUnit.config.current) {
+ if (!QUnit.config.current) {
+ return; // we are not in a test -> do nothing
+ }
+ // do not log to the console as this will kill python test early
+ ev.preventDefault();
+ // if the error service is deployed, we'll get to the patched default handler below if no
+ // other handler handled the error, so do nothing here
+ if (registry.category("services").get("error", false)) {
return;
}
- // Do not log to the console as this will kill python test early
- ev.preventDefault();
- const originalError = ev.reason;
- const uncaughtError = new UncaughtPromiseError();
- uncaughtError.unhandledRejectionEvent = ev;
- if (originalError instanceof Error) {
- originalError.errorEvent = ev;
- await completeUncaughtError(uncaughtError, originalError);
- originalError.stack = uncaughtError.traceback;
- }
- onUnhandledRejection(originalError);
+ onUncaughtErrorInTest(ev.reason);
+ });
+
+ // This is an approximation, but we can't directly import the default error handler, because
+ // it's not the same in all tested environments (e.g. /web and /pos), so we get the last item
+ // from the handler registry and assume it is the default one, which handles all "not already
+ // handled" errors, like tracebacks.
+ const errorHandlerRegistry = registry.category("error_handlers");
+ const [defaultHandlerName, defaultHandler] = errorHandlerRegistry.getEntries().at(-1);
+ const testDefaultHandler = (env, uncaughtError, originalError) => {
+ onUncaughtErrorInTest(originalError);
+ return defaultHandler(env, uncaughtError, originalError);
+ };
+ errorHandlerRegistry.add(defaultHandlerName, testDefaultHandler, {
+ sequence: Number.POSITIVE_INFINITY,
+ force: true,
});
}
diff --git a/addons/web/static/tests/views/fields/binary_field_tests.js b/addons/web/static/tests/views/fields/binary_field_tests.js
index f4196c2e11e..9a7f3996a6b 100644
--- a/addons/web/static/tests/views/fields/binary_field_tests.js
+++ b/addons/web/static/tests/views/fields/binary_field_tests.js
@@ -506,8 +506,10 @@ QUnit.module("Fields", (hooks) => {
QUnit.test("Binary filename doesn't exceed 255 bytes", async function (assert) {
const LARGE_BINARY_FILE = BINARY_FILE.repeat(5);
- assert.ok((LARGE_BINARY_FILE.length / 4 * 3) > MAX_FILENAME_SIZE_BYTES,
- "The initial binary file should be larger than max bytes that can represent the filename");
+ assert.ok(
+ (LARGE_BINARY_FILE.length / 4) * 3 > MAX_FILENAME_SIZE_BYTES,
+ "The initial binary file should be larger than max bytes that can represent the filename"
+ );
serverData.models.partner.fields.document.default = LARGE_BINARY_FILE;
await makeView({
serverData,
diff --git a/addons/web/static/tests/views/fields/many2one_field_tests.js b/addons/web/static/tests/views/fields/many2one_field_tests.js
index 088ce052bf2..2c09edbca4e 100644
--- a/addons/web/static/tests/views/fields/many2one_field_tests.js
+++ b/addons/web/static/tests/views/fields/many2one_field_tests.js
@@ -1,6 +1,5 @@
/** @odoo-module **/
-import { registerCleanup } from "@web/../tests/helpers/cleanup";
import { makeTestEnv } from "@web/../tests/helpers/mock_env";
import { makeServerError } from "@web/../tests/helpers/mock_server";
import {
@@ -2950,14 +2949,6 @@ QUnit.module("Fields", (hooks) => {
registry.category("services").add("error", errorService);
- // remove the override in qunit.js that swallows unhandledrejection errors
- // s.t. we let the error service handle them
- const originalOnUnhandledRejection = window.onunhandledrejection;
- window.onunhandledrejection = () => {};
- registerCleanup(() => {
- window.onunhandledrejection = originalOnUnhandledRejection;
- });
-
serverData.views = {
"product,false,form": '',
};
diff --git a/addons/web/static/tests/views/fields/one2many_field_tests.js b/addons/web/static/tests/views/fields/one2many_field_tests.js
index a4863babf62..f04c92f5699 100644
--- a/addons/web/static/tests/views/fields/one2many_field_tests.js
+++ b/addons/web/static/tests/views/fields/one2many_field_tests.js
@@ -8931,29 +8931,6 @@ QUnit.module("Fields", (hooks) => {
QUnit.test("display correct value after validation error", async function (assert) {
assert.expect(5);
- /*
- * By-pass QUnit's and test's error handling because the error service needs to be active
- */
- const handler = (ev) => {
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
- };
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
-
- patchWithCleanup(QUnit, {
- onUnhandledRejection: () => {},
- });
-
- const originOnunhandledrejection = window.onunhandledrejection;
- window.onunhandledrejection = () => {};
- registerCleanup(() => {
- window.onunhandledrejection = originOnunhandledrejection;
- });
- /*
- * End By pass error handling
- */
-
serviceRegistry.add("error", errorService);
function validationHandler(env, error, originalError) {
if (originalError.data.name === "odoo.exceptions.ValidationError") {
diff --git a/addons/web/static/tests/views/form/form_view_tests.js b/addons/web/static/tests/views/form/form_view_tests.js
index 6731f61a5cd..c58cbf9b34a 100644
--- a/addons/web/static/tests/views/form/form_view_tests.js
+++ b/addons/web/static/tests/views/form/form_view_tests.js
@@ -1,7 +1,6 @@
/** @odoo-module **/
import { Component, EventBus, xml } from "@odoo/owl";
-import { registerCleanup } from "@web/../tests/helpers/cleanup";
import { makeServerError } from "@web/../tests/helpers/mock_server";
import { makeFakeNotificationService } from "@web/../tests/helpers/mock_services";
import {
@@ -3289,7 +3288,8 @@ QUnit.module("Views", (hooks) => {
});
QUnit.test("buttons in form view", async function (assert) {
- assert.expect(10);
+ assert.expect(12);
+ assert.expectErrors();
const mockedActionService = {
start() {
@@ -3300,7 +3300,7 @@ QUnit.module("Views", (hooks) => {
assert.strictEqual(params.resId, 2);
params.onClose();
} else {
- return Promise.reject();
+ throw makeServerError();
}
},
};
@@ -3337,6 +3337,7 @@ QUnit.module("Views", (hooks) => {
// click on p (will succeed and reload)
await click(target.querySelector(".o_form_statusbar button.p"));
+ assert.verifyErrors([]);
// click on s (will fail)
await click(target.querySelector(".o_form_statusbar button.s"));
@@ -3348,6 +3349,7 @@ QUnit.module("Views", (hooks) => {
"web_read", // reload (successfully clicked on p)
"some_method",
]);
+ assert.verifyErrors(["Odoo Server Error"]);
});
QUnit.test("buttons classes in form view", async function (assert) {
@@ -6322,13 +6324,6 @@ QUnit.module("Views", (hooks) => {
QUnit.test("onchange returns an error", async function (assert) {
registry.category("services").add("error", errorService);
registry.category("error_dialogs").add("odoo.exceptions.UserError", WarningDialog);
- // remove the override in qunit.js that swallows unhandledrejection errors
- // s.t. we let the error service handle them
- const originalOnUnhandledRejection = window.onunhandledrejection;
- window.onunhandledrejection = () => {};
- registerCleanup(() => {
- window.onunhandledrejection = originalOnUnhandledRejection;
- });
serverData.models.partner.onchanges = { int_field: () => {} };
await makeView({
@@ -9975,19 +9970,6 @@ QUnit.module("Views", (hooks) => {
QUnit.test("form view is not broken if save operation fails", async function (assert) {
registry.category("services").add("error", errorService);
- const handler = (ev) => {
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
- };
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
- // remove the override in qunit.js that swallows unhandledrejection errors
- // s.t. we let the error service handle them
- const originalOnUnhandledRejection = window.onunhandledrejection;
- window.onunhandledrejection = () => {};
- registerCleanup(() => {
- window.onunhandledrejection = originalOnUnhandledRejection;
- });
await makeView({
type: "form",
@@ -9998,7 +9980,7 @@ QUnit.module("Views", (hooks) => {
mockRPC(route, args) {
assert.step(args.method);
if (args.method === "web_save" && args.args[1].foo === "incorrect value") {
- return Promise.reject(new Error("Odoo Server Error"));
+ throw makeServerError();
}
},
});
@@ -10023,19 +10005,6 @@ QUnit.module("Views", (hooks) => {
"form view is not broken if save failed in readonly mode on field changed",
async function (assert) {
registry.category("services").add("error", errorService);
- const handler = (ev) => {
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
- };
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
- // remove the override in qunit.js that swallows unhandledrejection errors
- // s.t. we let the error service handle them
- const originalOnUnhandledRejection = window.onunhandledrejection;
- window.onunhandledrejection = () => {};
- registerCleanup(() => {
- window.onunhandledrejection = originalOnUnhandledRejection;
- });
let failFlag = false;
await makeView({
type: "form",
@@ -10053,7 +10022,7 @@ QUnit.module("Views", (hooks) => {
if (args.method === "web_save") {
assert.step("web_save");
if (failFlag) {
- return Promise.reject(new Error("Odoo Server Error"));
+ throw makeServerError();
}
} else if (args.method === "web_read") {
assert.step("web_read");
@@ -10890,10 +10859,10 @@ QUnit.module("Views", (hooks) => {
});
QUnit.test("keep editing after call_button fail", async function (assert) {
- assert.expect(4);
+ assert.expect(5);
+ assert.expectErrors();
let values;
-
const mockedActionService = {
start() {
return {
@@ -10903,7 +10872,7 @@ QUnit.module("Views", (hooks) => {
["post", "object"],
"the action should be correctly executed"
);
- return Promise.reject();
+ throw makeServerError();
},
};
},
@@ -10941,6 +10910,9 @@ QUnit.module("Views", (hooks) => {
product_id: false,
};
await click(target.querySelector("button.p"));
+
+ assert.verifyErrors(["Odoo Server Error"]);
+
// edit the new row again and set a many2one value
await click(
target.querySelectorAll(".o_form_view .o_field_one2many .o_data_row .o_data_cell")[1]
@@ -11919,20 +11891,6 @@ QUnit.module("Views", (hooks) => {
registry.category("services").add("error", errorService);
- const handler = (ev) => {
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
- };
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
- // remove the override in qunit.js that swallows unhandledrejection errors
- // s.t. we let the error service handle them
- const originalOnUnhandledRejection = window.onunhandledrejection;
- window.onunhandledrejection = () => {};
- registerCleanup(() => {
- window.onunhandledrejection = originalOnUnhandledRejection;
- });
-
serverData.actions[1] = {
id: 1,
name: "Partner",
@@ -12540,20 +12498,6 @@ QUnit.module("Views", (hooks) => {
registry.category("services").add("error", errorService);
- const handler = (ev) => {
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
- };
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
- // remove the override in qunit.js that swallows unhandledrejection errors
- // s.t. we let the error service handle them
- const originalOnUnhandledRejection = window.onunhandledrejection;
- window.onunhandledrejection = () => {};
- registerCleanup(() => {
- window.onunhandledrejection = originalOnUnhandledRejection;
- });
-
await makeView({
type: "form",
resModel: "partner",
@@ -12611,20 +12555,6 @@ QUnit.module("Views", (hooks) => {
registry.category("services").add("error", errorService);
- const handler = (ev) => {
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
- };
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
- // remove the override in qunit.js that swallows unhandledrejection errors
- // s.t. we let the error service handle them
- const originalOnUnhandledRejection = window.onunhandledrejection;
- window.onunhandledrejection = () => {};
- registerCleanup(() => {
- window.onunhandledrejection = originalOnUnhandledRejection;
- });
-
await makeView({
type: "form",
resModel: "partner",
@@ -12650,13 +12580,6 @@ QUnit.module("Views", (hooks) => {
QUnit.test("no 'oh snap' error when clicking on a view button", async (assert) => {
registry.category("services").add("error", errorService);
registry.category("error_dialogs").add("odoo.exceptions.UserError", WarningDialog);
- // remove the override in qunit.js that swallows unhandledrejection errors
- // s.t. we let the error service handle them
- const originalOnUnhandledRejection = window.onunhandledrejection;
- window.onunhandledrejection = () => {};
- registerCleanup(() => {
- window.onunhandledrejection = originalOnUnhandledRejection;
- });
await makeView({
type: "form",
@@ -12691,19 +12614,6 @@ QUnit.module("Views", (hooks) => {
registry.category("services").add("error", errorService);
registry.category("error_dialogs").add("odoo.exceptions.UserError", WarningDialog);
- const handler = (ev) => {
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
- };
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
- // remove the override in qunit.js that swallows unhandledrejection errors
- // s.t. we let the error service handle them
- const originalOnUnhandledRejection = window.onunhandledrejection;
- window.onunhandledrejection = () => {};
- registerCleanup(() => {
- window.onunhandledrejection = originalOnUnhandledRejection;
- });
serverData.views = {
"partner,false,form": ``,
@@ -12891,18 +12801,7 @@ QUnit.module("Views", (hooks) => {
);
QUnit.test("Action Button clicked with failing action", async function (assert) {
- const handler = (ev) => {
- assert.step("error");
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
- };
- // fake error service so that the odoo qunit handlers don't think that they need to handle the error
- registry.category("services").add("error", { start: () => {} });
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
- patchWithCleanup(QUnit, {
- onUnhandledRejection: () => {},
- });
+ assert.expectErrors();
class MyComponent extends Component {
setup() {
@@ -12939,7 +12838,7 @@ QUnit.module("Views", (hooks) => {
await click(target.querySelector(".oe_stat_button"));
assert.containsOnce(target, ".o_form_view .test");
- assert.verifySteps(["error"]);
+ assert.verifyErrors(["test"]);
});
QUnit.test("form view with edit='0' but create='1', existing record", async (assert) => {
@@ -13286,7 +13185,7 @@ QUnit.module("Views", (hooks) => {
arch: ``,
mockRPC(route, { method }) {
if (method === "web_save") {
- return Promise.reject(false);
+ throw makeServerError();
}
},
});
@@ -13596,12 +13495,7 @@ QUnit.module("Views", (hooks) => {
QUnit.test(
"coming to an action with an error from a form view with a dirty x2m",
async function (assert) {
- const handler = (ev) => {
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
- };
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
+ assert.expectErrors();
class TestClientAction extends Component {
setup() {
@@ -13673,6 +13567,7 @@ QUnit.module("Views", (hooks) => {
await click(target, ".test_widget button");
await nextTick();
+ assert.verifyErrors(["Something went wrong"]);
// Close ErrorDialog
await click(target, ".o_dialog .btn-close");
@@ -13689,12 +13584,7 @@ QUnit.module("Views", (hooks) => {
QUnit.test(
"coming to an action with an error from a form view with a record in creation",
async function (assert) {
- const handler = (ev) => {
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
- };
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
+ assert.expectErrors();
class TestClientAction extends Component {
setup() {
@@ -13762,6 +13652,7 @@ QUnit.module("Views", (hooks) => {
await click(target, ".test_widget button");
await nextTick();
+ assert.verifyErrors(["Something went wrong"]);
// Close ErrorDialog
await click(target, ".o_dialog .btn-close");
diff --git a/addons/web/static/tests/views/list_view_tests.js b/addons/web/static/tests/views/list_view_tests.js
index ffc58ea43e3..489eeaf5da1 100644
--- a/addons/web/static/tests/views/list_view_tests.js
+++ b/addons/web/static/tests/views/list_view_tests.js
@@ -20,7 +20,6 @@ import { RelationalModel } from "@web/model/relational_model/relational_model";
import { actionService } from "@web/webclient/actions/action_service";
import { getPickerApplyButton, getPickerCell } from "../core/datetime/datetime_test_helpers";
import { makeFakeLocalizationService, makeFakeUserService } from "../helpers/mock_services";
-import { registerCleanup } from "@web/../tests/helpers/cleanup";
import {
addRow,
click,
@@ -65,6 +64,7 @@ import {
} from "../search/helpers";
import { createWebClient, doAction, loadState } from "../webclient/helpers";
import { makeView, makeViewInDialog, setupViewRegistries } from "./helpers";
+import { makeServerError } from "../helpers/mock_server";
const fieldRegistry = registry.category("fields");
const serviceRegistry = registry.category("services");
@@ -18361,10 +18361,6 @@ QUnit.module("Views", (hooks) => {
"edit a record then select another record with a throw error when saving",
async function (assert) {
serviceRegistry.add("error", errorService);
- // need to preventDefault to remove error from console (so python test pass)
- const handler = (ev) => ev.preventDefault();
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
await makeView({
type: "list",
@@ -18376,7 +18372,7 @@ QUnit.module("Views", (hooks) => {
`,
mockRPC(route, args) {
if (args.method === "web_save") {
- throw new Error("Can't write");
+ throw makeServerError({ message: "Can't write" });
}
},
});
diff --git a/addons/web/static/tests/webclient/actions/close_action_tests.js b/addons/web/static/tests/webclient/actions/close_action_tests.js
index f6eef8e0e2f..a66cd627a6a 100644
--- a/addons/web/static/tests/webclient/actions/close_action_tests.js
+++ b/addons/web/static/tests/webclient/actions/close_action_tests.js
@@ -1,11 +1,9 @@
/** @odoo-module **/
import testUtils from "@web/../tests/legacy/helpers/test_utils";
-import { registerCleanup } from "../../helpers/cleanup";
import { click, getFixture, nextTick, patchWithCleanup } from "../../helpers/utils";
import { createWebClient, doAction, getActionManagerServerData } from "./../helpers";
-import { registry } from "@web/core/registry";
import { formView } from "@web/views/form/form_view";
import { listView } from "../../../src/views/list/list_view";
@@ -180,19 +178,8 @@ QUnit.module("ActionManager", (hooks) => {
);
QUnit.test("web client is not deadlocked when a view crashes", async function (assert) {
- assert.expect(6);
- const handler = (ev) => {
- assert.step("error");
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
- };
- // fake error service so that the odoo qunit handlers don't think that they need to handle the error
- registry.category("services").add("error", { start: () => {} });
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
- patchWithCleanup(QUnit, {
- onUnhandledRejection: () => {},
- });
+ assert.expect(4);
+ assert.expectErrors();
const readOnFirstRecordDef = testUtils.makeTestPromise();
const mockRPC = (route, { method, args, kwargs }) => {
@@ -205,10 +192,10 @@ QUnit.module("ActionManager", (hooks) => {
// open first record in form view. this will crash and will not
// display a form view
await testUtils.dom.click($(target).find(".o_list_view .o_data_cell:first"));
- assert.verifySteps([]);
readOnFirstRecordDef.reject(new Error("not working as intended"));
await nextTick();
- assert.verifySteps(["error"]);
+ assert.verifyErrors(["not working as intended"]);
+
assert.containsOnce(target, ".o_list_view", "there should still be a list view in dom");
// open another record, the read will not crash
await testUtils.dom.click(
diff --git a/addons/web/static/tests/webclient/actions/error_handling_tests.js b/addons/web/static/tests/webclient/actions/error_handling_tests.js
index 17750058f01..ddcd05a0e7f 100644
--- a/addons/web/static/tests/webclient/actions/error_handling_tests.js
+++ b/addons/web/static/tests/webclient/actions/error_handling_tests.js
@@ -2,8 +2,7 @@
import { registry } from "@web/core/registry";
import { createWebClient, doAction, getActionManagerServerData } from "./../helpers";
-import { registerCleanup } from "../../helpers/cleanup";
-import { click, getFixture, nextTick, patchWithCleanup } from "../../helpers/utils";
+import { click, getFixture, nextTick } from "../../helpers/utils";
import { errorService } from "@web/core/errors/error_service";
import { Component, xml } from "@odoo/owl";
@@ -56,23 +55,17 @@ QUnit.module("ActionManager", (hooks) => {
});
QUnit.test("error in a client action (after the first rendering)", async function (assert) {
- const handler = (ev) => {
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
- };
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
-
- patchWithCleanup(QUnit, {
- onUnhandledRejection: () => {},
- });
-
+ assert.expectErrors();
registry.category("services").add("error", errorService);
class Boom extends Component {
setup() {
this.boom = false;
}
+ get a() {
+ // a bit artificial, but makes the test firefox compliant
+ throw new Error("Cannot read properties of undefined (reading 'b')");
+ }
onClick() {
this.boom = true;
this.render();
@@ -93,5 +86,6 @@ QUnit.module("ActionManager", (hooks) => {
await nextTick();
assert.containsOnce(target, ".my_button");
assert.containsOnce(target, ".o_error_dialog");
+ assert.verifyErrors(["Cannot read properties of undefined (reading 'b')"]);
});
});
diff --git a/addons/web/static/tests/webclient/actions/load_state_tests.js b/addons/web/static/tests/webclient/actions/load_state_tests.js
index 3ef625a2655..0ddfd7d2ef1 100644
--- a/addons/web/static/tests/webclient/actions/load_state_tests.js
+++ b/addons/web/static/tests/webclient/actions/load_state_tests.js
@@ -3,7 +3,6 @@
import { browser } from "@web/core/browser/browser";
import { registry } from "@web/core/registry";
import { WebClient } from "@web/webclient/webclient";
-import { registerCleanup } from "../../helpers/cleanup";
import { makeTestEnv } from "../../helpers/mock_env";
import {
click,
@@ -741,17 +740,7 @@ QUnit.module("ActionManager", (hooks) => {
QUnit.test("initial action crashes", async (assert) => {
assert.expect(8);
-
- const handler = (ev) => {
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
- };
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
-
- patchWithCleanup(QUnit, {
- onUnhandledRejection: () => {},
- });
+ assert.expectErrors();
browser.location.hash = "#action=__test__client__action__&menu_id=1";
const ClientAction = registry.category("actions").get("__test__client__action__");
@@ -769,6 +758,7 @@ QUnit.module("ActionManager", (hooks) => {
const webClient = await createWebClient({ serverData });
assert.verifySteps(["clientAction setup"]);
await nextTick();
+ assert.expectErrors(["my error"]);
assert.containsOnce(target, ".o_error_dialog");
await click(target, ".modal-header .btn-close");
assert.containsNone(target, ".o_error_dialog");
diff --git a/addons/web/static/tests/webclient/actions/target_tests.js b/addons/web/static/tests/webclient/actions/target_tests.js
index 3ead4c79837..d825b4354fe 100644
--- a/addons/web/static/tests/webclient/actions/target_tests.js
+++ b/addons/web/static/tests/webclient/actions/target_tests.js
@@ -4,7 +4,6 @@ import testUtils from "@web/../tests/legacy/helpers/test_utils";
import { registry } from "@web/core/registry";
import { click, getFixture, patchWithCleanup, makeDeferred, nextTick } from "../../helpers/utils";
import { createWebClient, doAction, getActionManagerServerData } from "./../helpers";
-import { registerCleanup } from "../../helpers/cleanup";
import { errorService } from "@web/core/errors/error_service";
import { useService } from "@web/core/utils/hooks";
import { ClientErrorDialog } from "@web/core/errors/error_dialogs";
@@ -266,18 +265,8 @@ QUnit.module("ActionManager", (hooks) => {
});
QUnit.test("do not commit a dialog in error", async (assert) => {
- assert.expect(6);
-
- const handler = (ev) => {
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
- };
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
-
- patchWithCleanup(QUnit, {
- onUnhandledRejection: () => {},
- });
+ assert.expect(7);
+ assert.expectErrors();
class ErrorClientAction extends Component {
setup() {
@@ -333,6 +322,7 @@ QUnit.module("ActionManager", (hooks) => {
assert.ok(
target.querySelector(".modal-body .o_error_detail").textContent.includes("my error")
);
+ assert.verifyErrors(["my error"]);
await click(target, ".modal-footer .btn-primary");
assert.containsNone(target, ".modal");
diff --git a/addons/web/static/tests/webclient/actions/window_action_tests.js b/addons/web/static/tests/webclient/actions/window_action_tests.js
index cd665a9ab71..ab4f7cde175 100644
--- a/addons/web/static/tests/webclient/actions/window_action_tests.js
+++ b/addons/web/static/tests/webclient/actions/window_action_tests.js
@@ -13,7 +13,6 @@ import { useSetupAction } from "@web/webclient/actions/action_hook";
import { clearUncommittedChanges } from "@web/webclient/actions/action_service";
import testUtils from "@web/../tests/legacy/helpers/test_utils";
import { errorService } from "../../../src/core/errors/error_service";
-import { registerCleanup } from "../../helpers/cleanup";
import {
click,
clickSave,
@@ -521,29 +520,6 @@ QUnit.module("ActionManager", (hooks) => {
QUnit.test("A new form view can be reloaded after a failed one", async function (assert) {
assert.expect(5);
- /*
- * By-pass QUnit's and test's error handling because the error service needs to be active
- */
- const handler = (ev) => {
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
- };
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
-
- patchWithCleanup(QUnit, {
- onUnhandledRejection: () => {},
- });
-
- const originOnunhandledrejection = window.onunhandledrejection;
- window.onunhandledrejection = () => {};
- registerCleanup(() => {
- window.onunhandledrejection = originOnunhandledrejection;
- });
- /*
- * End By pass error handling
- */
-
const webClient = await createWebClient({ serverData });
serviceRegistry.add("error", errorService);
@@ -2127,29 +2103,6 @@ QUnit.module("ActionManager", (hooks) => {
});
QUnit.test("window action in target new fails (onchange)", async (assert) => {
- /*
- * By-pass QUnit's and test's error handling because the error service needs to be active
- */
- const handler = (ev) => {
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
- };
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
-
- patchWithCleanup(QUnit, {
- onUnhandledRejection: () => {},
- });
-
- const originOnunhandledrejection = window.onunhandledrejection;
- window.onunhandledrejection = () => {};
- registerCleanup(() => {
- window.onunhandledrejection = originOnunhandledrejection;
- });
- /*
- * End By pass error handling
- */
-
const warningOpened = makeDeferred();
class WarningDialogWait extends WarningDialog {
setup() {
@@ -2362,26 +2315,6 @@ QUnit.module("ActionManager", (hooks) => {
QUnit.test("click on breadcrumb of a deleted record", async function (assert) {
serviceRegistry.add("error", errorService);
- // In tests we catch unhandledrejection of promises rejected with something that isn't an
- // error (see tests/qunit.js). In this scenario, with the legacy basic_model, the promise
- // is rejected with undefined, so without the following lines, we can't reproduce the issue,
- // which was that the error handlers were executed in a wrong order, and one of them crashed.
- const windowUnhandledReject = window.onunhandledrejection;
- window.onunhandledrejection = null;
- registerCleanup(() => {
- window.onunhandledrejection = windowUnhandledReject;
- });
-
- const handler = (ev) => {
- // need to preventDefault to remove error from console (so python test pass)
- ev.preventDefault();
- };
- window.addEventListener("unhandledrejection", handler);
- registerCleanup(() => window.removeEventListener("unhandledrejection", handler));
- patchWithCleanup(QUnit, {
- onUnhandledRejection: () => {},
- });
-
serverData.views["partner,false,form"] = `