diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js index ee6edf8941c17a2befbf53848d6253d0f3eea727..8e4e43f67495c727c9a733dd3af8a65de4721a99 100644 --- a/addons/web/static/tests/views/list_tests.js +++ b/addons/web/static/tests/views/list_tests.js @@ -4448,6 +4448,78 @@ QUnit.module('Views', { list.destroy(); }); + QUnit.test('edition, then navigation with tab (with a readonly field and onchange)', async function (assert) { + // This test makes sure that if we have a read-only cell in a row, in + // case the keyboard navigation move over it and there a unsaved changes + // (which will trigger an onchange), the focus of the next activable + // field will not crash + assert.expect(4); + + this.data.bar.onchanges = { + o2m: function () {}, + }; + this.data.bar.fields.o2m = {string: "O2M field", type: "one2many", relation: "foo"}; + this.data.bar.records[0].o2m = [1, 4]; + + var form = await createView({ + View: FormView, + model: 'bar', + res_id: 1, + data: this.data, + arch: '<form>' + + '<group>' + + '<field name="display_name"/>' + + '<field name="o2m">' + + '<tree editable="bottom">' + + '<field name="foo"/>' + + '<field name="date" readonly="1"/>' + + '<field name="int_field"/>' + + '</tree>' + + '</field>' + + '</group>' + + '</form>', + mockRPC: function (route, args) { + if (args.method === 'onchange') { + assert.step(args.method + ':' + args.model); + } + return this._super.apply(this, arguments); + }, + fieldDebounce: 1, + viewOptions: { + mode: 'edit', + }, + }); + + var jq_evspecial_focus_trigger = $.event.special.focus.trigger; + // As KeyboardEvent will be triggered by JS and not from the + // User-Agent itself, the focus event will not trigger default + // action (event not being trusted), we need to manually trigger + // 'change' event on the currently focused element + $.event.special.focus.trigger = function () { + if (this !== document.activeElement && this.focus) { + var activeElement = document.activeElement; + this.focus(); + $(activeElement).trigger('change'); + } + }; + + // editable list, click on first td and press TAB + await testUtils.dom.click(form.$('.o_data_cell:contains(yop)')); + assert.strictEqual(document.activeElement, form.$('tr.o_selected_row input[name="foo"]')[0], + "focus should be on an input with name = foo"); + await testUtils.fields.editInput(form.$('tr.o_selected_row input[name="foo"]'), 'new value'); + var tabEvent = $.Event("keydown", { which: $.ui.keyCode.TAB }); + await testUtils.dom.triggerEvents(form.$('tr.o_selected_row input[name="foo"]'), [tabEvent]); + assert.strictEqual(document.activeElement, form.$('tr.o_selected_row input[name="int_field"]')[0], + "focus should be on an input with name = int_field"); + + // Restore origin jQuery special trigger for 'focus' + $.event.special.focus.trigger = jq_evspecial_focus_trigger; + + assert.verifySteps(["onchange:bar"], "onchange method should have been called"); + form.destroy(); + }); + QUnit.test('pressing SHIFT-TAB in editable list with a readonly field [REQUIRE FOCUS]', async function (assert) { assert.expect(4);