From 438c6efdd74d8891d7ca1698f9eb8d015049e2f7 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 28 Apr 2021 12:01:56 +0000 Subject: [PATCH 01/14] [IMP] core: JS test runner Emit JS warnings as Python warnings, otherwise it's a pain in the ass to identify the t-raw messages (they get lost in the INFO spam). Also just log exceptions when looking for specific messages instead of re-raising them: if the pipe from chrome is full of exception reports, the runner may blow its stack as it looks for the screenshot message: on the first it takes a screenshot, then looks for the screenshot message, finds an exception, takes a screenshot, looks for a screenshot message, finds an exception, takes a screenshot, looks for a s... --- odoo/tests/common.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/odoo/tests/common.py b/odoo/tests/common.py index c0040c37000..28a2e5c8e59 100644 --- a/odoo/tests/common.py +++ b/odoo/tests/common.py @@ -1051,11 +1051,22 @@ class ChromeBrowser(): res['success'] = 'test successful' in message if res.get('method') == 'Runtime.exceptionThrown': - exception_details = res['params']['exceptionDetails'] - descr = exception_details.get('exception', {}).get('description') - self.take_screenshot() - self._save_screencast() - raise ChromeBrowserException(descr or pprint.pformat(exception_details)) + details = res['params']['exceptionDetails'] + message = details['text'] + exception = details.get('exception') + if exception: + message += str(self._from_remoteobject(exception)) + details['type'] = 'trace' # fake this so _format_stack works + stack = ''.join(self._format_stack(details)) + if stack: + message += '\n' + stack + + if raise_log_error: + self.take_screenshot() + self._save_screencast() + raise ChromeBrowserException(message) + else: + self._logger.getChild('browser').error(message) return res @@ -1063,7 +1074,7 @@ class ChromeBrowser(): 'debug': logging.DEBUG, 'log': logging.INFO, 'info': logging.INFO, - 'warning': logging.INFO, # logging.WARNING, + 'warning': logging.WARNING, 'error': logging.ERROR, # TODO: what do with # dir, dirxml, table, trace, clear, startGroup, startGroupCollapsed, From c6855cdcf844fb49cdf8aae7bacecca1fef01b88 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 23 Apr 2021 05:38:27 +0000 Subject: [PATCH 02/14] [IMP] qunit: avoid splitting `console.error` calls The Chrome runner may only show the first one, which may or may not be useful on its own. --- addons/web/static/tests/helpers/cleanup.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/addons/web/static/tests/helpers/cleanup.js b/addons/web/static/tests/helpers/cleanup.js index 814410d0392..d68bc467ee3 100644 --- a/addons/web/static/tests/helpers/cleanup.js +++ b/addons/web/static/tests/helpers/cleanup.js @@ -79,24 +79,18 @@ QUnit.on("OdooAfterTestHook", function (info) { (e) => e.tagName === bodyChild.tagName && bodyChild.getAttribute(e.attr) === e.value ); if (!tolerated) { - console.error(`Test ${info.moduleName} > ${info.testName}`); console.error( - "Body still contains undesirable elements:" + - "\nInvalid element:\n" + - bodyChild.outerHTML - ); +`Test ${info.moduleName} > ${info.testName}: body still contains undesirable elements: + ${bodyChild.outerHTML}`); QUnit.pushFailure(`Body still contains undesirable elements`); } if (!tolerated || !tolerated.keep) { toRemove.push(bodyChild); } } - // check for leftovers in #qunit-fixture + // cleanup leftovers in #qunit-fixture const qunitFixture = document.getElementById("qunit-fixture"); if (qunitFixture.children.length) { - // console.error('#qunit-fixture still contains elements:' + - // '\n#qunit-fixture HTML:\n' + qunitFixture.outerHTML); - // QUnit.pushFailure(`#qunit-fixture still contains elements`); toRemove.push(...qunitFixture.children); } // remove unwanted elements if not in debug From 9528fd350f43a0dd4c9cbed8f956a273a173bb3d Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 21 Jun 2021 12:42:56 +0000 Subject: [PATCH 03/14] [FIX] qunit: suppress ResizeObserver error The error is (apparently) benign and already suppressed in some parts of the system, however it can (apparently) trigger locally during some tests, causing the test to fail as the error is caught and converted to a failure by QUnit. Sadly QUnit does not offer a proper hook for this, so it has to be suppressed by wrapping the existing handler and only calling it for other errors. --- addons/web/static/tests/qunit.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/addons/web/static/tests/qunit.js b/addons/web/static/tests/qunit.js index d66bce60f8a..6203facd223 100644 --- a/addons/web/static/tests/qunit.js +++ b/addons/web/static/tests/qunit.js @@ -363,6 +363,13 @@ }); } }); + const oldError = QUnit.onError; + QUnit.onError = err => { + if (err.message === 'ResizeObserver loop limit exceeded') { + return true; + } + return oldError(err); + } // ----------------------------------------------------------------------------- // Add sort button From 29de1ef72b8c4cb81019dfac0192666df304a35e Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 20 May 2021 06:57:08 +0000 Subject: [PATCH 04/14] [IMP] web: reduce warning spam, only show rpc error warning in debug Trigger a *lot* of spam while running tests It's not great that this is now disabled: * some cases are mistakes in the test e.g. RPC not properly setup, they should really be fixed * others are literally testing error responses, the logging should be suppressed instead Ideal scenario would probably be to upgrade this to `error` and have an API of some sort to suppress it on a per-test basis (not unlike `@mute_logger` on the Python side). --- addons/web/static/tests/legacy/helpers/mock_server.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/addons/web/static/tests/legacy/helpers/mock_server.js b/addons/web/static/tests/legacy/helpers/mock_server.js index 1a6f2d80b4c..0cea8e11fbf 100644 --- a/addons/web/static/tests/legacy/helpers/mock_server.js +++ b/addons/web/static/tests/legacy/helpers/mock_server.js @@ -166,7 +166,15 @@ var MockServer = Class.extend({ var message = result && result.message; var event = result && result.event; var errorString = JSON.stringify(message || false); - console.warn('%c[rpc] response (error) ' + route, 'color: orange; font-weight: bold;', JSON.parse(errorString)); + if (debug) { + console.warn( + '%c[rpc] response (error) %s%s, during test %s', + 'color: orange; font-weight: bold;', + route, + message != null && ` -> ${errorString}`, + JSON.stringify(QUnit.config.current.testName) + ); + } return Promise.reject({message: errorString, event: event || $.Event()}); }); From 053285afdc661100552ee17b357a120ec8f4ea22 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 10 Jun 2021 07:22:03 +0000 Subject: [PATCH 05/14] [FIX] web: momentjs warnings * Without an explicit format string, moment() should be called with ISO date(times). * Correctly destroy all test locales (`zz` was not destroyed at all, and `englishForTest` was double-destroyed instead of destroying `frenchForTests`). * Avoid creating a moment object from the value `false` in date(time) fields. * Disable the warning entirely in dates_tests, the contents are super messy and weird. --- .../static/tests/test_leave_stats_widget.js | 4 ++-- .../src/legacy/js/fields/basic_fields.js | 8 ++++---- .../web/static/tests/core/l10n/dates_tests.js | 6 +++++- .../legacy/components/datepicker_tests.js | 19 ++++++++++--------- .../tests/legacy/views/calendar_tests.js | 1 + 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/addons/hr_holidays/static/tests/test_leave_stats_widget.js b/addons/hr_holidays/static/tests/test_leave_stats_widget.js index 157459dc61d..e7d2299326d 100644 --- a/addons/hr_holidays/static/tests/test_leave_stats_widget.js +++ b/addons/hr_holidays/static/tests/test_leave_stats_widget.js @@ -64,8 +64,8 @@ odoo.define('hr_holidays.leave_stats_widget_tests', function (require) { id: 13, employee_id: 100, department_id: 11, - date_from: "2016-10-2 09:00:00", - date_to: "2016-10-2 18:00:00", + date_from: "2016-10-02 09:00:00", + date_to: "2016-10-02 18:00:00", holiday_status_id: 55, state: 'validate', number_of_days: 1, diff --git a/addons/web/static/src/legacy/js/fields/basic_fields.js b/addons/web/static/src/legacy/js/fields/basic_fields.js index 16e433da52b..3d4df0cb0a1 100644 --- a/addons/web/static/src/legacy/js/fields/basic_fields.js +++ b/addons/web/static/src/legacy/js/fields/basic_fields.js @@ -926,8 +926,8 @@ var FieldDate = InputField.extend({ * @returns {boolean} */ _isSameValue: function (value) { - if (value === false) { - return this.value === false; + if (this.value === false || value === false) { + return this.value === value; } return value.isSame(this.value, 'day'); }, @@ -1005,8 +1005,8 @@ var FieldDateTime = FieldDate.extend({ * @private */ _isSameValue: function (value) { - if (value === false) { - return this.value === false; + if (this.value === false || value === false) { + return this.value === value; } return value.isSame(this.value); }, diff --git a/addons/web/static/tests/core/l10n/dates_tests.js b/addons/web/static/tests/core/l10n/dates_tests.js index 6395b340236..e535bc12688 100644 --- a/addons/web/static/tests/core/l10n/dates_tests.js +++ b/addons/web/static/tests/core/l10n/dates_tests.js @@ -59,7 +59,11 @@ function runTestSet(assert, testSet, options) { } } -QUnit.module("utils", () => { + +QUnit.module("utils", { + before() {moment.suppressDeprecationWarnings = true;}, + after() {moment.suppressDeprecationWarnings = false;}, + }, () => { QUnit.module("dates"); QUnit.test("formatDateTime", async (assert) => { diff --git a/addons/web/static/tests/legacy/components/datepicker_tests.js b/addons/web/static/tests/legacy/components/datepicker_tests.js index 643bcdb5188..4ab0da28f5d 100644 --- a/addons/web/static/tests/legacy/components/datepicker_tests.js +++ b/addons/web/static/tests/legacy/components/datepicker_tests.js @@ -15,9 +15,10 @@ odoo.define('web.datepicker_tests', function (require) { assert.expect(8); const picker = await createComponent(DatePicker, { - props: { date: moment('01/09/1997') }, + props: { date: moment('1997-01-09') }, }); + assert.containsOnce(picker, 'input.o_input.o_datepicker_input'); assert.containsOnce(picker, 'span.o_datepicker_button'); assert.containsNone(document.body, 'div.bootstrap-datetimepicker-widget'); @@ -46,7 +47,7 @@ odoo.define('web.datepicker_tests', function (require) { assert.expect(5); const picker = await createComponent(DatePicker, { - props: { date: moment('01/09/1997') }, + props: { date: moment('1997-01-09') }, intercepts: { 'datetime-changed': ev => { assert.step('datetime-changed'); @@ -106,7 +107,7 @@ odoo.define('web.datepicker_tests', function (require) { assert.verifySteps(['datetime-changed']); moment.locale(originalLocale); - moment.updateLocale('englishForTest', null); + moment.updateLocale('frenchForTests', null); picker.destroy(); }); @@ -115,7 +116,7 @@ odoo.define('web.datepicker_tests', function (require) { assert.expect(5); const picker = await createComponent(DatePicker, { - props: { date: moment('01/09/1997') }, + props: { date: moment('1997-01-09') }, intercepts: { 'datetime-changed': ev => { assert.step('datetime-changed'); @@ -148,7 +149,7 @@ odoo.define('web.datepicker_tests', function (require) { testUtils.patch(time, { getLangDateFormat: () => "YYYY/MM/DD" }); const picker = await createComponent(DatePicker, { - props: { date: moment('01/09/1997') }, + props: { date: moment('1997-01-09') }, }); const input = picker.el.querySelector('.o_datepicker_input'); @@ -169,7 +170,7 @@ odoo.define('web.datepicker_tests', function (require) { assert.expect(11); const picker = await createComponent(DateTimePicker, { - props: { date: moment('01/09/1997 12:30:01') }, + props: { date: moment('1997-01-09 12:30:01') }, }); assert.containsOnce(picker, 'input.o_input.o_datepicker_input'); @@ -204,7 +205,7 @@ odoo.define('web.datepicker_tests', function (require) { assert.expect(5); const picker = await createComponent(DateTimePicker, { - props: { date: moment('01/09/1997 12:30:01') }, + props: { date: moment('1997-01-09 12:30:01') }, intercepts: { 'datetime-changed': ev => { assert.step('datetime-changed'); @@ -292,7 +293,7 @@ odoo.define('web.datepicker_tests', function (require) { assert.expect(9); const picker = await createComponent(DateTimePicker, { - props: { date: moment('01/09/1997 12:30:01') }, + props: { date: moment('1997-01-09 12:30:01') }, intercepts: { 'datetime-changed': ev => { assert.step('datetime-changed'); @@ -332,7 +333,7 @@ odoo.define('web.datepicker_tests', function (require) { testUtils.patch(time, { getLangDatetimeFormat: () => "hh:mm:ss YYYY/MM/DD" }); const picker = await createComponent(DateTimePicker, { - props: { date: moment('01/09/1997 12:30:01') }, + props: { date: moment('1997-01-09 12:30:01') }, }); const input = picker.el.querySelector('.o_datepicker_input'); diff --git a/addons/web/static/tests/legacy/views/calendar_tests.js b/addons/web/static/tests/legacy/views/calendar_tests.js index 753e271c23e..c5beffc08c3 100644 --- a/addons/web/static/tests/legacy/views/calendar_tests.js +++ b/addons/web/static/tests/legacy/views/calendar_tests.js @@ -3369,6 +3369,7 @@ QUnit.module('Views', { 'The day should be in the given locale specific format'); moment.locale(initialLocale); + moment.defineLocale('zz', null); calendar.destroy(); }); From 1e6de40b78d1fac70a5aa4b5a73c2e604f8b983a Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 8 Jun 2021 13:25:21 +0000 Subject: [PATCH 06/14] [IMP] web: downgrade warning messages to info Two internal warnings are features which literally are not (entirely) implemented, the tests can't be fixed to avoid them. Also augmented the log messages with which test triggered the log, as it's very hard to debug the issue otherwise. As for the qweb debug mode warning, there's no way to disable it easily because multiple tours explicitly opt into debug mode (with good reasons), so it's not enough to just bypass the `mode` setter in the test setup helpers (test_main in POS and main_tests in web), there would also need to be special workarounds in the 4 modules which set `owl.config.mode` based on the session's debug mode. I don't know that this warning is even useful, it defaults to `false` so the only situation in which this would be relevant would be for a third-party to use Owl *and* explicitly enable the debug mode *and* forget to remove it when deploying to production *and* look at their console. --- addons/web/static/lib/owl/owl.js | 6 ++++-- addons/web/static/tests/helpers/mock_server.js | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/addons/web/static/lib/owl/owl.js b/addons/web/static/lib/owl/owl.js index 29aa09cebb5..fc748477910 100644 --- a/addons/web/static/lib/owl/owl.js +++ b/addons/web/static/lib/owl/owl.js @@ -2818,8 +2818,10 @@ set(mode) { QWeb.dev = mode === "dev"; if (QWeb.dev) { - const url = `https://github.com/odoo/owl/blob/master/doc/reference/config.md#mode`; - console.warn(`Owl is running in 'dev' mode. This is not suitable for production use. See ${url} for more information.`); + console.info(`Owl is running in 'dev' mode. + +This is not suitable for production use. +See https://github.com/odoo/owl/blob/master/doc/reference/config.md#mode for more information.`); } else { console.log(`Owl is now running in 'prod' mode.`); diff --git a/addons/web/static/tests/helpers/mock_server.js b/addons/web/static/tests/helpers/mock_server.js index 34058a7955f..f677b3e7298 100644 --- a/addons/web/static/tests/helpers/mock_server.js +++ b/addons/web/static/tests/helpers/mock_server.js @@ -242,7 +242,7 @@ export class MockServer { // TODO // const pyevalContext = window.py.dict.fromJSON(context || {}); // var v = pyUtils.py_eval(mod, {context: pyevalContext}) ? true : false; - console.warn("MockServer: naive parse of modifier value"); + console.info("MockServer: naive parse of modifier value in", QUnit.config.current.testName); const v = JSON.parse(mod); if (inTreeView && !inListHeader && attr === "invisible") { modifiers.column_invisible = v; @@ -808,7 +808,7 @@ export class MockServer { res[groupByField] = val; } if (field.type === "date" && val) { - console.warn("Mock Server: read group not fully implemented (moment stuff)"); + console.info("Mock Server: read group not fully implemented (moment stuff) in", QUnit.config.current.testName); // const aggregateFunction = groupByField.split(':')[1]; // let startDate; // let endDate; From 46bc0b110e76a542d056c754bd0c6f098b28ab41 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 15 Jun 2021 13:08:20 +0000 Subject: [PATCH 07/14] [FIX] web_tour: warning during tip consumption test Tip consumption is an RPC request. Because the test did not mock the model or RPC, a warning would be triggered by the mock server. * update `createTourManager` to forward parameters outside its very own to the mock environment setup * pass in a `data` to set up our model, including `fields` because for some reason the default RPC mocking is quite cross when a model doesn't have fields --- addons/web_tour/static/tests/tour_manager_tests.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/addons/web_tour/static/tests/tour_manager_tests.js b/addons/web_tour/static/tests/tour_manager_tests.js index 26ebaeb398c..b4e994733ad 100644 --- a/addons/web_tour/static/tests/tour_manager_tests.js +++ b/addons/web_tour/static/tests/tour_manager_tests.js @@ -14,16 +14,17 @@ odoo.define('web_tour.tour_manager_tests', async function (require) { /** * Create a widget and a TourManager instance with a list of given Tour objects. - * @see TourManager.register() for more details on the Tours registry system. - * @param {Object} params + * @see `TourManager.register()` for more details on the Tours registry system. + * @param {Object} params aside from the parameters defined below, passed + * to {@see addMockEnvironment}. * @param {string[]} [params.consumed_tours] - * @param {boolean} [params.debug] + * @param {boolean} [params.debug] also passed along * @param {boolean} [params.disabled] * @param {string} params.template inner HTML content of the widget * @param {Object[]} params.tours { {string} name, {Object} option, {Object[]} steps } */ - async function createTourManager({ consumed_tours, debug, disabled, template, tours }) { - const parent = await testUtils.createParent({ debug }); + async function createTourManager({ consumed_tours, disabled, template, tours, ...params }) { + const parent = await testUtils.createParent(params); const tourManager = new TourManager(parent, consumed_tours, disabled); tourManager.running_step_delay = 0; for (const { name, options, steps } of tours) { @@ -34,7 +35,7 @@ odoo.define('web_tour.tour_manager_tests', async function (require) { tourManager.destroy = _destroy; parent.destroy(); }; - await parent.prependTo(testUtils.prepareTarget(debug)); + await parent.prependTo(testUtils.prepareTarget(params.debug)); parent.el.innerHTML = template; await tourManager._register_all(true); // Wait for possible tooltips to be loaded and appended. @@ -75,6 +76,7 @@ odoo.define('web_tour.tour_manager_tests', async function (require) { assert.expect(5); const tourManager = await createTourManager({ + data: { 'web_tour.tour': { fields: {}, consume() {} } }, template: ` From 3985edd5daad9f8f9185a8d097a729cd942f81da Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 21 Jun 2021 10:21:54 +0000 Subject: [PATCH 08/14] [FIX] web: missing action id warnings * Add test name when logging missing action ids, makes finding out which test causes the issue much simpler. * Suppress the warning emission in the one remaining test which triggers it, as testing invalid action IDs is exactly the purpose of the test. --- addons/web/static/tests/helpers/mock_server.js | 2 +- addons/web/static/tests/legacy/helpers/mock_server.js | 2 +- addons/web/static/tests/webclient/actions/misc_tests.js | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/addons/web/static/tests/helpers/mock_server.js b/addons/web/static/tests/helpers/mock_server.js index f677b3e7298..318c48103cf 100644 --- a/addons/web/static/tests/helpers/mock_server.js +++ b/addons/web/static/tests/helpers/mock_server.js @@ -498,7 +498,7 @@ export class MockServer { if (!action) { // when the action doesn't exist, the real server doesn't crash, it // simply returns false - console.warn("No action found for ID " + kwargs.action_id); + console.warn(`No action found for ID ${kwargs.action_id} during test ${QUnit.config.current.testName}`); } return action || false; } diff --git a/addons/web/static/tests/legacy/helpers/mock_server.js b/addons/web/static/tests/legacy/helpers/mock_server.js index 0cea8e11fbf..2ce6392b56b 100644 --- a/addons/web/static/tests/legacy/helpers/mock_server.js +++ b/addons/web/static/tests/legacy/helpers/mock_server.js @@ -1160,7 +1160,7 @@ var MockServer = Class.extend({ if (!action) { // when the action doesn't exist, the real server doesn't crash, it // simply returns false - console.warn("No action found for ID " + kwargs.action_id); + console.warn(`No action found for ID ${kwargs.action_id} during test ${QUnit.config.current.testName} (legacy)`); } return action || false; }, diff --git a/addons/web/static/tests/webclient/actions/misc_tests.js b/addons/web/static/tests/webclient/actions/misc_tests.js index 3cde098f53d..578854c4a11 100644 --- a/addons/web/static/tests/webclient/actions/misc_tests.js +++ b/addons/web/static/tests/webclient/actions/misc_tests.js @@ -6,7 +6,7 @@ import core from "web.core"; import testUtils from "web.test_utils"; import Widget from "web.Widget"; import { makeTestEnv } from "../../helpers/mock_env"; -import { legacyExtraNextTick, patchWithCleanup } from "../../helpers/utils"; +import {hushConsole, legacyExtraNextTick, patchWithCleanup} from "../../helpers/utils"; import { createWebClient, doAction, @@ -97,6 +97,7 @@ QUnit.module("ActionManager", (hooks) => { QUnit.test("properly handle case when action id does not exist", async (assert) => { assert.expect(2); const webClient = await createWebClient({ serverData }); + patchWithCleanup(window, {console: hushConsole}, {pure: true}); patchWithCleanup(webClient.env.services.notification, { add(message) { assert.strictEqual(message, "No action with id '4448' could be found"); From de5aceb88ea004a938f5077d55d1b51043c68c0c Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 21 Apr 2021 12:21:09 +0000 Subject: [PATCH 09/14] [IMP] web: test reliability This test sometimes fails locally. Updating it to be a bit more modern also seems to make it more reliable (also moved the delay between the drag & drop operation & the steps checking as it seems more logical, but the reliability issues had disappeared before that). --- .../relational_fields/field_one2many_tests.js | 78 +++++++------------ 1 file changed, 30 insertions(+), 48 deletions(-) diff --git a/addons/web/static/tests/legacy/fields/relational_fields/field_one2many_tests.js b/addons/web/static/tests/legacy/fields/relational_fields/field_one2many_tests.js index 9f96a0d7afa..859a2e94460 100644 --- a/addons/web/static/tests/legacy/fields/relational_fields/field_one2many_tests.js +++ b/addons/web/static/tests/legacy/fields/relational_fields/field_one2many_tests.js @@ -1,6 +1,7 @@ odoo.define('web.field_one_to_many_tests', function (require) { "use strict"; +const {delay} = require('web.concurrency'); var AbstractField = require('web.AbstractField'); var AbstractStorageService = require('web.AbstractStorageService'); const ControlPanel = require('web.ControlPanel'); @@ -1659,28 +1660,26 @@ QUnit.module('fields', {}, function () { }); QUnit.test('embedded one2many with handle widget with minimum setValue calls', async function (assert) { - var done = assert.async(); assert.expect(20); - this.data.turtle.records[0].turtle_int = 6; this.data.turtle.records.push({ id: 4, turtle_int: 20, turtle_foo: "a1", }, { - id: 5, - turtle_int: 9, - turtle_foo: "a2", - }, { - id: 6, - turtle_int: 2, - turtle_foo: "a3", - }, { - id: 7, - turtle_int: 11, - turtle_foo: "a4", - }); + id: 5, + turtle_int: 9, + turtle_foo: "a2", + }, { + id: 6, + turtle_int: 2, + turtle_foo: "a3", + }, { + id: 7, + turtle_int: 11, + turtle_foo: "a4", + }); this.data.partner.records[0].turtles = [1, 2, 3, 4, 5, 6, 7]; var form = await createView({ @@ -1688,18 +1687,12 @@ QUnit.module('fields', {}, function () { model: 'partner', data: this.data, arch: '
' + - '' + - '' + - '' + '' + '' + '' + '' + '' + '' + - '' + - '' + - '' + '
', res_id: 1, }); @@ -1715,40 +1708,29 @@ QUnit.module('fields', {}, function () { [5, 1, 'top', ['7', '6', '1', '2', '5']], // move the penultimate to the second line [2, 5, 'bottom', ['1', '2', '5', '6']], // move the third to the penultimate line ]; - async function dragAndDrop() { - var pos = positions.shift(); - + for (const [source, target, position, steps] of positions) { await testUtils.dom.dragAndDrop( - form.$('.ui-sortable-handle').eq(pos[0]), - form.$('tbody tr').eq(pos[1]), - { position: pos[2] } + form.$('.ui-sortable-handle').eq(source), + form.$('tbody tr').eq(target), + {position: position} ); - assert.verifySteps(pos[3], + await delay(10); + + assert.verifySteps(steps, "sequences values should be apply from the begin index to the drop index"); - - if (positions.length) { - - setTimeout(dragAndDrop, 10); - - } else { - - assert.deepEqual(_.pluck(form.model.get(form.handle).data.turtles.data, 'data'), [ - { id: 3, turtle_foo: "kawa", turtle_int: 2 }, - { id: 7, turtle_foo: "a4", turtle_int: 3 }, - { id: 1, turtle_foo: "yop", turtle_int: 4 }, - { id: 2, turtle_foo: "blip", turtle_int: 5 }, - { id: 5, turtle_foo: "a2", turtle_int: 6 }, - { id: 6, turtle_foo: "a3", turtle_int: 7 }, - { id: 4, turtle_foo: "a1", turtle_int: 8 } - ], "sequences must be apply correctly"); - - form.destroy(); - done(); - } } + assert.deepEqual(_.pluck(form.model.get(form.handle).data.turtles.data, 'data'), [ + { id: 3, turtle_foo: "kawa", turtle_int: 2 }, + { id: 7, turtle_foo: "a4", turtle_int: 3 }, + { id: 1, turtle_foo: "yop", turtle_int: 4 }, + { id: 2, turtle_foo: "blip", turtle_int: 5 }, + { id: 5, turtle_foo: "a2", turtle_int: 6 }, + { id: 6, turtle_foo: "a3", turtle_int: 7 }, + { id: 4, turtle_foo: "a1", turtle_int: 8 } + ], "sequences must be apply correctly"); - dragAndDrop(); + form.destroy(); }); QUnit.test('embedded one2many (editable list) with handle widget', async function (assert) { From b39c5072f7bb490f7d23fabc4f8930d97bbe94a8 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 11 Jun 2021 08:25:19 +0000 Subject: [PATCH 10/14] [FIX] web: avoid warning during qweb tests One of the qweb tests checks that in a t-set @t-value takes priority over body contents. However this construct also triggers a warning when invoked. Mock out `window.console` during qweb tests, this suppresses that warning. --- addons/web/static/tests/helpers/utils.js | 5 +++++ addons/web/static/tests/legacy/qweb_tests.js | 9 ++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/addons/web/static/tests/helpers/utils.js b/addons/web/static/tests/helpers/utils.js index f01c79b991b..cdf3bf7b88c 100644 --- a/addons/web/static/tests/helpers/utils.js +++ b/addons/web/static/tests/helpers/utils.js @@ -208,3 +208,8 @@ export async function legacyExtraNextTick() { export function mockDownload(cb) { patchWithCleanup(download, { _download: cb }); } + +export const hushConsole = Object.create(null); +for(const propName of Object.keys(window.console)) { + hushConsole[propName] = () => {} +} diff --git a/addons/web/static/tests/legacy/qweb_tests.js b/addons/web/static/tests/legacy/qweb_tests.js index fda72e2392b..dd2b0c527ec 100644 --- a/addons/web/static/tests/legacy/qweb_tests.js +++ b/addons/web/static/tests/legacy/qweb_tests.js @@ -2,6 +2,7 @@ odoo.define('web.qweb_tests', function (require) { "use strict"; var qwebPath = '/web/static/lib/qweb/'; +const {hushConsole} = require('@web/../tests/helpers/utils'); function trim(s) { return s.replace(/(^\s+|\s+$)/g, ''); @@ -63,7 +64,13 @@ function loadTest(assert, template, context) { return prom; } -QUnit.module('QWeb', {}, function () { +QUnit.module('QWeb', { + before() { + this.oldConsole = window.console; + window.console = hushConsole; + }, + after() {window.console = this.oldConsole;} +}, function () { QUnit.test('Output', function (assert) { loadTest(assert, 'qweb-test-output.xml'); }); From 7d90cfac55aa1c8f303d9cb3426ed9666fd195ae Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 11 Jun 2021 07:17:12 +0000 Subject: [PATCH 11/14] [FIX] web: SearchPanel warnings Can't have a searchpanel with both: * a filter (`field[@select='multi']`) with a `@domain` * *and* a category (`field[not(@select='multi')]`) with `@enable_counters` That specific case will trigger a warning and the counters being disabled. Fix them. Oddly enough the only cases seem to be in tests... --- addons/web/static/tests/legacy/views/search_panel_tests.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/web/static/tests/legacy/views/search_panel_tests.js b/addons/web/static/tests/legacy/views/search_panel_tests.js index d50ecea676d..9a745ad6760 100644 --- a/addons/web/static/tests/legacy/views/search_panel_tests.js +++ b/addons/web/static/tests/legacy/views/search_panel_tests.js @@ -1144,7 +1144,7 @@ QUnit.module('Views', { "partner,false,search": ` - + `, @@ -2065,7 +2065,7 @@ QUnit.module('Views', { 'partner,false,search': ` - + `, @@ -4135,7 +4135,7 @@ QUnit.module('Views', { 'partner,false,search': ` - + `, From 32062a3bbb3a4b309a71d24cfe76cf86a45144b7 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 8 Jun 2021 12:36:04 +0000 Subject: [PATCH 12/14] [FIX] board, bus, web: replace deprecated test-utils calls A number of functions from `web.test_utils` have been deprecated at the module root and should be called through submodules. Fix a bunch of remaining cases. Also add a few missing `await`s on `triggerMouseEvent` calls. Don't bother rewriting the imports in unpacking style as for most updating the imports is unnecessary. Do so for `field_one2many_tests.js` where we have to rewrite the imports anyway: * recursively import controlPanel, createView, mock.patch and mock.unpatch * remove the aliasing of controlPanel to cpHelpers --- addons/board/static/tests/dashboard_tests.js | 4 +-- addons/bus/static/tests/bus_tests.js | 8 +++--- .../legacy/components/datepicker_tests.js | 8 +++--- .../tests/legacy/fields/basic_fields_tests.js | 8 +++--- .../relational_fields/field_one2many_tests.js | 4 +-- .../legacy/fields/relational_fields_tests.js | 4 +-- .../tests/legacy/views/calendar_tests.js | 26 +++++++++---------- .../static/tests/legacy/views/kanban_tests.js | 2 +- .../widgets/model_field_selector_tests.js | 2 +- 9 files changed, 33 insertions(+), 33 deletions(-) diff --git a/addons/board/static/tests/dashboard_tests.js b/addons/board/static/tests/dashboard_tests.js index 905a0ff87f1..1473823946d 100644 --- a/addons/board/static/tests/dashboard_tests.js +++ b/addons/board/static/tests/dashboard_tests.js @@ -702,7 +702,7 @@ QUnit.test('dashboard intercepts custom events triggered by sub controllers', as QUnit.test("save actions to dashboard", async function (assert) { assert.expect(6); - testUtils.patch(ListController, { + testUtils.mock.patch(ListController, { getOwnedQueryParams: function () { var result = this._super.apply(this, arguments); result.context = { @@ -773,7 +773,7 @@ QUnit.test("save actions to dashboard", async function (assert) { await testUtils.fields.editInput($(".o_add_to_board input"), "a name"); await testUtils.dom.click($(".o_add_to_board div button")); - testUtils.unpatch(ListController); + testUtils.mock.unpatch(ListController); }); QUnit.test("save two searches to dashboard", async function (assert) { diff --git a/addons/bus/static/tests/bus_tests.js b/addons/bus/static/tests/bus_tests.js index 449e3ba2c93..90bc31dcc61 100644 --- a/addons/bus/static/tests/bus_tests.js +++ b/addons/bus/static/tests/bus_tests.js @@ -316,7 +316,7 @@ QUnit.module('Bus', { assert.expect(5); let id = 1; - testUtils.patch(CrossTabBus, { + testUtils.mock.patch(CrossTabBus, { init: function () { this._super.apply(this, arguments); this.__tabId__ = id++; @@ -333,7 +333,7 @@ QUnit.module('Bus', { let pollPromise; const parentTab1 = new Widget(); - await testUtils.addMockEnvironment(parentTab1, { + await testUtils.mock.addMockEnvironment(parentTab1, { data: {}, services: { local_storage: LocalStorageServiceMock, @@ -350,7 +350,7 @@ QUnit.module('Bus', { } }); const parentTab2 = new Widget(); - await testUtils.addMockEnvironment(parentTab2, { + await testUtils.mock.addMockEnvironment(parentTab2, { data: {}, services: { local_storage: LocalStorageServiceMock, @@ -382,7 +382,7 @@ QUnit.module('Bus', { "Tab 2: addChannel beta", ]); - testUtils.unpatch(CrossTabBus); + testUtils.mock.unpatch(CrossTabBus); parentTab1.destroy(); parentTab2.destroy(); }); diff --git a/addons/web/static/tests/legacy/components/datepicker_tests.js b/addons/web/static/tests/legacy/components/datepicker_tests.js index 4ab0da28f5d..78908bd911f 100644 --- a/addons/web/static/tests/legacy/components/datepicker_tests.js +++ b/addons/web/static/tests/legacy/components/datepicker_tests.js @@ -147,7 +147,7 @@ odoo.define('web.datepicker_tests', function (require) { QUnit.test("Date format is correctly set", async function (assert) { assert.expect(2); - testUtils.patch(time, { getLangDateFormat: () => "YYYY/MM/DD" }); + testUtils.mock.patch(time, { getLangDateFormat: () => "YYYY/MM/DD" }); const picker = await createComponent(DatePicker, { props: { date: moment('1997-01-09') }, }); @@ -161,7 +161,7 @@ odoo.define('web.datepicker_tests', function (require) { assert.strictEqual(input.value, '1997/01/09'); picker.destroy(); - testUtils.unpatch(time); + testUtils.mock.unpatch(time); }); QUnit.module('DateTimePicker'); @@ -331,7 +331,7 @@ odoo.define('web.datepicker_tests', function (require) { QUnit.test("Date time format is correctly set", async function (assert) { assert.expect(2); - testUtils.patch(time, { getLangDatetimeFormat: () => "hh:mm:ss YYYY/MM/DD" }); + testUtils.mock.patch(time, { getLangDatetimeFormat: () => "hh:mm:ss YYYY/MM/DD" }); const picker = await createComponent(DateTimePicker, { props: { date: moment('1997-01-09 12:30:01') }, }); @@ -345,7 +345,7 @@ odoo.define('web.datepicker_tests', function (require) { assert.strictEqual(input.value, '12:30:01 1997/01/09'); picker.destroy(); - testUtils.unpatch(time); + testUtils.mock.unpatch(time); }); }); }); diff --git a/addons/web/static/tests/legacy/fields/basic_fields_tests.js b/addons/web/static/tests/legacy/fields/basic_fields_tests.js index 04d94321145..fa7ed263804 100644 --- a/addons/web/static/tests/legacy/fields/basic_fields_tests.js +++ b/addons/web/static/tests/legacy/fields/basic_fields_tests.js @@ -3910,7 +3910,7 @@ QUnit.module('basic_fields', { assert.strictEqual($('.bootstrap-datetimepicker-widget:visible').length, 0, "datepicker should be closed initially"); - testUtils.openDatepicker(form.$('.o_datepicker')); + testUtils.dom.openDatepicker(form.$('.o_datepicker')); assert.strictEqual($('.bootstrap-datetimepicker-widget:visible').length, 1, "datepicker should be opened"); @@ -4375,7 +4375,7 @@ QUnit.module('basic_fields', { var dateViewForm = form.$('.o_field_date').text(); await testUtils.dom.click(form.$buttons.find('.o_form_button_edit')); - await testUtils.openDatepicker(form.$('.o_datepicker')); + await testUtils.dom.openDatepicker(form.$('.o_datepicker')); assert.strictEqual(form.$('.o_datepicker_input').val(), dateViewForm, "input date field should be the same as it was in the view form"); @@ -7564,7 +7564,7 @@ QUnit.module('basic_fields', { var top = $progressBarEl.offset().top + 5; var left = $progressBarEl.offset().left + 5; try { - testUtils.triggerPositionalMouseEvent(left, top, "click"); + testUtils.dom.triggerPositionalMouseEvent(left, top, "click"); } catch (e) { form.destroy(); $view.remove(); @@ -7611,7 +7611,7 @@ QUnit.module('basic_fields', { var top = $progressBarEl.offset().top + 5; var left = $progressBarEl.offset().left + 5; try { - testUtils.triggerPositionalMouseEvent(left, top, "click"); + testUtils.dom.triggerPositionalMouseEvent(left, top, "click"); } catch (e) { form.destroy(); $view.remove(); diff --git a/addons/web/static/tests/legacy/fields/relational_fields/field_one2many_tests.js b/addons/web/static/tests/legacy/fields/relational_fields/field_one2many_tests.js index 859a2e94460..83e3b50a699 100644 --- a/addons/web/static/tests/legacy/fields/relational_fields/field_one2many_tests.js +++ b/addons/web/static/tests/legacy/fields/relational_fields/field_one2many_tests.js @@ -9702,7 +9702,7 @@ QUnit.module('fields', {}, function () { assert.expect(2); let o2m; - testUtils.patch(FieldOne2Many, { + testUtils.mock.patch(FieldOne2Many, { init() { this._super(...arguments); o2m = this; @@ -9729,7 +9729,7 @@ QUnit.module('fields', {}, function () { assert.strictEqual(o2m.recordData.display_name, "val"); form.destroy(); - testUtils.unpatch(FieldOne2Many); + testUtils.mock.unpatch(FieldOne2Many); }); QUnit.test('nested one2many, onchange, no command value', async function (assert) { diff --git a/addons/web/static/tests/legacy/fields/relational_fields_tests.js b/addons/web/static/tests/legacy/fields/relational_fields_tests.js index e60dca578bc..1757d121347 100644 --- a/addons/web/static/tests/legacy/fields/relational_fields_tests.js +++ b/addons/web/static/tests/legacy/fields/relational_fields_tests.js @@ -873,7 +873,7 @@ QUnit.module('relational_fields', { `, config: {device: {isMobile: false}}, }); - testUtils.intercept(form, 'call_service', function (ev) { + testUtils.mock.intercept(form, 'call_service', function (ev) { assert.strictEqual(ev.data.service, 'notification', "should display an 'invalid fields' notification"); }, true); @@ -1482,7 +1482,7 @@ QUnit.module('relational_fields', { assert.containsN(list, '.o_field_many2manytags .badge', 2, "there should be 2 tags"); assert.containsNone(list, '.badge.dropdown-toggle', "the tags should not be dropdowns"); - testUtils.intercept(list, 'switch_view', function (event) { + testUtils.mock.intercept(list, 'switch_view', function (event) { assert.strictEqual(event.data.view_type, "form", "should switch to form view"); }); // click on the tag: should do nothing and open the form view diff --git a/addons/web/static/tests/legacy/views/calendar_tests.js b/addons/web/static/tests/legacy/views/calendar_tests.js index c5beffc08c3..b1d959775cd 100644 --- a/addons/web/static/tests/legacy/views/calendar_tests.js +++ b/addons/web/static/tests/legacy/views/calendar_tests.js @@ -2972,7 +2972,7 @@ QUnit.module('Views', { assert.strictEqual(calendar.$('.o_field_widget[name="start"]').text(), "12/16/2016 16:00:00"); // Move event 6 as on first day of month view (27th november 2016) - await testUtils.dragAndDrop( + await testUtils.dom.dragAndDrop( calendar.$('.fc-event').eq(5), calendar.$('.fc-day-top').first() ); @@ -3023,8 +3023,8 @@ QUnit.module('Views', { // Create event (on 20 december) var $cell = calendar.$('.fc-day-grid .fc-row:eq(3) .fc-day:eq(2)'); - await testUtils.triggerMouseEvent($cell, "mousedown"); - await testUtils.triggerMouseEvent($cell, "mouseup"); + await testUtils.dom.triggerMouseEvent($cell, "mousedown"); + await testUtils.dom.triggerMouseEvent($cell, "mouseup"); await testUtils.nextTick(); var $input = $('.modal-body input:first'); await testUtils.fields.editInput($input, "An event"); @@ -3036,7 +3036,7 @@ QUnit.module('Views', { assert.strictEqual(calendar.$('.o_cw_popover .o_cw_popover_fields_secondary .list-group-item:last .o_field_date').text(), '12/20/2016', "should have correct start date"); // Move event to another day (on 27 november) - await testUtils.dragAndDrop( + await testUtils.dom.dragAndDrop( calendar.$('.fc-event').first(), calendar.$('.fc-day-top').first() ); @@ -3047,7 +3047,7 @@ QUnit.module('Views', { assert.strictEqual(calendar.$('.o_cw_popover .o_cw_popover_fields_secondary .list-group-item:last .o_field_date').text(), '11/27/2016', "should have correct start date"); // Move event to last day (on 7 january) - await testUtils.dragAndDrop( + await testUtils.dom.dragAndDrop( calendar.$('.fc-event').first(), calendar.$('.fc-day-top').last() ); @@ -3077,8 +3077,8 @@ QUnit.module('Views', { // Create event (on 20 december) var $cell = calendar.$('.fc-day-grid .fc-row:eq(3) .fc-day:eq(2)'); - testUtils.triggerMouseEvent($cell, "mousedown"); - testUtils.triggerMouseEvent($cell, "mouseup"); + await testUtils.dom.triggerMouseEvent($cell, "mousedown"); + await testUtils.dom.triggerMouseEvent($cell, "mouseup"); await testUtils.nextTick(); var $input = $('.modal-body input:first'); await testUtils.fields.editInput($input, "An event"); @@ -3086,7 +3086,7 @@ QUnit.module('Views', { await testUtils.nextTick(); // Move event to another day (on 19 december) - await testUtils.dragAndDrop( + await testUtils.dom.dragAndDrop( calendar.$('.fc-event:contains("An event")'), calendar.$('.fc-day-grid .fc-row:eq(3) .fc-day-top:eq(1)') ); @@ -3121,8 +3121,8 @@ QUnit.module('Views', { // Create event (on 20 december) var $cell = calendar.$('.fc-day-grid .fc-row:eq(3) .fc-day:eq(2)'); - testUtils.triggerMouseEvent($cell, "mousedown"); - testUtils.triggerMouseEvent($cell, "mouseup"); + await testUtils.dom.triggerMouseEvent($cell, "mousedown"); + await testUtils.dom.triggerMouseEvent($cell, "mouseup"); await testUtils.nextTick(); var $input = $('.modal-body input:first'); await testUtils.fields.editInput($input, "An event"); @@ -3190,8 +3190,8 @@ QUnit.module('Views', { // Create event (on 20 december) var $cell = calendar.$('.fc-day-grid .fc-row:eq(3) .fc-day:eq(2)'); - await testUtils.triggerMouseEvent($cell, "mousedown"); - await testUtils.triggerMouseEvent($cell, "mouseup"); + await testUtils.dom.triggerMouseEvent($cell, "mousedown"); + await testUtils.dom.triggerMouseEvent($cell, "mouseup"); await testUtils.nextTick(); var $input = $('.modal-body input:first'); await testUtils.fields.editInput($input, "An event"); @@ -3199,7 +3199,7 @@ QUnit.module('Views', { await testUtils.nextTick(); // Move event to another day (on 27 november) - await testUtils.dragAndDrop( + await testUtils.dom.dragAndDrop( calendar.$('.fc-event').first(), calendar.$('.fc-day-top').first() ); diff --git a/addons/web/static/tests/legacy/views/kanban_tests.js b/addons/web/static/tests/legacy/views/kanban_tests.js index 1e737f0535f..4a7fb13e03e 100644 --- a/addons/web/static/tests/legacy/views/kanban_tests.js +++ b/addons/web/static/tests/legacy/views/kanban_tests.js @@ -2987,7 +2987,7 @@ QUnit.module('Views', { // drag&drop a record in another column var $record = kanban.$('.o_kanban_group:nth-child(1) .o_kanban_record:first'); var $group = kanban.$('.o_kanban_group:nth-child(2)'); - await testUtils.dragAndDrop($record, $group); + await testUtils.dom.dragAndDrop($record, $group); // should not drag&drop record assert.strictEqual(kanban.$('.o_kanban_group:nth-child(1) .o_kanban_record').length , 2, diff --git a/addons/web/static/tests/legacy/widgets/model_field_selector_tests.js b/addons/web/static/tests/legacy/widgets/model_field_selector_tests.js index 69bb1eb9314..988fb7a757f 100644 --- a/addons/web/static/tests/legacy/widgets/model_field_selector_tests.js +++ b/addons/web/static/tests/legacy/widgets/model_field_selector_tests.js @@ -182,7 +182,7 @@ QUnit.module('ModelFieldSelector', { readonly: false, debugMode: true, }); - await testUtils.addMockEnvironment(fieldSelector, {data: this.data}); + await testUtils.mock.addMockEnvironment(fieldSelector, {data: this.data}); await fieldSelector.appendTo($target); // Focusing the field selector input should open a field selector popover From 03772ac07a676811bc046c4ef6bde92940cbae9f Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 23 Apr 2021 05:44:50 +0000 Subject: [PATCH 13/14] [IMP] web: use testUtils in tests Seems like a better idea than doing it by hand? IDK. --- addons/web/static/tests/legacy/views/form_tests.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/web/static/tests/legacy/views/form_tests.js b/addons/web/static/tests/legacy/views/form_tests.js index fde1d1076b2..55bc28953d5 100644 --- a/addons/web/static/tests/legacy/views/form_tests.js +++ b/addons/web/static/tests/legacy/views/form_tests.js @@ -9650,17 +9650,17 @@ QUnit.module('Views', { const $productLabel = form.$('.o_form_label:eq(1)'); $productLabel.tooltip('show', false); - $productLabel.trigger($.Event('mouseenter')); + await testUtils.dom.triggerMouseEvent($productLabel, 'mouseenter'); assert.strictEqual($('.tooltip .oe_tooltip_help').text().trim(), "this is a tooltip\n\nValues set here are company-specific."); - $productLabel.trigger($.Event('mouseleave')); + await testUtils.dom.triggerMouseEvent($productLabel, 'mouseleave'); const $fooLabel = form.$('.o_form_label:first'); $fooLabel.tooltip('show', false); - $fooLabel.trigger($.Event('mouseenter')); + await testUtils.dom.triggerMouseEvent($fooLabel, 'mouseenter'); assert.strictEqual($('.tooltip .oe_tooltip_help').text().trim(), "Values set here are company-specific."); - $fooLabel.trigger($.Event('mouseleave')); + await testUtils.dom.triggerMouseEvent($fooLabel, 'mouseleave'); form.destroy(); }); @@ -9689,9 +9689,9 @@ QUnit.module('Views', { const $productLabel = form.$('.o_form_label'); $productLabel.tooltip('show', false); - $productLabel.trigger($.Event('mouseenter')); + await testUtils.dom.triggerMouseEvent($productLabel, 'mouseenter'); assert.strictEqual($('.tooltip .oe_tooltip_help').text().trim(), "this is a tooltip"); - $productLabel.trigger($.Event('mouseleave')); + await testUtils.dom.triggerMouseEvent($productLabel, 'mouseleave'); form.destroy(); }); From 6cfc26594478052e850443a34915771ed385f39d Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 23 Apr 2021 05:43:49 +0000 Subject: [PATCH 14/14] [FIX] web: typo in test's attr key Does not really seem used by the test so probably not much of an issue either way. --- addons/web/static/tests/legacy/views/form_tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web/static/tests/legacy/views/form_tests.js b/addons/web/static/tests/legacy/views/form_tests.js index 55bc28953d5..e2ee4864c79 100644 --- a/addons/web/static/tests/legacy/views/form_tests.js +++ b/addons/web/static/tests/legacy/views/form_tests.js @@ -9704,7 +9704,7 @@ QUnit.module('Views', { model: 'partner', data: this.data, arch: `
- + `, });