[FIX] *: JS runner and large number of JS warnings
Currently the JS logs are full of warnings and it doesn't really matter because they don't block CI. This PR: * flips JS warnings to trigger Python warnings * improves qunit's logging (hopefully) so test failures are more readable and actionable * fixes / removes / downgrades JS warnings occurring during runbot runs * also other updates probably closes odoo/odoo#71845 Related: odoo/enterprise#18949 Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.`);
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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] = () => {}
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
@@ -146,9 +147,9 @@ 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('01/09/1997') },
|
||||
props: { date: moment('1997-01-09') },
|
||||
});
|
||||
const input = picker.el.querySelector('.o_datepicker_input');
|
||||
|
||||
@@ -160,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');
|
||||
@@ -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');
|
||||
@@ -330,9 +331,9 @@ 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('01/09/1997 12:30:01') },
|
||||
props: { date: moment('1997-01-09 12:30:01') },
|
||||
});
|
||||
const input = picker.el.querySelector('.o_datepicker_input');
|
||||
|
||||
@@ -344,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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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: '<form string="Partners">' +
|
||||
'<sheet>' +
|
||||
'<notebook>' +
|
||||
'<page string="P page">' +
|
||||
'<field name="turtles">' +
|
||||
'<tree default_order="turtle_int">' +
|
||||
'<field name="turtle_int" widget="handle"/>' +
|
||||
'<field name="turtle_foo"/>' +
|
||||
'</tree>' +
|
||||
'</field>' +
|
||||
'</page>' +
|
||||
'</notebook>' +
|
||||
'</sheet>' +
|
||||
'</form>',
|
||||
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) {
|
||||
@@ -9720,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;
|
||||
@@ -9747,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) {
|
||||
|
||||
@@ -873,7 +873,7 @@ QUnit.module('relational_fields', {
|
||||
</form>`,
|
||||
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
|
||||
|
||||
@@ -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()});
|
||||
});
|
||||
|
||||
@@ -1152,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;
|
||||
},
|
||||
|
||||
@@ -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');
|
||||
});
|
||||
|
||||
@@ -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()
|
||||
);
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
@@ -9704,7 +9704,7 @@ QUnit.module('Views', {
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: `<form>
|
||||
<widget name="pie_chart" title="qux by product" attrs="{'measure\': 'qux', 'groupby': 'product_id'}"/>
|
||||
<widget name="pie_chart" title="qux by product" attrs="{'measure': 'qux', 'groupby': 'product_id'}"/>
|
||||
</form>`,
|
||||
});
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1144,7 +1144,7 @@ QUnit.module('Views', {
|
||||
"partner,false,search": `
|
||||
<search>
|
||||
<searchpanel>
|
||||
<field name="category_id" enable_counters="1"/>
|
||||
<field name="category_id"/>
|
||||
<field name="company_id" select="multi" domain="[['category_id', '=', category_id]]" enable_counters="1"/>
|
||||
</searchpanel>
|
||||
</search>`,
|
||||
@@ -2065,7 +2065,7 @@ QUnit.module('Views', {
|
||||
'partner,false,search': `
|
||||
<search>
|
||||
<searchpanel>
|
||||
<field name="category_id" enable_counters="1"/>
|
||||
<field name="category_id"/>
|
||||
<field name="company_id" select="multi" domain="[['category_id', '=', category_id]]" enable_counters="1"/>
|
||||
</searchpanel>
|
||||
</search>`,
|
||||
@@ -4135,7 +4135,7 @@ QUnit.module('Views', {
|
||||
'partner,false,search': `
|
||||
<search>
|
||||
<searchpanel>
|
||||
<field name="category_id" enable_counters="1"/>
|
||||
<field name="category_id"/>
|
||||
<field name="company_id" select="multi" domain="[['category_id', '=', category_id]]"/>
|
||||
</searchpanel>
|
||||
</search>`,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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: `
|
||||
<button class="btn anchor1">Anchor</button>
|
||||
<button class="btn anchor2">Anchor</button>
|
||||
|
||||
+17
-6
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user