[TEST] start adding some testing to new editable listview, validate structure of...
authorXavier Morel <xmo@openerp.com>
Wed, 4 Jul 2012 09:56:26 +0000 (11:56 +0200)
committerXavier Morel <xmo@openerp.com>
Wed, 4 Jul 2012 09:56:26 +0000 (11:56 +0200)
bzr revid: xmo@openerp.com-20120704095626-j7wtbgdmoti0kjie

addons/web/static/src/js/view_list_editable.js
addons/web/static/src/js/views.js
addons/web/static/test/list-editable.js [new file with mode: 0644]
addons/web/static/test/test.html
doc/list-view.rst

index 197cb3d..a02383a 100644 (file)
@@ -50,11 +50,12 @@ openerp.web.list_editable = function (instance) {
          * @param {Boolean} [force] forces the list to editability. Sets new row edition status to "bottom".
          */
         set_editable: function (force) {
+            // TODO: fix handling of editability status to be simpler & clearer & more coherent
             // If ``force``, set editability to bottom
             // otherwise rely on view default
             // view' @editable is handled separately as we have not yet
             // fetched and processed the view at this point.
-            this.options.editable = true || (
+            this.options.editable = (
                     ! this.options.read_only && ((force && "bottom") || this.defaults.editable));
         },
         /**
@@ -82,7 +83,7 @@ openerp.web.list_editable = function (instance) {
             // tree/@editable takes priority on everything else if present.
             this.options.editable = ! this.options.read_only && (data.arch.attrs.editable || this.options.editable);
             var result = this._super(data, grouped);
-            if (this.options.editable || true) {
+            if (this.options.editable) {
                 this.editor = new instance.web.list.Editor(this);
 
                 var editor_ready = this.editor.prependTo(this.$element)
@@ -168,6 +169,7 @@ openerp.web.list_editable = function (instance) {
          */
         saveEdition: function () {
             var self = this;
+            // TODO: save:after should be invoked after reload
             return this.withEvent('save', {
                 editor: this.editor,
                 form: this.editor.form,
@@ -349,16 +351,44 @@ openerp.web.list_editable = function (instance) {
         start: function () {
             var self = this;
             var _super = this._super();
-            this.form.embedded_view = this.delegate.editionView(this);
+            this.form.embedded_view = this._validateView(
+                    this.delegate.editionView(this));
             var form_ready = this.form.appendTo(this.$element).then(
                 self.form.proxy('do_hide'));
             return $.when(_super, form_ready);
         },
+        _validateView: function (edition_view) {
+            if (!edition_view) {
+                throw new Error("editor delegate's #editionView must return "
+                              + "a view descriptor");
+            }
+            var arch = edition_view.arch;
+            if (!(arch && arch.children instanceof Array)) {
+                throw new Error("Editor delegate's #editionView must have a" +
+                                " non-empty arch")
+            }
+            if (!(arch.tag === "form")) {
+                throw new Error("Editor delegate's #editionView must have a" +
+                                " 'form' root node");
+            }
+            if (!(arch.attrs && arch.attrs.version === "7.0")) {
+                throw new Error("Editor delegate's #editionView must be a" +
+                                " version 7 view");
+            }
+            if (!/\boe_form_container\b/.test(arch.attrs['class'])) {
+                throw new Error("Editor delegate's #editionView must have the" +
+                                " class 'oe_form_container' on its root" +
+                                " element");
+            }
+
+            return edition_view;
+        },
 
         isEditing: function () {
             return !!this.record;
         },
         edit: function (record, configureField) {
+            // TODO: specify sequence of edit calls
             var self = this;
             var form = self.form;
             record = _.extend({}, record);
index e82d3d0..35901e9 100644 (file)
@@ -1238,7 +1238,9 @@ instance.web.json_node_to_xml = function(node, human_readable, indent) {
     if (typeof(node) === 'string') {
         return sindent + node;
     } else if (typeof(node.tag) !== 'string' || !node.children instanceof Array || !node.attrs instanceof Object) {
-        throw("Node a json node");
+        throw new Error(
+            _.str.sprintf("Node [%s] is not a JSONified XML node",
+                          JSON.stringify(node)));
     }
     for (var attr in node.attrs) {
         var vattr = node.attrs[attr];
diff --git a/addons/web/static/test/list-editable.js b/addons/web/static/test/list-editable.js
new file mode 100644 (file)
index 0000000..6ac3d96
--- /dev/null
@@ -0,0 +1,71 @@
+$(document).ready(function () {
+    var $fix = $('#qunit-fixture');
+    var xhr = QWeb2.Engine.prototype.get_xhr();
+    xhr.open('GET', '/web/static/src/xml/base.xml', false);
+    xhr.send(null);
+    var doc = xhr.responseXML;
+
+    var noop = function () {};
+    /**
+     * Make connection RPC responses mockable by setting keys on the
+     * Connection#responses object (key is the URL, value is the function to
+     * call with the RPC request payload)
+     *
+     * @param {openerp.web.Connection} connection connection instance to mockify
+     * @param {Object} [responses] url:function mapping to seed the mock connection
+     */
+    var mockifyRPC = function (connection, responses) {
+        connection.responses = responses || {};
+        connection.rpc_function = function (url, payload) {
+            if (!(url.url in this.responses)) {
+                return $.Deferred().reject({}, 'failed', _.str.sprintf("Url %s not found in mock responses", url.url)).promise();
+            }
+            return $.when(this.responses[url.url](payload));
+        };
+    };
+
+    var instance;
+    var baseSetup = function () {
+        instance = window.openerp.init([]);
+        window.openerp.web.corelib(instance);
+        window.openerp.web.coresetup(instance);
+        window.openerp.web.chrome(instance);
+        window.openerp.web.data(instance);
+        window.openerp.web.views(instance);
+        window.openerp.web.list(instance);
+        window.openerp.web.form(instance);
+        window.openerp.web.list_editable(instance);
+
+        instance.web.qweb.add_template(doc);
+
+        mockifyRPC(instance.connection);
+    };
+    module('editor', {
+        setup: baseSetup
+    });
+    asyncTest('base-state', 2, function () {
+        var e = new instance.web.list.Editor({
+            dataset: {},
+            editionView: function () {
+                return {
+                    arch: {
+                        tag: 'form',
+                        attrs: {
+                            version: '7.0',
+                            'class': 'oe_form_container'
+                        },
+                        children: []
+                    }
+                };
+            }
+        });
+        e.appendTo($fix)
+            .always(start)
+            .fail(function (error) { ok(false, error && error.message); })
+            .done(function () {
+                ok(!e.isEditing(), "should not be editing");
+                ok(e.form instanceof instance.web.FormView,
+                   "should use default form type");
+            });
+    });
+});
index e352f63..f06d68e 100644 (file)
@@ -38,6 +38,7 @@
     <script src="/web/static/src/js/search.js"></script>
     <script src="/web/static/src/js/view_form.js"></script>
     <script src="/web/static/src/js/view_list.js"></script>
+    <script src="/web/static/src/js/view_list_editable.js"></script>
 </head>
     <body id="oe" class="openerp">
         <h1 id="qunit-header">OpenERP web Test Suite</h1>
@@ -55,4 +56,5 @@
     <script type="text/javascript" src="/web/static/test/rpc.js"></script>
     <script type="text/javascript" src="/web/static/test/evals.js"></script>
     <script type="text/javascript" src="/web/static/test/search.js"></script>
+    <script type="text/javascript" src="/web/static/test/list-editable.js"></script>
 </html>
index e71c6a8..28f22ab 100644 (file)
@@ -163,9 +163,6 @@ view provides a number of dedicated events to its lifecycle.
 
     Invoked after a save has been completed
 
-    .. todo:: currently invoked before the record has reloaded, which
-              is kinda shitty
-
 ``cancel:before`` *cancellable*
 
     Invoked before cancelling a pending edition, provided with the
@@ -193,8 +190,6 @@ formview, delegating instead to its
     e.g. :js:func:`~openerp.web.list.Editor.edit` multiple times in a
     row without saving or cancelling each edit is undefined.
 
-    .. todo:: define this behavior
-
     :param parent:
     :type parent: :js:class:`~openerp.web.Widget`
     :param EditorOptions options: