diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 76fcabe13f8..2620694b74b 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -717,14 +717,15 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM });}); }, on_invalid: function() { - var msg = ""; - this.do_warn("The following fields are invalid :", msg); + var warnings = _(this.fields).chain() + .filter(function (f) { return !f.is_valid(); }) + .map(function (f) { + return _.str.sprintf('
  • %s
  • ', + _.escape(f.node.attrs.string || f.field.string)); + }).value(); + warnings.unshift(''); + this.do_warn("The following fields are invalid :", warnings.join('')); }, on_saved: function(r, success) { if (!r.result) { diff --git a/addons/web/static/test/list-editable.js b/addons/web/static/test/list-editable.js index 62d9d82ae83..c96d50061b2 100644 --- a/addons/web/static/test/list-editable.js +++ b/addons/web/static/test/list-editable.js @@ -9,6 +9,64 @@ $(document).ready(function () { openerp.testing.mockifyRPC(instance); }; + + + /** + * + * @param {String} name + * @param {Object} [attrs] + * @param {String} [attrs.type="char"] + * @param {Boolean} [attrs.required] + * @param {Boolean} [attrs.invisible] + * @param {Boolean} [attrs.readonly] + * @return {Object} + */ + function field(name, attrs) { + attrs = attrs || {}; + attrs.name = name; + return _.defaults(attrs, { + type: 'char' + }); + } + + /** + * @param {Array} fields + * @return {Object} + */ + function makeFormView(fields) { + var fobj = {}; + _(fields).each(function (field) { + fobj[field.name] = { + type: field.type, + string: field.string + }; + }); + var children = _(fields).map(function (field) { + return { + tag: 'field', + attrs: { + name: field.name, + modifiers: JSON.stringify({ + required: field.required, + invisible: field.invisible, + readonly: field.readonly + }) + } + } + }); + return { + arch: { + tag: 'form', + attrs: { + version: '7.0', + 'class': 'oe_form_container' + }, + children: children + }, + fields: fobj + }; + } + module('editor', { setup: baseSetup }); @@ -16,16 +74,7 @@ $(document).ready(function () { var e = new instance.web.list.Editor({ dataset: {}, editionView: function () { - return { - arch: { - tag: 'form', - attrs: { - version: '7.0', - 'class': 'oe_form_container' - }, - children: [] - } - }; + return makeFormView(); } }); e.appendTo($fix) @@ -37,10 +86,10 @@ $(document).ready(function () { "should use default form type"); }); }); - asyncTest('toggle-edition-new', function () { + asyncTest('toggle-edition-save', 4, function () { instance.connection.responses['/web/dataset/call_kw:create'] = function () { return { result: 42 }; - }; + }; instance.connection.responses['/web/dataset/call_kw:read'] = function () { return { result: [{ id: 42, @@ -50,35 +99,13 @@ $(document).ready(function () { }]}; }; var e = new instance.web.list.Editor({ - do_warn: function (e) { - warning = e; - }, dataset: new instance.web.DataSetSearch(), isPrependOnCreate: function () { return false; }, editionView: function () { - return { - arch: { - tag: 'form', - attrs: { - version: '7.0', - 'class': 'oe_form_container' - }, - children: [ - {tag: 'field', attrs: {name: 'a'}}, - {tag: 'field', attrs: {name: 'b'}}, - {tag: 'field', attrs: {name: 'c'}} - ] - }, - fields: { - a: {type: 'char'}, - b: {type: 'char'}, - c: {type: 'char'} - } - }; + return makeFormView([ field('a'), field('b'), field('c') ]); } }); var counter = 0; - var warning = null; e.appendTo($fix) .pipe(function () { return e.edit(null, function () { @@ -86,17 +113,76 @@ $(document).ready(function () { }); }) .pipe(function (form) { - ok(e.isEditing(), "editor is now editing"); - equal(counter, 3, "all fields have been configured"); - strictEqual(form, e.form); + ok(e.isEditing(), "should be editing"); + equal(counter, 3, "should have configured all fields"); return e.save(); }) .always(start) .fail(function (error) { ok(false, error && error.message); }) .done(function (record) { - ok(!warning, "should have received no warning"); ok(!e.isEditing(), "should have stopped editing"); equal(record.id, 42, "should have newly created id"); }) }); + asyncTest('toggle-edition-cancel', 2, function () { + instance.connection.responses['/web/dataset/call_kw:create'] = function () { + return { result: 42 }; + }; + var e = new instance.web.list.Editor({ + dataset: new instance.web.DataSetSearch(), + isPrependOnCreate: function () { return false; }, + editionView: function () { + return makeFormView([ field('a'), field('b'), field('c') ]); + } + }); + var counter = 0; + e.appendTo($fix) + .pipe(function () { + return e.edit(null, function () { + ++counter; + }); + }) + .pipe(function (form) { + return e.cancel(); + }) + .always(start) + .fail(function (error) { ok(false, error && error.message); }) + .done(function (record) { + ok(!e.isEditing(), "should have stopped editing"); + ok(!record.id, "should have no id"); + }) + }); + asyncTest('toggle-save-required', 2, function () { + instance.connection.responses['/web/dataset/call_kw:create'] = function () { + return { result: 42 }; + }; + var e = new instance.web.list.Editor({ + do_warn: function () { + warnings++; + }, + dataset: new instance.web.DataSetSearch(), + isPrependOnCreate: function () { return false; }, + editionView: function () { + return makeFormView([ + field('a', {required: true}), field('b'), field('c') ]); + } + }); + var counter = 0; + var warnings = 0; + e.appendTo($fix) + .pipe(function () { + return e.edit(null, function () { + ++counter; + }); + }) + .pipe(function (form) { + return e.save(); + }) + .always(start) + .done(function () { ok(false, "cancel should not succeed"); }) + .fail(function () { + equal(warnings, 1, "should have been warned"); + ok(e.isEditing(), "should have kept editing"); + }) + }); });