diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js
index cc5f3d31ef5..462ea74ac89 100644
--- a/addons/web/static/tests/fields/relational_fields_tests.js
+++ b/addons/web/static/tests/fields/relational_fields_tests.js
@@ -415,7 +415,7 @@ QUnit.module('relational_fields', {
});
QUnit.test('onchanges on many2ones trigger when editing record in form view', function (assert) {
- assert.expect(9);
+ assert.expect(10);
this.data.partner.onchanges.user_id = function () {};
this.data.user.fields.other_field = {string: "Other Field", type: "char"};
@@ -454,12 +454,12 @@ QUnit.module('relational_fields', {
// save the modal and make sure an onchange is triggered
$('.modal .modal-footer .btn-primary').first().click();
- assert.verifySteps(['read', 'get_formview_id', 'read', 'write', 'onchange', 'read']);
+ assert.verifySteps(['read', 'get_formview_id', 'load_views', 'read', 'write', 'onchange', 'read']);
// save the main record, and check that no extra rpcs are done (record
// is not dirty, only a related record was modified)
form.$buttons.find('.o_form_button_save').click();
- assert.verifySteps(['read', 'get_formview_id', 'read', 'write', 'onchange', 'read']);
+ assert.verifySteps(['read', 'get_formview_id', 'load_views', 'read', 'write', 'onchange', 'read']);
form.destroy();
});
@@ -5902,7 +5902,7 @@ QUnit.module('relational_fields', {
// should omit require fields that aren't in the view as they (obviously)
// have no value, when checking the validity of required fields
// shouldn't consider numerical fields with value 0 as unset
- assert.expect(11);
+ assert.expect(12);
this.data.turtle.fields.turtle_foo.required = true;
this.data.turtle.fields.turtle_qux.required = true; // required field not in the view
@@ -5951,13 +5951,13 @@ QUnit.module('relational_fields', {
form.$('.o_field_x2many_list_row_add a').click();
assert.strictEqual(form.$('.o_field_widget[name="int_field"]').val(), "0",
"int_field should still be 0 (no onchange should have been done yet)");
- assert.verifySteps(['read', 'default_get'], "no onchange should have been applied");
+ assert.verifySteps(['load_views', 'read', 'default_get'], "no onchange should have been applied");
// fill turtle_foo field
form.$('.o_field_widget[name="turtle_foo"]').val("some text").trigger('input');
assert.strictEqual(form.$('.o_field_widget[name="int_field"]').val(), "0",
"int_field should still be 0 (no onchange should have been done yet)");
- assert.verifySteps(['read', 'default_get'], "no onchange should have been applied");
+ assert.verifySteps(['load_views', 'read', 'default_get'], "no onchange should have been applied");
// fill partner_ids field with a tag (all required fields will then be set)
var $m2mInput = form.$('.o_field_widget[name=partner_ids] input');
@@ -7140,7 +7140,9 @@ QUnit.module('relational_fields', {
},
res_id: 1,
mockRPC: function (route, args) {
- assert.step(_.last(route.split('/')));
+ if (args.method !== 'load_views') {
+ assert.step(_.last(route.split('/')));
+ }
if (args.method === 'write' && args.model === 'partner') {
assert.deepEqual(args.args[1].timmy, [
[6, false, [12, 15]],
@@ -7238,7 +7240,9 @@ QUnit.module('relational_fields', {
'partner_type,false,search': '',
},
mockRPC: function (route, args) {
- assert.step(_.last(route.split('/')));
+ if (args.method !== 'load_views') {
+ assert.step(_.last(route.split('/')));
+ }
if (args.method === 'write') {
assert.deepEqual(args.args[1].timmy, [
[6, false, [12, 15]],
@@ -7544,7 +7548,9 @@ QUnit.module('relational_fields', {
'',
},
mockRPC: function (route, args) {
- assert.step(_.last(route.split('/')) + ' on ' + args.model);
+ if (args.method !== 'load_views') {
+ assert.step(_.last(route.split('/')) + ' on ' + args.model);
+ }
if (args.model === 'turtle') {
assert.step(args.args[0]); // the read ids
}
@@ -7629,7 +7635,7 @@ QUnit.module('relational_fields', {
});
QUnit.test('many2many list with onchange and edition of a record', function (assert) {
- assert.expect(7);
+ assert.expect(8);
this.data.partner.fields.turtles.type = "many2many";
this.data.partner.onchanges.turtles = function () {};
@@ -7666,6 +7672,7 @@ QUnit.module('relational_fields', {
assert.verifySteps([
'read', // read initial record (on partner)
'read', // read many2many turtles
+ 'load_views', // load arch of turtles form view
'read', // read missing field when opening record in modal form view
'write', // when saving the modal
'onchange', // onchange should be triggered on partner
diff --git a/addons/web/static/tests/helpers/mock_server.js b/addons/web/static/tests/helpers/mock_server.js
index 9ce15568d46..4bc58dd097d 100644
--- a/addons/web/static/tests/helpers/mock_server.js
+++ b/addons/web/static/tests/helpers/mock_server.js
@@ -12,11 +12,14 @@ var MockServer = Class.extend({
* @constructor
* @param {Object} data
* @param {Object} options
+ * @param {Object} [options.archs={}] dict of archs with keys being strings like
+ * 'model,id,viewType'
* @param {boolean} [options.debug=false] logs RPCs if set to true
* @param {string} [options.currentDate] formatted string, default to
* current day
*/
init: function (data, options) {
+ options = options || {};
this.data = data;
for (var modelName in this.data) {
var model = this.data[modelName];
@@ -40,9 +43,11 @@ var MockServer = Class.extend({
}
}
- this.debug = options && options.debug;
+ this.debug = options.debug;
this.currentDate = options.currentDate || moment().format("YYYY-MM-DD");
+
+ this.archs = options.archs || {};
},
//--------------------------------------------------------------------------
@@ -426,6 +431,38 @@ var MockServer = Class.extend({
}
return modelFields;
},
+ /**
+ * Simulate a 'load_views' operation
+ *
+ * @param {string} model
+ * @param {Array} args
+ * @param {Object} kwargs
+ * @param {Array} kwargs.views
+ * @param {Object} kwargs.options
+ * @param {Object} kwargs.context
+ * @returns {Object}
+ */
+ _mockLoadViews: function (model, kwargs) {
+ var self = this;
+ var views = {};
+ _.each(kwargs.views, function (view_descr) {
+ var viewID = view_descr[0] || false;
+ var viewType = view_descr[1];
+ var key = [model, viewID, viewType].join(',');
+ var arch = self.archs[key];
+ if (!arch) {
+ throw new Error('No arch found for key ' + key);
+ }
+ views[viewType] = {
+ arch: arch,
+ model: model,
+ viewOptions: {
+ context: kwargs.context,
+ },
+ };
+ });
+ return views;
+ },
/**
* Simulate a 'name_get' operation
*
@@ -927,6 +964,9 @@ var MockServer = Class.extend({
case 'fields_get':
return $.when(this._mockFieldsGet(args.model, args.args));
+ case 'load_views':
+ return $.when(this._mockLoadViews(args.model, args.kwargs));
+
case 'name_get':
return $.when(this._mockNameGet(args.model, args.args));
diff --git a/addons/web/static/tests/helpers/test_utils.js b/addons/web/static/tests/helpers/test_utils.js
index d8a03783288..33b29622ea7 100644
--- a/addons/web/static/tests/helpers/test_utils.js
+++ b/addons/web/static/tests/helpers/test_utils.js
@@ -245,6 +245,7 @@ function addMockEnvironment(widget, params) {
console.log('%c[debug] debug mode activated', 'color: blue; font-weight: bold;', url);
}
var mockServer = new Server(params.data, {
+ archs: params.archs,
currentDate: params.currentDate,
debug: params.debug,
});
@@ -313,30 +314,21 @@ function addMockEnvironment(widget, params) {
});
intercept(widget, "load_views", function (event) {
- if (params.debug) {
- console.log('[mock] load_views', event.data);
- }
- var views = {};
- var model = event.data.modelName;
- _.each(event.data.views, function (view_descr) {
- var view_id = view_descr[0] || false;
- var view_type = view_descr[1];
- var key = [model, view_id, view_type].join(',');
- var arch = params.archs[key];
- var viewParams = {
- arch: arch,
- model: model,
- viewOptions: {
- context: event.data.context.eval(),
- },
- };
- if (!arch) {
- throw new Error('No arch found for key ' + key);
- }
- views[view_type] = mockServer.fieldsViewGet(viewParams);
+ mockServer.performRpc('/web/dataset/call_kw/' + event.data.modelName, {
+ args: [],
+ kwargs: {
+ context: event.data.context.eval(),
+ options: event.data.options,
+ views: event.data.views,
+ },
+ method: 'load_views',
+ model: event.data.modelName,
+ }).then(function (views) {
+ views = _.mapObject(views, function (viewParams) {
+ return mockServer.fieldsViewGet(viewParams);
+ });
+ event.data.on_success(views);
});
-
- event.data.on_success(views);
});
intercept(widget, "get_session", function (event) {
diff --git a/addons/web/static/tests/views/form_tests.js b/addons/web/static/tests/views/form_tests.js
index bf88a921b67..4067a2d4c39 100644
--- a/addons/web/static/tests/views/form_tests.js
+++ b/addons/web/static/tests/views/form_tests.js
@@ -4272,7 +4272,7 @@ QUnit.module('Views', {
});
QUnit.test('open one2many form containing one2many', function (assert) {
- assert.expect(8);
+ assert.expect(9);
this.data.partner.records[0].product_ids = [37];
this.data.product.fields.partner_type_ids = {
@@ -4326,7 +4326,7 @@ QUnit.module('Views', {
"the row should contains the 2 fields defined in the form view");
assert.strictEqual($(modal_row).text(), "gold2",
"the value of the fields should be fetched and displayed");
- assert.verifySteps(['read', 'read', 'read', 'read'],
+ assert.verifySteps(['read', 'read', 'load_views', 'read', 'read'],
"there should be 4 read rpcs");
form.destroy();
});
@@ -5905,7 +5905,7 @@ QUnit.module('Views', {
// parent view. If this event isn't stopPropagated by the first controller
// catching it, it will crash when the other one will try to handle it,
// as this one doesn't know at all the dataPointID to reload.
- assert.expect(9);
+ assert.expect(11);
var arch = '