From e02a4b93e514e5b8ef457ea651e28ed84340bfeb Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Tue, 12 May 2020 08:41:23 +0000 Subject: [PATCH] [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] a71f22370217d2da6ad13bd29c2fa412a40ebe4c Related to task 1958793 --- .../static/tests/fields/basic_fields_tests.js | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 5f4c4eb8dcb..c7040a98744 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -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: ` +
+ + + + + + + +
`, + 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);