diff options
| author | Mohammed Shekha <msh@odoo.com> | 2019-12-19 05:14:01 +0000 |
|---|---|---|
| committer | Aaron Bohy <aab@odoo.com> | 2020-01-22 13:01:33 +0000 |
| commit | 370f53d8dcc88b4c6960fc321199df688d1d0810 (patch) | |
| tree | 3062d5774444821c7516a34b9dc357c8528ac20c /addons/web/static/tests/fields | |
| parent | a5c4855a6b5c05a27184a55261ca01966a91248e (diff) | |
[IMP] web: conditional create/delete options on x2many fields
After this commit, x2many fields can have options like
create/delete which accept a domain, to make create/delete on
x2many conditional, say for example x2many field can have options
like:
options="{'create:' [('foo', '=', True)]', 'delete:' [('foo', '=', True)]'}"
With this when foo field is True, Create and Delete actions will
be available, but if foo is False then they won't.
In case of one2many fields, if 'create' is false, then 'Add a line'
(list) or 'Add' button (kanban) won't be displayed.
In case of many2many fields, 'Add a line' or 'Add' button will
always be displayed even if 'create' condition is false as it
doesn't really create records (but rather links existing ones).
Same applies for delete.
Task-2092953
closes odoo/odoo#42919
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
Co-authored-by: Parth Chokshi <pch@odoo.com>
Co-authored-by: Aaron Bohy<aab@odoo.com>
Diffstat (limited to 'addons/web/static/tests/fields')
| -rw-r--r-- | addons/web/static/tests/fields/relational_fields/field_many2many_tests.js | 215 | ||||
| -rw-r--r-- | addons/web/static/tests/fields/relational_fields/field_one2many_tests.js | 99 |
2 files changed, 314 insertions, 0 deletions
diff --git a/addons/web/static/tests/fields/relational_fields/field_many2many_tests.js b/addons/web/static/tests/fields/relational_fields/field_many2many_tests.js index 487cd8647b8..7af0216e20e 100644 --- a/addons/web/static/tests/fields/relational_fields/field_many2many_tests.js +++ b/addons/web/static/tests/fields/relational_fields/field_many2many_tests.js @@ -350,6 +350,74 @@ QUnit.module('fields', {}, function () { form.destroy(); }); + QUnit.test('many2many kanban: conditional create/delete actions', async function (assert) { + assert.expect(6); + + this.data.partner.records[0].timmy = [12, 14]; + + const form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: ` + <form> + <field name="color"/> + <field name="timmy" options="{'create': [('color', '=', 'red')], 'delete': [('color', '=', 'red')]}"> + <kanban> + <field name="display_name"/> + <templates> + <t t-name="kanban-box"> + <div class="oe_kanban_global_click"> + <span><t t-esc="record.display_name.value"/></span> + </div> + </t> + </templates> + </kanban> + </field> + </form>`, + archs: { + 'partner_type,false,form': '<form><field name="name"/></form>', + 'partner_type,false,list': '<tree><field name="name"/></tree>', + 'partner_type,false,search': '<search/>', + }, + res_id: 1, + viewOptions: { + mode: 'edit', + }, + }); + + // color is red + assert.containsOnce(form, '.o-kanban-button-new', '"Add" button should be available'); + + await testUtils.dom.click(form.$('.o_kanban_record:contains(silver)')); + assert.containsOnce(document.body, '.modal .modal-footer .o_btn_remove', + 'remove button should be visible in modal'); + await testUtils.dom.click($('.modal .modal-footer .o_form_button_cancel')); + + await testUtils.dom.click(form.$('.o-kanban-button-new')); + assert.containsN(document.body, '.modal .modal-footer button', 3, + 'there should be 3 buttons available in the modal'); + await testUtils.dom.click($('.modal .modal-footer .o_form_button_cancel')); + + // set color to black + await testUtils.fields.editSelect(form.$('select[name="color"]'), '"black"'); + assert.containsOnce(form, '.o-kanban-button-new', + '"Add" button should still be available even after color field changed'); + + await testUtils.dom.click(form.$('.o-kanban-button-new')); + // only select and cancel button should be available, create + // button should be removed based on color field condition + assert.containsN(document.body, '.modal .modal-footer button', 2, + '"Create" button should not be available in the modal after color field changed'); + await testUtils.dom.click($('.modal .modal-footer .o_form_button_cancel')); + + await testUtils.dom.click(form.$('.o_kanban_record:contains(silver)')); + assert.containsNone(document.body, '.modal .modal-footer .o_btn_remove', + 'remove button should be visible in modal'); + + form.destroy(); + }); + QUnit.test('many2many list (non editable): edition', async function (assert) { assert.expect(29); @@ -642,6 +710,64 @@ QUnit.module('fields', {}, function () { form.destroy(); }); + QUnit.test('many2many list: conditional create/delete actions', async function (assert) { + assert.expect(6); + + this.data.partner.records[0].timmy = [12, 14]; + + const form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: ` + <form> + <field name="color"/> + <field name="timmy" options="{'create': [('color', '=', 'red')], 'delete': [('color', '=', 'red')]}"> + <tree> + <field name="name"/> + </tree> + </field> + </form>`, + archs: { + 'partner_type,false,list': '<tree><field name="name"/></tree>', + 'partner_type,false,search': '<search/>', + }, + res_id: 1, + viewOptions: { + mode: 'edit', + }, + }); + + // color is red -> create and delete actions are available + assert.containsOnce(form, '.o_field_x2many_list_row_add', + "should have the 'Add an item' link"); + assert.containsN(form, '.o_list_record_remove', 2, + "should have two remove icons"); + + await testUtils.dom.click(form.$('.o_field_x2many_list_row_add a')); + + assert.containsN(document.body, '.modal .modal-footer button', 3, + 'there should be 3 buttons available in the modal'); + + await testUtils.dom.click($('.modal .modal-footer .o_form_button_cancel')); + + // set color to black -> create and delete actions are no longer available + await testUtils.fields.editSelect(form.$('select[name="color"]'), '"black"'); + + // add a line and remove icon should still be there as they don't create/delete records, + // but rather add/remove links + assert.containsOnce(form, '.o_field_x2many_list_row_add', + '"Add a line" button should still be available even after color field changed'); + assert.containsN(form, '.o_list_record_remove', 2, + "should still have remove icon even after color field changed"); + + await testUtils.dom.click(form.$('.o_field_x2many_list_row_add a')); + assert.containsN(document.body, '.modal .modal-footer button', 2, + '"Create" button should not be available in the modal after color field changed'); + + form.destroy(); + }); + QUnit.test('many2many list: list of id as default value', async function (assert) { assert.expect(1); @@ -1232,6 +1358,95 @@ QUnit.module('fields', {}, function () { form.destroy(); }); + + QUnit.test('many2many_tags widget: conditional create/delete actions', async function (assert) { + assert.expect(10); + + this.data.turtle.records[0].partner_ids = [2]; + for (var i = 1; i <= 10; i++) { + this.data.partner.records.push({ id: 100 + i, display_name: "Partner" + i }); + } + + const form = await createView({ + View: FormView, + model: 'turtle', + data: this.data, + arch: ` + <form> + <field name="display_name"/> + <field name="turtle_bar"/> + <field name="partner_ids" options="{'create': [('turtle_bar', '=', True)], 'delete': [('turtle_bar', '=', True)]}" widget="many2many_tags"/> + </form>`, + archs: { + 'partner,false,list': '<tree><field name="name"/></tree>', + 'partner,false,search': '<search/>', + }, + res_id: 1, + viewOptions: { + mode: 'edit', + }, + }); + + // turtle_bar is true -> create and delete actions are available + assert.containsOnce(form, '.o_field_many2manytags.o_field_widget .badge .o_delete', + 'X icon on badges should not be available'); + + await testUtils.fields.many2one.clickOpenDropdown('partner_ids'); + + const $dropdown1 = form.$('.o_field_many2one input').autocomplete('widget'); + assert.containsOnce($dropdown1, 'li.o_m2o_dropdown_option:contains(Create and Edit...)', + 'autocomplete should contain Create and Edit...'); + + await testUtils.fields.many2one.clickItem('partner_ids', 'Search More'); + + assert.containsN(document.body, '.modal .modal-footer button', 3, + 'there should be 3 buttons (Select, Create and Cancel) available in the modal footer'); + + await testUtils.dom.click($('.modal .modal-footer .o_form_button_cancel')); + + // type something that doesn't exist + await testUtils.fields.editAndTrigger(form.$('.o_field_many2one input'), + 'Something that does not exist', 'keydown'); + // await testUtils.nextTick(); + assert.containsN($dropdown1, 'li.o_m2o_dropdown_option', 2, + 'autocomplete should contain Create and Create and Edit... options'); + + // set turtle_bar false -> create and delete actions are no longer available + await testUtils.dom.click(form.$('.o_field_widget[name="turtle_bar"] input').first()); + + // remove icon should still be there as it doesn't delete records but rather remove links + assert.containsOnce(form, '.o_field_many2manytags.o_field_widget .badge .o_delete', + 'X icon on badge should still be there even after turtle_bar is not checked'); + + await testUtils.fields.many2one.clickOpenDropdown('partner_ids'); + const $dropdown2 = form.$('.o_field_many2one input').autocomplete('widget'); + + // only Search More option should be available + assert.containsOnce($dropdown2, 'li.o_m2o_dropdown_option', + 'autocomplete should contain only one option'); + assert.containsOnce($dropdown2, 'li.o_m2o_dropdown_option:contains(Search More)', + 'autocomplete option should be Search More'); + + await testUtils.fields.many2one.clickItem('partner_ids', 'Search More'); + + assert.containsN(document.body, '.modal .modal-footer button', 2, + 'there should be 2 buttons (Select and Cancel) available in the modal footer'); + + await testUtils.dom.click($('.modal .modal-footer .o_form_button_cancel')); + + // type something that doesn't exist + await testUtils.fields.editAndTrigger(form.$('.o_field_many2one input'), + 'Something that does not exist', 'keyup'); + // await testUtils.nextTick(); + + // only Search More option should be available + assert.containsOnce($dropdown2, 'li.o_m2o_dropdown_option', + 'autocomplete should contain only one option'); + assert.containsOnce($dropdown2, 'li.o_m2o_dropdown_option:contains(Search More)', + 'autocomplete option should be Search More'); + + form.destroy(); + }); }); }); }); 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 8aacf099de4..ad68ede00d2 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 @@ -2142,6 +2142,46 @@ QUnit.module('fields', {}, function () { form.destroy(); }); + QUnit.test('one2many list: conditional create/delete actions', async function (assert) { + assert.expect(4); + + this.data.partner.records[0].p = [2, 4]; + const form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: ` + <form> + <field name="bar"/> + <field name="p" options="{'create': [('bar', '=', True)], 'delete': [('bar', '=', True)]}"> + <tree> + <field name="display_name"/> + </tree> + </field> + </form>`, + res_id: 1, + viewOptions: { + mode: 'edit', + }, + }); + + // bar is true -> create and delete action are available + assert.containsOnce(form, '.o_field_x2many_list_row_add', + '"Add an item" link should be available'); + assert.hasClass(form.$('td.o_list_record_remove button').first(), 'fa fa-trash-o', + "should have trash bin icons"); + + // set bar to false -> create and delete action are no longer available + await testUtils.dom.click(form.$('.o_field_widget[name="bar"] input').first()); + + assert.containsNone(form, '.o_field_x2many_list_row_add', + '"Add an item" link should not be available if bar field is False'); + assert.containsNone(form, 'td.o_list_record_remove button', + "should not have trash bin icons if bar field is False"); + + form.destroy(); + }); + QUnit.test('one2many list: unlink two records', async function (assert) { assert.expect(8); this.data.partner.records[0].p = [1, 2, 4]; @@ -2441,6 +2481,65 @@ QUnit.module('fields', {}, function () { form.destroy(); }); + QUnit.test('one2many kanban: conditional create/delete actions', async function (assert) { + assert.expect(4); + + this.data.partner.records[0].p = [2, 4]; + + const form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: ` + <form> + <field name="bar"/> + <field name="p" options="{'create': [('bar', '=', True)], 'delete': [('bar', '=', True)]}"> + <kanban> + <field name="display_name"/> + <templates> + <t t-name="kanban-box"> + <div class="oe_kanban_global_click"> + <span><t t-esc="record.display_name.value"/></span> + </div> + </t> + </templates> + </kanban> + <form> + <field name="display_name"/> + <field name="foo"/> + </form> + </field> + </form>`, + res_id: 1, + viewOptions: { + mode: 'edit', + }, + }); + + // bar is initially true -> create and delete actions are available + assert.containsOnce(form, '.o-kanban-button-new', '"Add" button should be available'); + + await testUtils.dom.click(form.$('.oe_kanban_global_click').first()); + + assert.containsOnce(document.body, '.modal .modal-footer .o_btn_remove', + 'There should be a Remove Button inside modal'); + + await testUtils.dom.click($('.modal .modal-footer .o_form_button_cancel')); + + // set bar false -> create and delete actions are no longer available + await testUtils.dom.click(form.$('.o_field_widget[name="bar"] input').first()); + + assert.containsNone(form, '.o-kanban-button-new', + '"Add" button should not be available as bar is False'); + + await testUtils.dom.click(form.$('.oe_kanban_global_click').first()); + + assert.containsNone(document.body, '.modal .modal-footer .o_btn_remove', + 'There should not be a Remove Button as bar field is False'); + + form.destroy(); + }); + QUnit.test('editable one2many list, pager is updated', async function (assert) { assert.expect(1); |
