diff --git a/addons/mass_mailing/static/src/js/mailing_m2o_filter.js b/addons/mass_mailing/static/src/js/mailing_m2o_filter.js index 36e5f7c2b09..4364266fdd1 100644 --- a/addons/mass_mailing/static/src/js/mailing_m2o_filter.js +++ b/addons/mass_mailing/static/src/js/mailing_m2o_filter.js @@ -63,8 +63,18 @@ export class FieldMany2OneMailingFilter extends Many2OneField { } // By default, domains in recordData are in string format, but adding / removing a leaf from domain widget converts // value into object, so we use 'Domain' class to convert them in same (string) format, allowing proper comparison. - const recordDomain = new Domain(this.props.record.data[this.props.domain_field] || []).toString(); - const filterDomain = new Domain(this.props.record.data.mailing_filter_domain || []).toString(); + let recordDomain; + let filterDomain; + try { + recordDomain = new Domain(this.props.record.data[this.props.domain_field] || []).toString(); + filterDomain = new Domain(this.props.record.data.mailing_filter_domain || []).toString(); + } catch { + // Don't raise a traceback if a domain set manually doesn't match the format expected. + // This can happen when we unfocus the domain editor + this.filter.canSaveFilter = false; + this.filter.canRemoveFilter = false; + return; + } const modelFieldElement = this.props.model_field && document.querySelector( `input#${this.props.model_field},div [name="${this.props.model_field}"]`); @@ -81,6 +91,7 @@ export class FieldMany2OneMailingFilter extends Many2OneField { || value.length || this.state.isFloating || filterDomain !== recordDomain; + this.filter.canRemoveFilter = !this.filter.canSaveFilter } // HANDLERS diff --git a/addons/mass_mailing/static/src/xml/mailing_filter_widget.xml b/addons/mass_mailing/static/src/xml/mailing_filter_widget.xml index 4b95ad89508..d72e39ffbae 100644 --- a/addons/mass_mailing/static/src/xml/mailing_filter_widget.xml +++ b/addons/mass_mailing/static/src/xml/mailing_filter_widget.xml @@ -24,7 +24,7 @@ - + diff --git a/addons/mass_mailing/static/tests/mass_mailing_favourite_filter_tests.js b/addons/mass_mailing/static/tests/mass_mailing_favourite_filter_tests.js index f268c6b02cd..3fee3a1552d 100644 --- a/addons/mass_mailing/static/tests/mass_mailing_favourite_filter_tests.js +++ b/addons/mass_mailing/static/tests/mass_mailing_favourite_filter_tests.js @@ -409,6 +409,44 @@ QUnit.module('favorite filter widget', (hooks) => { "should not have option to remove filter because mailing domain is changed"); }); + QUnit.test('filter widget does not raise traceback when losing focus with unexpected domain format', async (assert) => { + assert.expect(4); + + await makeView({ + type: "form", + resModel: "mailing.mailing", + resId: 2, + serverData, + arch: `
+ + + + + + + + + `, + }); + + // Initial state of icons with no filter + assert.isVisible(fixture.querySelector('.o_mass_mailing_save_filter_container'), + "should have option to save filter if no filter is set"); + assert.isNotVisible(fixture.querySelector('.o_mass_mailing_remove_filter')); + + // Set incorrect domain format + await testUtils.editInput(fixture, "div[name='mailing_domain'] input", "["); + // Wait to lose the focus + await testUtils.nextTick(); + + assert.isNotVisible(fixture.querySelector('.o_mass_mailing_save_filter_container'), + "should not have option to save filter if domain format is incorrect"); + assert.isNotVisible(fixture.querySelector('.o_mass_mailing_remove_filter'), + "should still not be visible"); + }); + QUnit.test('filter widget works in edit and readonly', async (assert) => { assert.expect(4);