summaryrefslogtreecommitdiff
path: root/addons/web/static/tests/fields/relational_fields_tests.js
diff options
context:
space:
mode:
authorGéry Debongnie <ged@odoo.com>2017-10-20 15:29:10 +0200
committerGéry Debongnie <ged@odoo.com>2017-10-20 17:14:10 +0200
commit635572b49d5b70a32b717cf2d52da49b10aac28e (patch)
treeb61517934491495d11208d0fed3186adc769d8d9 /addons/web/static/tests/fields/relational_fields_tests.js
parentfd65dbaa1fa2f0169f0b44c7fe90a35b4cb137b4 (diff)
[FIX] web: properly handle failures in onchanges
With the new views, we mainly focused on making them work. But we also need to be able to handle unusual cases, such as some RPC failing. An example of such a problem was the following: - a form view with a one2many with an onchange - edit mode, change a field in the one2many, click elsewhere - the onchange triggers, calls the server - it may happen that the server fails with a ValidationError - the onchange deferred fails, the line in the one2many is restored to the value known by the list renderer, which is the previous value (but the new value was applied to the model) - we now have a 'corrupted' state: clicking on save will send the invalid value, even though the UI displays the previous one. We solve this problem in this commit by making sure that the onchange deferred returned by the _performOnchange always succeed (or stays pending). If the rpc fails, the deferred will succeed with an empty dictionary. This means that the list renderer will be updated with the value from the model. Note that it may not be intuitive that a failure in the onchange is not seen as an error from the perspective of the _performOnChange, but I think that it still makes sense: - the validation/network errors are not really a concern of the UI. The UI just display the values entered by the user. - if an onchange fails (for example, because of a coding error), we do not really want to prevent the user from working. Also, when the onchange is performed, the initial change was already applied to the local data. Rollbacking them would be a more difficult task. Note that we also improve the mock server in this commit, to allow mocking failures.
Diffstat (limited to 'addons/web/static/tests/fields/relational_fields_tests.js')
-rw-r--r--addons/web/static/tests/fields/relational_fields_tests.js60
1 files changed, 60 insertions, 0 deletions
diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js
index f8652b13341..a5ed514663b 100644
--- a/addons/web/static/tests/fields/relational_fields_tests.js
+++ b/addons/web/static/tests/fields/relational_fields_tests.js
@@ -5836,6 +5836,66 @@ QUnit.module('relational_fields', {
form.destroy();
});
+ QUnit.test('display correct value after validation error', function (assert) {
+ assert.expect(4);
+
+ this.data.partner.onchanges.turtles = true;
+
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: '<form>' +
+ '<sheet>' +
+ '<field name="turtles">' +
+ '<tree editable="bottom">' +
+ '<field name="turtle_foo"/>' +
+ '</tree>' +
+ '</field>' +
+ '</sheet>' +
+ '</form>',
+ mockRPC: function (route, args) {
+ if (args.method === 'onchange') {
+ // we simulate a validation error. In the 'real' web client,
+ // the server error will be used by the session to display
+ // an error dialog. From the point of view of the basic
+ // model, the deferred is just rejected.
+ return $.Deferred().reject();
+ }
+ if (args.method === 'write') {
+ assert.deepEqual(args.args[1].turtles[0], [1,2,{turtle_foo: 'foo'}],
+ 'should send the "bad" value');
+ // we simulate a validation error
+ return $.Deferred().reject();
+ }
+ return this._super.apply(this, arguments);
+ },
+ viewOptions: {mode: 'edit'},
+ res_id: 1,
+ });
+
+ assert.strictEqual(form.$('.o_data_row .o_data_cell:nth(0)').text(), 'blip',
+ "initial text should be correct");
+ form.$('.o_data_row .o_data_cell:nth(0)').click();
+ form.$('.o_field_widget[name=turtle_foo]').val('foo').trigger('input');
+
+ // we try to validate the line. This triggers an onchange which will be
+ // rejected. The line will be returned to readonly mode, but with the
+ // new invalid value.
+ form.$el.click();
+
+ assert.strictEqual(form.$('.o_data_row .o_data_cell:nth(0)').text(), 'foo',
+ "turtle_foo text should now be foo (invalid value)");
+
+ // we make sure here that when we save, the values are the current
+ // values displayed in the field.
+ form.$buttons.find('.o_form_button_save').click();
+ assert.strictEqual(form.mode, 'edit', "form view should still be in edit mode");
+
+ form.destroy();
+ });
+
+
QUnit.module('FieldMany2Many');
QUnit.test('many2many kanban: edition', function (assert) {