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 = "
";
- _.each(this.fields, function(f) {
- if (!f.is_valid()) {
- msg += "- " + (f.node.attrs.string || f.field.string) + "
";
- }
- });
- 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");
+ })
+ });
});