diff options
| author | Nicolas Lempereur <nle@odoo.com> | 2020-06-23 16:43:29 +0000 |
|---|---|---|
| committer | Nicolas Lempereur <nle@odoo.com> | 2020-06-24 15:48:27 +0000 |
| commit | e961a2fe0998860f051a8ef585dd619b8a7dadda (patch) | |
| tree | 892ad3d7c8f23338a12da298f699fff770adfc4a | |
| parent | 446888cc0d8023c771e7fe2a8ea1be501619b39d (diff) | |
[FIX] web: action before field willStart end
On a re-render, when:
- a field is not yet started (still in willStart because of RPC)
- then an action is executed
we can get a traceback because we try to save the field before it is
started and `this.el` is not set.
eg. in MRP on a work order:
- click on + to get new serial number
=> page is re-rendered with RPC call to update duration to
mrp.workcenter.productivity().search_read to update time
counter
- click on "Record production" before RPC is finished
=> traceback because we try to save `duration` that is not already
started (`this.$el.toggleClass` when `this.$el` is `undefined`)
Without change, added test fails with:
"Cannot read property 'toggleClass' of undefined"
in BasicRenderer.canBeSaved
"Expected 6 assertions, but 5 were run"
Before saas-11.3 5faec34a3c this.el was always set in `init` so this
issue did not happen.
opw-2272117
closes #53532
closes odoo/odoo#53612
X-original-commit: befcad51fd236fdaf284f76cea5624d21c070b0e
Signed-off-by: Nicolas Lempereur (nle) <nle@odoo.com>
| -rw-r--r-- | addons/web/static/src/js/views/basic/basic_renderer.js | 6 | ||||
| -rw-r--r-- | addons/web/static/tests/views/form_tests.js | 58 |
2 files changed, 62 insertions, 2 deletions
diff --git a/addons/web/static/src/js/views/basic/basic_renderer.js b/addons/web/static/src/js/views/basic/basic_renderer.js index f90e27d23d8..9daa9c9936a 100644 --- a/addons/web/static/src/js/views/basic/basic_renderer.js +++ b/addons/web/static/src/js/views/basic/basic_renderer.js @@ -100,8 +100,10 @@ var BasicRenderer = AbstractRenderer.extend(WidgetAdapterMixin, { if (!canBeSaved) { invalidFields.push(widget.name); } - widget.$el.toggleClass('o_field_invalid', !canBeSaved); - widget.$el.attr('aria-invalid', !canBeSaved); + if (widget.el) { // widget may not be started yet + widget.$el.toggleClass('o_field_invalid', !canBeSaved); + widget.$el.attr('aria-invalid', !canBeSaved); + } }); return invalidFields; }, diff --git a/addons/web/static/tests/views/form_tests.js b/addons/web/static/tests/views/form_tests.js index 56fba6515bc..99c49fc9519 100644 --- a/addons/web/static/tests/views/form_tests.js +++ b/addons/web/static/tests/views/form_tests.js @@ -1434,6 +1434,64 @@ QUnit.module('Views', { form.destroy(); }); + QUnit.test('button in form view and long willStart', async function (assert) { + assert.expect(6); + + var rpcCount = 0; + + var FieldChar = fieldRegistry.get('char'); + fieldRegistry.add('asyncwidget', FieldChar.extend({ + willStart: function () { + assert.step('load '+rpcCount); + if (rpcCount === 2) { + return $.Deferred(); + } + return $.Deferred().resolve(); + }, + })); + + var form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '<form string="Partners">' + + '<field name="state" invisible="1"/>' + + '<header>' + + '<button name="post" class="p" string="Confirm" type="object"/>' + + '</header>' + + '<sheet>' + + '<group>' + + '<field name="foo" widget="asyncwidget"/>' + + '</group>' + + '</sheet>' + + '</form>', + res_id: 2, + mockRPC: function () { + rpcCount++; + return this._super.apply(this, arguments); + }, + }); + assert.verifySteps(['load 1']); + + await testUtils.mock.intercept(form, 'execute_action', function (ev) { + ev.data.on_success(); + ev.data.on_closed(); + }); + + await testUtils.dom.click('.o_form_statusbar button.p', form); + assert.verifySteps(['load 2']); + + testUtils.mock.intercept(form, 'execute_action', function (ev) { + ev.data.on_success(); + ev.data.on_closed(); + }); + + await testUtils.dom.click('.o_form_statusbar button.p', form); + assert.verifySteps(['load 3']); + + form.destroy(); + }); + QUnit.test('buttons in form view, new record', async function (assert) { // this simulates a situation similar to the settings forms. assert.expect(7); |
