[IMP] web: add more accurate test on onchange scenario

In a form view, have an x2many list with two fields A and B (e.g.
A is a many2one, and B is a char). There is an onchange on the
x2many that is triggered when the user sets A, and that sets B.

In this scenario, let's assume that the user first writes something
in B, but directly deletes it. Then, he sets A. In this situation,
B isn't updated with the value returned by the onchange.

Commit [1] is an attempt to fix this, but it actually broke what
has been done in [2]. However, tests of [2] still passed, because
they didn't accurately reproduce what happens in practice (outside
the test environment).

An input field widget listens to 'input' and 'change' events. It
commits its value when both occur, but in the 'input' case, the
action is debounced with a large value (so that it actually only
commits the value on 'change', i.e. when the field is focusset
out). In the tests, the debounce value is 0, so fields actually
commit their value directly when 'input' events occur. This is
something we may want to change in the future, to remove this
discrepancy.

This commit adds a test with a large debounce value, so that we
accurately test what happens in practice, and we make sure that
this won't be broken in an attempt of fixing something else.

[1] cdca11db2ec207363df1d4fb3c87014d9c931d25
[2] a71f223702

Related to task 1958793
This commit is contained in:
Aaron Bohy
2020-05-12 13:43:39 +00:00
parent 5d55426eb9
commit e02a4b93e5
@@ -1569,6 +1569,69 @@ QUnit.module('basic_fields', {
form.destroy();
});
QUnit.test('input field: change value before pending onchange returns (with fieldDebounce)', async function (assert) {
// this test is exactly the same as the previous one, except that we set
// here a fieldDebounce to accurately reproduce what happens in practice:
// the field doesn't notify the changes on 'input', but on 'change' event.
assert.expect(5);
this.data.partner.onchanges = {
product_id: function (obj) {
obj.int_field = obj.product_id ? 7 : false;
},
};
let def;
const form = await createView({
View: FormView,
model: 'partner',
data: this.data,
arch: `
<form>
<field name="p">
<tree editable="bottom">
<field name="product_id"/>
<field name="foo"/>
<field name="int_field"/>
</tree>
</field>
</form>`,
async mockRPC(route, args) {
const result = this._super(...arguments);
if (args.method === "onchange") {
await Promise.resolve(def);
}
return result;
},
fieldDebounce: 5000,
});
await testUtils.dom.click(form.$('.o_field_x2many_list_row_add a'));
assert.strictEqual(form.$('input[name="foo"]').val(), 'My little Foo Value',
'should contain the default value');
def = testUtils.makeTestPromise();
await testUtils.fields.many2one.clickOpenDropdown('product_id');
await testUtils.fields.many2one.clickHighlightedItem('product_id');
// set foo before onchange
await testUtils.fields.editInput(form.$('input[name="foo"]'), "tralala");
assert.strictEqual(form.$('input[name="foo"]').val(), 'tralala');
assert.strictEqual(form.$('input[name="int_field"]').val(), '');
// complete the onchange
def.resolve();
await testUtils.nextTick();
assert.strictEqual(form.$('input[name="foo"]').val(), 'tralala',
'foo should contain the same value as before onchange');
assert.strictEqual(form.$('input[name="int_field"]').val(), '7',
'int_field should contain the value returned by the onchange');
form.destroy();
});
QUnit.test('input field: change value before pending onchange renaming', async function (assert) {
assert.expect(3);