summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Bohy <aab@odoo.com>2020-03-03 12:00:43 +0000
committerAaron Bohy <aab@odoo.com>2020-03-09 14:14:39 +0000
commit8a52f10ceb9e3a70cf729e511a6962bbed952333 (patch)
tree9b2363f33713deee8a85871b864bffd82785c1d1
parenta9cebd5acbba40ae63aa9f986d9bab39b2112f92 (diff)
[FIX] web: BasicModel: always set a valid limit
When x2many fields are displayed with widgets like many2many_tags, there is no limit on the number of related records to fetch and display. In this case, the 'limit' attribute on the datapoints is undefined. This could lead to weird issues when the limit is used in computation, e.g. var index = list.offset + list.limit; // = NaN There are several occurrences of the above examples in the code, which can be observed in specific scenarios, e.g. the one encoded in the test. In this scenario, when the bug occurs, new records added to editable list views are inserted on top (even if the list is editable="bottom"), but the edited row is the last one. Issue reported on task 2189529
-rw-r--r--addons/web/static/src/js/views/basic/basic_model.js2
-rw-r--r--addons/web/static/tests/fields/relational_fields/field_one2many_tests.js101
2 files changed, 102 insertions, 1 deletions
diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js
index 033d0f670ae..00ff4464eff 100644
--- a/addons/web/static/src/js/views/basic/basic_model.js
+++ b/addons/web/static/src/js/views/basic/basic_model.js
@@ -3951,7 +3951,7 @@ var BasicModel = AbstractModel.extend({
groupsOffset: 0,
id: _.uniqueId(params.modelName + '_'),
isOpen: params.isOpen,
- limit: type === 'record' ? 1 : params.limit,
+ limit: type === 'record' ? 1 : (params.limit || Number.MAX_SAFE_INTEGER),
loadMoreOffset: 0,
model: params.modelName,
offset: params.offset || (type === 'record' ? _.indexOf(res_ids, res_id) : 0),
diff --git a/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js b/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js
index 7b470cda22a..485f05abf1f 100644
--- a/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js
+++ b/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js
@@ -8992,6 +8992,107 @@ QUnit.module('fields', {}, function () {
form.destroy();
});
+
+ QUnit.skip('one2many with many2many_tags in list and list in form with a limit', async function (assert) {
+ // This test is skipped for now, as it doesn't work, and it can't be fixed in the current
+ // architecture (without large changes). However, this is unlikely to happen as the default
+ // limit is 80, and it would be useless to display so many records with a many2many_tags
+ // widget. So it would be nice if we could make it work in the future, but it's no big
+ // deal for now.
+ assert.expect(6);
+
+ this.data.partner.records[0].p = [1];
+ this.data.partner.records[0].turtles = [1, 2, 3];
+
+ const form = await createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: `
+ <form>
+ <field name="bar"/>
+ <field name="p">
+ <tree>
+ <field name="turtles" widget="many2many_tags"/>
+ </tree>
+ <form>
+ <field name="turtles">
+ <tree limit="2"><field name="display_name"/></tree>
+ </field>
+ </form>
+ </field>
+ </form>`,
+ res_id: 1,
+ });
+
+ assert.containsOnce(form, '.o_field_widget[name=p] .o_data_row');
+ assert.containsN(form, '.o_data_row .o_field_many2manytags .badge', 3);
+
+ await testUtils.dom.click(form.$('.o_data_row'));
+
+ assert.containsOnce(document.body, '.modal .o_form_view');
+ assert.containsN(document.body, '.modal .o_field_widget[name=turtles] .o_data_row', 2);
+ assert.isVisible($('.modal .o_field_x2many_list .o_pager'));
+ assert.strictEqual($(".modal .o_field_x2many_list .o_pager").text().trim(), '1-2 / 3');
+
+ form.destroy();
+ });
+
+ QUnit.test('one2many with many2many_tags in list and list in form, and onchange', async function (assert) {
+ assert.expect(8);
+
+ this.data.partner.onchanges = {
+ bar: function (obj) {
+ obj.p = [
+ [5],
+ [0, 0, {
+ turtles: [
+ [5],
+ [0, 0, {
+ display_name: 'new turtle',
+ }]
+ ],
+ }]
+ ];
+ },
+ };
+
+ const form = await createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: `
+ <form>
+ <field name="bar"/>
+ <field name="p">
+ <tree>
+ <field name="turtles" widget="many2many_tags"/>
+ </tree>
+ <form>
+ <field name="turtles">
+ <tree editable="bottom"><field name="display_name"/></tree>
+ </field>
+ </form>
+ </field>
+ </form>`,
+ });
+
+ assert.containsOnce(form, '.o_field_widget[name=p] .o_data_row');
+ assert.containsOnce(form, '.o_data_row .o_field_many2manytags .badge');
+
+ await testUtils.dom.click(form.$('.o_data_row'));
+
+ assert.containsOnce(document.body, '.modal .o_form_view');
+ assert.containsOnce(document.body, '.modal .o_field_widget[name=turtles] .o_data_row');
+ assert.strictEqual($('.modal .o_field_widget[name=turtles] .o_data_row').text(), 'new turtle');
+
+ await testUtils.dom.click($('.modal .o_field_x2many_list_row_add a'));
+ assert.containsN(document.body, '.modal .o_field_widget[name=turtles] .o_data_row', 2);
+ assert.strictEqual($('.modal .o_field_widget[name=turtles] .o_data_row:first').text(), 'new turtle');
+ assert.hasClass($('.modal .o_field_widget[name=turtles] .o_data_row:nth(1)'), 'o_selected_row');
+
+ form.destroy();
+ });
});
});
});