[FIX] base: res_config_settings allow deferred field

If a deferred field, for example with auth_user_policy installed:

  <field name="f" password="True" widget="password_meter"/>

is inside the res_config_settings view, the rendering will be deferred
which is not taken into account when initializing the content
(_initModules) or attaching to DOM (after start).

Thus we would would get an error and have no access to settings.

The issue that happened in 12.0 was solved with 23bec7fb7 and refactored
in between in 5bbbd25ed, but the heart of the issue was not solved in
the case of a customization.

With this commit, we do not lose the deferred when it is necessary to
keep them in the case of deferred while rendering.

Without fix, the added test fails with a traceback and message:

 TypeError: Cannot read property 'settingView' of undefined

opw-1890343
closes #27589
This commit is contained in:
Nicolas Lempereur
2018-10-10 15:02:10 +00:00
parent c9041e8dcf
commit 5c6edfc8d3
2 changed files with 90 additions and 8 deletions
@@ -24,12 +24,13 @@ var BaseSettingRenderer = FormRenderer.extend({
},
start: function () {
this._super.apply(this, arguments);
var res = this._super.apply(this, arguments);
if (config.device.isMobile) {
core.bus.on("DOM_updated", this, function () {
this._moveToTab(this.currentIndex || this._currentAppIndex());
});
}
return res;
},
/**
@@ -266,14 +267,16 @@ var BaseSettingRenderer = FormRenderer.extend({
},
_render: function () {
var self = this;
var res = this._super.apply(this, arguments);
this._initModules();
this._renderLeftPanel();
this._initSearch();
if (config.device.isMobile) {
this._enableSwipe();
}
return res;
return res.then(function () {
self._initModules();
self._renderLeftPanel();
self._initSearch();
if (config.device.isMobile) {
self._enableSwipe();
}
});
},
_renderLeftPanel: function () {
@@ -1,9 +1,11 @@
odoo.define('base.settings_tests', function (require) {
"use strict";
var field_registry = require('web.field_registry');
var testUtils = require('web.test_utils');
var view_registry = require('web.view_registry');
var createAsyncView = testUtils.createAsyncView;
var createView = testUtils.createView;
var BaseSettingsView = view_registry.get('base_settings');
var createActionManager = testUtils.createActionManager;
@@ -178,5 +180,82 @@ QUnit.module('base_settings_tests', {
form.destroy();
});
QUnit.test('settings view works with deferred field', function (assert) {
assert.expect(7);
var def = $.Deferred();
testUtils.patch(field_registry.map.boolean, {
willStart: function () {
var res = this._super.apply(this, arguments);
return $.when(def, res);
}
});
createAsyncView({
View: BaseSettingsView,
model: 'project',
data: this.data,
arch: '<form string="Settings" class="oe_form_configuration o_base_settings">' +
'<div class="o_control_panel">' +
'<div class="o_panel">' +
'<div class="o_setting_search">' +
'<input type="text" class="searchInput" placeholder="Search..."/>' +
'<span class="searchIcon"><i class="fa fa-search" role="img" aria-label="Search" title="Search"/></span>' +
'</div> ' +
'</div> ' +
'<header>' +
'<button string="Save" type="object" name="execute" class="oe_highlight" />' +
'<button string="Cancel" type="object" name="cancel" class="oe_link" />' +
'</header>' +
'</div>' +
'<div class="o_setting_container">' +
'<div class="settings_tab"/>'+
'<div class="settings">' +
'<div class="notFound o_hidden">No Record Found</div>' +
'<div class="app_settings_block" string="CRM" data-key="crm">' +
'<div class="o_setting_left_pane">' +
'<field name="foo"/>'+
'</div>'+
'<div class="o_setting_right_pane">'+
'<label for="foo"/>'+
'<div class="text-muted">'+
'this is foo'+
'</div>'+
'</div>' +
'</div>' +
'<div class="app_settings_block" string="Other App" data-key="otherapp">' +
'<div class="o_setting_left_pane">' +
'<field name="bar"/>'+
'</div>'+
'<div class="o_setting_right_pane">'+
'<label for="bar"/>'+
'<div class="text-muted">'+
'this is bar'+
'</div>'+
'</div>' +
'</div>' +
'</div>' +
'</div>' +
'</form>',
}).then(function (form) {
assert.notOk(form.$('.oe_form_configuration').is(':empty'),
"render should finish once deferred fields are resolved");
assert.ok(form.$('.tab.selected').is('[data-key="crm"]'));
assert.ok(form.$('.tab').is('[data-key="otherapp"]'));
assert.ok(form.$('.app_settings_block[data-key="crm"]').is(':visible'));
assert.ok(form.$('.app_settings_block[data-key="otherapp"]').is(':hidden'));
assert.ok($(document.activeElement).is('.searchInput'), "search has focus");
form.destroy();
}).always(function () {
testUtils.unpatch(field_registry.map.boolean);
});
assert.strictEqual($('.oe_form_configuration').length, 0,
"view is not attached until deferred are resolved");
// resolve fields widget deferred so view is attached
def.resolve();
});
});
});