diff options
| author | Olivier Dony <odo@openerp.com> | 2012-10-01 16:53:08 +0200 |
|---|---|---|
| committer | Olivier Dony <odo@openerp.com> | 2012-10-01 16:53:08 +0200 |
| commit | 9e6920415e41a052cffa7b898bf044dbf82b5ccb (patch) | |
| tree | 05e8d64788da1ff9f65e7406e3ff3d96d58a5762 /addons/web/static/test | |
| parent | 4ed79f3457a0252dcee4780385dc474ff2af356e (diff) | |
| parent | 1370ae133d4477d0a7a2239732f529a1eef39824 (diff) | |
[MERGE] Sync with trunk
bzr revid: odo@openerp.com-20121001145308-ri5rp2cazxqxcxme
Diffstat (limited to 'addons/web/static/test')
| -rw-r--r-- | addons/web/static/test/Widget.js | 239 | ||||
| -rw-r--r-- | addons/web/static/test/evals.js | 20 | ||||
| -rw-r--r-- | addons/web/static/test/fulltest.html | 12 | ||||
| -rw-r--r-- | addons/web/static/test/fulltest/dataset.js | 30 | ||||
| -rw-r--r-- | addons/web/static/test/list-editable.js | 349 | ||||
| -rw-r--r-- | addons/web/static/test/list-utils.js | 121 | ||||
| -rw-r--r-- | addons/web/static/test/registry.js | 15 | ||||
| -rw-r--r-- | addons/web/static/test/search.js | 227 | ||||
| -rw-r--r-- | addons/web/static/test/test.html | 18 | ||||
| -rw-r--r-- | addons/web/static/test/testing.js | 97 |
10 files changed, 968 insertions, 160 deletions
diff --git a/addons/web/static/test/Widget.js b/addons/web/static/test/Widget.js new file mode 100644 index 00000000000..3e6cc262565 --- /dev/null +++ b/addons/web/static/test/Widget.js @@ -0,0 +1,239 @@ +$(document).ready(function () { + var $fix = $('#qunit-fixture'); + var mod = { + setup: function () { + instance = window.openerp.init([]); + window.openerp.web.corelib(instance); + + instance.web.qweb = new QWeb2.Engine(); + instance.web.qweb.add_template( + '<no>' + + '<t t-name="test.widget.template">' + + '<ol>' + + '<li t-foreach="5" t-as="counter" ' + + 't-attf-class="class-#{counter}">' + + '<input/>' + + '<t t-esc="counter"/>' + + '</li>' + + '</ol>' + + '</t>' + + '<t t-name="test.widget.template-value">' + + '<p><t t-esc="widget.value"/></p>' + + '</t>' + + '</no>'); + } + }; + var instance; + + module('Widget.proxy', mod); + test('(String)', function () { + var W = instance.web.Widget.extend({ + exec: function () { + this.executed = true; + } + }); + var w = new W; + var fn = w.proxy('exec'); + fn(); + ok(w.executed, 'should execute the named method in the right context'); + }); + test('(String)(*args)', function () { + var W = instance.web.Widget.extend({ + exec: function (arg) { + this.executed = arg; + } + }); + var w = new W; + var fn = w.proxy('exec'); + fn(42); + ok(w.executed, "should execute the named method in the right context"); + equal(w.executed, 42, "should be passed the proxy's arguments"); + }); + test('(String), include', function () { + // the proxy function should handle methods being changed on the class + // and should always proxy "by name", to the most recent one + var W = instance.web.Widget.extend({ + exec: function () { + this.executed = 1; + } + }); + var w = new W; + var fn = w.proxy('exec'); + W.include({ + exec: function () { this.executed = 2; } + }); + + fn(); + equal(w.executed, 2, "should be lazily resolved"); + }); + + test('(Function)', function () { + var w = new (instance.web.Widget.extend({ })); + + var fn = w.proxy(function () { this.executed = true; }); + fn(); + ok(w.executed, "should set the function's context (like Function#bind)"); + }); + test('(Function)(*args)', function () { + var w = new (instance.web.Widget.extend({ })); + + var fn = w.proxy(function (arg) { this.executed = arg; }); + fn(42); + equal(w.executed, 42, "should be passed the proxy's arguments"); + }); + + module('Widget.renderElement', mod); + test('no template, default', function () { + var w = new (instance.web.Widget.extend({ })); + + var $original = w.$el; + ok($original, "should initially have a root element"); + w.renderElement(); + ok(w.$el, "should have generated a root element"); + ok($original !== w.$el, "should have generated a new root element"); + strictEqual(w.$el, w.$el, "should provide $el alias"); + ok(w.$el.is(w.el), "should provide raw DOM alias"); + + equal(w.el.nodeName, 'DIV', "should have generated the default element"); + equal(w.el.attributes.length, 0, "should not have generated any attribute"); + ok(_.isEmpty(w.$el.html(), "should not have generated any content")); + }); + test('no template, custom tag', function () { + var w = new (instance.web.Widget.extend({ + tagName: 'ul' + })); + w.renderElement(); + + equal(w.el.nodeName, 'UL', "should have generated the custom element tag"); + }); + test('no template, @id', function () { + var w = new (instance.web.Widget.extend({ + id: 'foo' + })); + w.renderElement(); + + equal(w.el.attributes.length, 1, "should have one attribute"); + equal(w.$el.attr('id'), 'foo', "should have generated the id attribute"); + equal(w.el.id, 'foo', "should also be available via property"); + }); + test('no template, @className', function () { + var w = new (instance.web.Widget.extend({ + className: 'oe_some_class' + })); + w.renderElement(); + + equal(w.el.className, 'oe_some_class', "should have the right property"); + equal(w.$el.attr('class'), 'oe_some_class', "should have the right attribute"); + }); + test('no template, bunch of attributes', function () { + var w = new (instance.web.Widget.extend({ + attributes: { + 'id': 'some_id', + 'class': 'some_class', + 'data-foo': 'data attribute', + 'clark': 'gable', + 'spoiler': 'snape kills dumbledore' + } + })); + w.renderElement(); + + equal(w.el.attributes.length, 5, "should have all the specified attributes"); + + equal(w.el.id, 'some_id'); + equal(w.$el.attr('id'), 'some_id'); + + equal(w.el.className, 'some_class'); + equal(w.$el.attr('class'), 'some_class'); + + equal(w.$el.attr('data-foo'), 'data attribute'); + equal(w.$el.data('foo'), 'data attribute'); + + equal(w.$el.attr('clark'), 'gable'); + equal(w.$el.attr('spoiler'), 'snape kills dumbledore'); + }); + + test('template', function () { + var w = new (instance.web.Widget.extend({ + template: 'test.widget.template' + })); + w.renderElement(); + + equal(w.el.nodeName, 'OL'); + equal(w.$el.children().length, 5); + equal(w.el.textContent, '01234'); + }); + + module('Widget.$', mod); + test('basic-alias', function () { + var w = new (instance.web.Widget.extend({ + template: 'test.widget.template' + })); + w.renderElement(); + + ok(w.$('li:eq(3)').is(w.$el.find('li:eq(3)')), + "should do the same thing as calling find on the widget root"); + }); + + module('Widget.events', mod); + test('delegate', function () { + var a = []; + var w = new (instance.web.Widget.extend({ + template: 'test.widget.template', + events: { + 'click': function () { + a[0] = true; + strictEqual(this, w, "should trigger events in widget") + }, + 'click li.class-3': 'class3', + 'change input': function () { a[2] = true; } + }, + class3: function () { a[1] = true; } + })); + w.renderElement(); + + w.$el.click(); + w.$('li:eq(3)').click(); + w.$('input:last').val('foo').change(); + + for(var i=0; i<3; ++i) { + ok(a[i], "should pass test " + i); + } + }); + test('undelegate', function () { + var clicked = false, newclicked = false; + var w = new (instance.web.Widget.extend({ + template: 'test.widget.template', + events: { 'click li': function () { clicked = true; } } + })); + w.renderElement(); + w.$el.on('click', 'li', function () { newclicked = true }); + + w.$('li').click(); + ok(clicked, "should trigger bound events"); + ok(newclicked, "should trigger bound events"); + clicked = newclicked = false; + + w.undelegateEvents(); + w.$('li').click(); + ok(!clicked, "undelegate should unbind events delegated"); + ok(newclicked, "undelegate should only unbind events it created"); + }); + + module('Widget.renderElement', mod); + asyncTest('repeated', 4, function () { + var w = new (instance.web.Widget.extend({ + template: 'test.widget.template-value' + })); + w.value = 42; + w.appendTo($fix) + .always(start) + .done(function () { + equal($fix.find('p').text(), '42', "DOM fixture should contain initial value"); + equal(w.$el.text(), '42', "should set initial value"); + w.value = 36; + w.renderElement(); + equal($fix.find('p').text(), '36', "DOM fixture should use new value"); + equal(w.$el.text(), '36', "should set new value"); + }); + }); +}); diff --git a/addons/web/static/test/evals.js b/addons/web/static/test/evals.js index 290a009f46d..757d98c5bcc 100644 --- a/addons/web/static/test/evals.js +++ b/addons/web/static/test/evals.js @@ -12,7 +12,7 @@ $(document).ready(function () { // Context n should have base evaluation context + all of contexts // 0..n-1 in its own evaluation context var active_id = 4; - var result = openerp.connection.test_eval_contexts([ + var result = openerp.session.test_eval_contexts([ { "__contexts": [ { @@ -56,7 +56,7 @@ $(document).ready(function () { }); }); test('non-literal_eval_contexts', function () { - var result = openerp.connection.test_eval_contexts([{ + var result = openerp.session.test_eval_contexts([{ "__ref": "compound_context", "__contexts": [ {"__ref": "context", "__debug": "{'type':parent.type}", @@ -133,4 +133,20 @@ $(document).ready(function () { }]); deepEqual(result, {type: 'out_invoice'}); }); + module('eval.domains', { + setup: function () { + openerp = window.openerp.testing.instanceFor('coresetup'); + window.openerp.web.dates(openerp); + } + }); + test('current_date', function () { + var current_date = openerp.web.date_to_str(new Date()); + var result = openerp.session.test_eval_domains( + [[],{"__ref":"domain","__debug":"[('name','>=',current_date),('name','<=',current_date)]","__id":"5dedcfc96648"}], + openerp.session.test_eval_get_context()); + deepEqual(result, [ + ['name', '>=', current_date], + ['name', '<=', current_date] + ]); + }) }); diff --git a/addons/web/static/test/fulltest.html b/addons/web/static/test/fulltest.html index a031325966a..2917b246b8d 100644 --- a/addons/web/static/test/fulltest.html +++ b/addons/web/static/test/fulltest.html @@ -2,7 +2,7 @@ <html style="height: 100%"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> - <title>OpenERP</title> + <title>OpenERP Web Full Stack</title> <link rel="shortcut icon" href="/web/static/src/img/favicon.ico" type="image/x-icon"/> <link rel="stylesheet" href="/web/static/lib/qunit/qunit.css"> @@ -12,7 +12,7 @@ <script src="/web/static/lib/underscore/underscore.string.js" type="text/javascript"></script> <!-- jquery --> - <script src="/web/static/lib/jquery/jquery-1.6.4.js"></script> + <script src="/web/static/lib/jquery/jquery-1.7.2.js"></script> <script src="/web/static/lib/jquery.ui/js/jquery-ui-1.8.17.custom.min.js"></script> <script src="/web/static/lib/jquery.ba-bbq/jquery.ba-bbq.js"></script> @@ -37,13 +37,7 @@ <script src="/web/static/src/js/test_support.js"></script> </head> <body id="oe" class="openerp"> - <h1 id="qunit-header"> - OpenERP Web Test Suite: javascript to XML-RPC (excluded) - </h1> - <h2 id="qunit-banner"></h2> - <div id="qunit-testrunner-toolbar"></div> - <h2 id="qunit-userAgent"></h2> - <ol id="qunit-tests"></ol> + <div id="qunit"></div> <div id="qunit-fixture"></div> <script type="text/javascript" src="/web/static/test/fulltest/dataset.js"></script> </body> diff --git a/addons/web/static/test/fulltest/dataset.js b/addons/web/static/test/fulltest/dataset.js index 9f7ab101869..d276f4e2494 100644 --- a/addons/web/static/test/fulltest/dataset.js +++ b/addons/web/static/test/fulltest/dataset.js @@ -7,7 +7,7 @@ $(document).ready(function () { t.module('Dataset shortcuts', 'data'); t.test('read_index', function (openerp) { var ds = new openerp.web.DataSet( - {session: openerp.connection}, 'some.model'); + {session: openerp.session}, 'some.model'); ds.ids = [10, 20, 30, 40, 50]; ds.index = 2; t.expect(ds.read_index(['a', 'b', 'c']), function (result) { @@ -24,7 +24,7 @@ $(document).ready(function () { }); t.test('default_get', function (openerp) { var ds = new openerp.web.DataSet( - {session: openerp.connection}, 'some.model', {foo: 'bar'}); + {session: openerp.session}, 'some.model', {foo: 'bar'}); t.expect(ds.default_get(['a', 'b', 'c']), function (result) { strictEqual(result.method, 'default_get'); strictEqual(result.model, 'some.model'); @@ -38,7 +38,7 @@ $(document).ready(function () { }); }); t.test('create', function (openerp) { - var ds = new openerp.web.DataSet({session: openerp.connection}, 'some.model'); + var ds = new openerp.web.DataSet({session: openerp.session}, 'some.model'); t.expect(ds.create({foo: 1, bar: 2}), function (r) { strictEqual(r.method, 'create'); @@ -51,7 +51,7 @@ $(document).ready(function () { }); }); t.test('write', function (openerp) { - var ds = new openerp.web.DataSet({session: openerp.connection}, 'mod'); + var ds = new openerp.web.DataSet({session: openerp.session}, 'mod'); t.expect(ds.write(42, {foo: 1}), function (r) { strictEqual(r.method, 'write'); @@ -69,7 +69,7 @@ $(document).ready(function () { // }); }); t.test('unlink', function (openerp) { - var ds = new openerp.web.DataSet({session: openerp.connection}, 'mod'); + var ds = new openerp.web.DataSet({session: openerp.session}, 'mod'); t.expect(ds.unlink([42]), function (r) { strictEqual(r.method, 'unlink'); @@ -81,7 +81,7 @@ $(document).ready(function () { }); }); t.test('call', function (openerp) { - var ds = new openerp.web.DataSet({session: openerp.connection}, 'mod'); + var ds = new openerp.web.DataSet({session: openerp.session}, 'mod'); t.expect(ds.call('frob', ['a', 'b', 42]), function (r) { strictEqual(r.method, 'frob'); @@ -91,8 +91,8 @@ $(document).ready(function () { ok(_.isEmpty(r.kwargs)); }); }); - t.test('name_get', function (openerp) { - var ds = new openerp.web.DataSet({session: openerp.connection}, 'mod'); + t.test('name_get').then(function (openerp) { + var ds = new openerp.web.DataSet({session: openerp.session}, 'mod'); t.expect(ds.name_get([1, 2], null), function (r) { strictEqual(r.method, 'name_get'); @@ -104,7 +104,7 @@ $(document).ready(function () { }); }); t.test('name_search, name', function (openerp) { - var ds = new openerp.web.DataSet({session: openerp.connection}, 'mod'); + var ds = new openerp.web.DataSet({session: openerp.session}, 'mod'); t.expect(ds.name_search('bob'), function (r) { strictEqual(r.method, 'name_search'); @@ -119,7 +119,7 @@ $(document).ready(function () { }); }); t.test('name_search, domain & operator', function (openerp) { - var ds = new openerp.web.DataSet({session: openerp.connection}, 'mod'); + var ds = new openerp.web.DataSet({session: openerp.session}, 'mod'); t.expect(ds.name_search(0, [['foo', '=', 3]], 'someop'), function (r) { strictEqual(r.method, 'name_search'); @@ -134,7 +134,7 @@ $(document).ready(function () { }); }); t.test('exec_workflow', function (openerp) { - var ds = new openerp.web.DataSet({session: openerp.connection}, 'mod'); + var ds = new openerp.web.DataSet({session: openerp.session}, 'mod'); t.expect(ds.exec_workflow(42, 'foo'), function (r) { strictEqual(r['service'], 'object'); strictEqual(r.method, 'exec_workflow'); @@ -147,7 +147,7 @@ $(document).ready(function () { }); t.test('DataSetSearch#read_slice', function (openerp) { - var ds = new openerp.web.DataSetSearch({session: openerp.connection}, 'mod'); + var ds = new openerp.web.DataSetSearch({session: openerp.session}, 'mod'); t.expect(ds.read_slice(['foo', 'bar'], { domain: [['foo', '>', 42], ['qux', '=', 'grault']], context: {peewee: 'herman'}, @@ -167,7 +167,7 @@ $(document).ready(function () { }); }); t.test('DataSetSearch#read_slice sorted', function (openerp) { - var ds = new openerp.web.DataSetSearch({session: openerp.connection}, 'mod'); + var ds = new openerp.web.DataSetSearch({session: openerp.session}, 'mod'); ds.sort('foo'); ds.sort('foo'); ds.sort('bar'); @@ -194,7 +194,7 @@ $(document).ready(function () { }); t.test('Dataset', function (openerp) { var ds = new openerp.web.DataSetSearch( - {session: openerp.connection}, 'mod'); + {session: openerp.session}, 'mod'); var c = new openerp.web.CompoundContext( {a: 'foo', b: 3, c: 5}, openerp.contexts[0]); t.expect(ds.read_slice(['foo', 'bar'], { @@ -220,7 +220,7 @@ $(document).ready(function () { parent: {model: 'qux'} }; var ds = new openerp.web.DataSet( - {session: openerp.connection}, 'mod', + {session: openerp.session}, 'mod', new openerp.web.CompoundContext({}) .set_eval_context(eval_context)); var domain = new openerp.web.CompoundDomain(openerp.domains[0]) diff --git a/addons/web/static/test/list-editable.js b/addons/web/static/test/list-editable.js new file mode 100644 index 00000000000..0388e56048d --- /dev/null +++ b/addons/web/static/test/list-editable.js @@ -0,0 +1,349 @@ +$(document).ready(function () { + var $fix = $('#qunit-fixture'); + + var instance; + var baseSetup = function () { + instance = openerp.testing.instanceFor('list_editable'); + + openerp.testing.loadTemplate(instance); + + 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 + }); + asyncTest('base-state', 2, function () { + var e = new instance.web.list.Editor({ + dataset: {ids: []}, + edition_view: function () { + return makeFormView(); + } + }); + e.appendTo($fix) + .always(start) + .fail(function (error) { ok(false, error && error.message); }) + .done(function () { + ok(!e.is_editing(), "should not be editing"); + ok(e.form instanceof instance.web.FormView, + "should use default form type"); + }); + }); + asyncTest('toggle-edition-save', 4, function () { + instance.session.responses['/web/dataset/call_kw:create'] = function () { + return { result: 42 }; + }; + instance.session.responses['/web/dataset/call_kw:read'] = function () { + return { result: [{ + id: 42, + a: false, + b: false, + c: false + }]}; + }; + var e = new instance.web.list.Editor({ + dataset: new instance.web.DataSetSearch(), + prepends_on_create: function () { return false; }, + edition_view: function () { + return makeFormView([ field('a'), field('b'), field('c') ]); + } + }); + var counter = 0; + e.appendTo($fix) + .pipe(function () { + return e.edit({}, function () { + ++counter; + }); + }) + .pipe(function (form) { + ok(e.is_editing(), "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(!e.is_editing(), "should have stopped editing"); + equal(record.id, 42, "should have newly created id"); + }) + }); + asyncTest('toggle-edition-cancel', 2, function () { + instance.session.responses['/web/dataset/call_kw:create'] = function () { + return { result: 42 }; + }; + var e = new instance.web.list.Editor({ + dataset: new instance.web.DataSetSearch(), + prepends_on_create: function () { return false; }, + edition_view: function () { + return makeFormView([ field('a'), field('b'), field('c') ]); + } + }); + var counter = 0; + e.appendTo($fix) + .pipe(function () { + return e.edit({}, function () { + ++counter; + }); + }) + .pipe(function (form) { + return e.cancel(); + }) + .always(start) + .fail(function (error) { ok(false, error && error.message); }) + .done(function (record) { + ok(!e.is_editing(), "should have stopped editing"); + ok(!record.id, "should have no id"); + }) + }); + asyncTest('toggle-save-required', 2, function () { + instance.session.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(), + prepends_on_create: function () { return false; }, + edition_view: 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({}, 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.is_editing(), "should have kept editing"); + }) + }); + + module('list-edition', { + setup: function () { + baseSetup(); + + var records = {}; + _.extend(instance.session.responses, { + '/web/view/load': function () { + return {result: { + type: 'tree', + fields: { + a: {type: 'char', string: "A"}, + b: {type: 'char', string: "B"}, + c: {type: 'char', string: "C"} + }, + arch: { + tag: 'tree', + attrs: {}, + children: [ + {tag: 'field', attrs: {name: 'a'}}, + {tag: 'field', attrs: {name: 'b'}}, + {tag: 'field', attrs: {name: 'c'}} + ] + } + }}; + }, + '/web/dataset/call_kw:create': function (params) { + records[42] = _.extend({}, params.params.args[0]); + return {result: 42}; + }, + '/web/dataset/call_kw:read': function (params) { + var id = params.params.args[0][0]; + if (id in records) { + return {result: [records[id]]}; + } + return {result: []}; + } + }) + } + }); + asyncTest('newrecord', 6, function () { + var got_defaults = false; + instance.session.responses['/web/dataset/call_kw:default_get'] = function (params) { + var fields = params.params.args[0]; + deepEqual( + fields, ['a', 'b', 'c'], + "should ask defaults for all fields"); + got_defaults = true; + return {result: { + a: "qux", + b: "quux" + }}; + }; + + var ds = new instance.web.DataSetStatic(null, 'demo', null, [1]); + var l = new instance.web.ListView({}, ds, false, {editable: 'top'}); + + l.appendTo($fix) + .pipe(l.proxy('reload_content')) + .pipe(function () { + return l.start_edition(); + }) + .always(start) + .pipe(function () { + ok(got_defaults, "should have fetched default values for form"); + return l.save_edition(); + }) + .pipe(function (result) { + ok(result.created, "should yield newly created record"); + equal(result.record.get('a'), "qux", + "should have used default values"); + equal(result.record.get('b'), "quux", + "should have used default values"); + ok(!result.record.get('c'), + "should have no value if there was no default"); + }) + .fail(function (e) { ok(false, e && e.message || e); }); + }); + + module('list-edition-events', { + setup: function () { + baseSetup(); + _.extend(instance.session.responses, { + '/web/view/load': function () { + return {result: { + type: 'tree', + fields: { + a: {type: 'char', string: "A"}, + b: {type: 'char', string: "B"}, + c: {type: 'char', string: "C"} + }, + arch: { + tag: 'tree', + attrs: {}, + children: [ + {tag: 'field', attrs: {name: 'a'}}, + {tag: 'field', attrs: {name: 'b'}}, + {tag: 'field', attrs: {name: 'c'}} + ] + } + }}; + }, + '/web/dataset/call_kw:read': function (params) { + return {result: [{ + id: 1, + a: 'foo', + b: 'bar', + c: 'baz' + }]}; + } + }); + } + }); + asyncTest('edition events', 4, function () { + var ds = new instance.web.DataSetStatic(null, 'demo', null, [1]); + var o = { + counter: 0, + onEvent: function (e) { this.counter++; } + }; + var l = new instance.web.ListView({}, ds, false, {editable: 'top'}); + l.on('edit:before edit:after', o, o.onEvent); + l.appendTo($fix) + .pipe(l.proxy('reload_content')) + .always(start) + .pipe(function () { + ok(l.options.editable, "should be editable"); + equal(o.counter, 0, "should have seen no event yet"); + return l.start_edition(l.records.get(1)); + }) + .pipe(function () { + ok(l.editor.is_editing(), "should be editing"); + equal(o.counter, 2, "should have seen two edition events"); + }) + .fail(function (e) { ok(false, e && e.message); }); + }); + + asyncTest('edition events: cancelling', 3, function () { + var edit_after = false; + var ds = new instance.web.DataSetStatic(null, 'demo', null, [1]); + var l = new instance.web.ListView({}, ds, false, {editable: 'top'}); + l.on('edit:before', {}, function (e) { + e.cancel = true; + }); + l.on('edit:after', {}, function () { + edit_after = true; + }); + l.appendTo($fix) + .pipe(l.proxy('reload_content')) + .always(start) + .pipe(function () { + ok(l.options.editable, "should be editable"); + return l.start_edition(); + }) + // cancelling an event rejects the deferred + .pipe($.Deferred().reject(), function () { + ok(!l.editor.is_editing(), "should not be editing"); + ok(!edit_after, "should not have fired the edit:after event"); + return $.when(); + }) + .fail(function (e) { ok(false, e && e.message || e); }); + }); +}); diff --git a/addons/web/static/test/list-utils.js b/addons/web/static/test/list-utils.js index 7890e71c6bc..6200ba788ce 100644 --- a/addons/web/static/test/list-utils.js +++ b/addons/web/static/test/list-utils.js @@ -133,7 +133,7 @@ $(document).ready(function () { strictEqual(changed, 1); }); - module('list-collections-degenerate', { + module('list-collections', { setup: function () { openerp = window.openerp.init([]); window.openerp.web.corelib(openerp); @@ -145,7 +145,7 @@ $(document).ready(function () { window.openerp.web.list(openerp); } }); - test('Fetch from collection', function () { + test('degenerate-fetch', function () { var c = new openerp.web.list.Collection(); strictEqual(c.length, 0); c.add({id: 1, value: 2}); @@ -163,7 +163,7 @@ $(document).ready(function () { strictEqual(r2.get('id'), 1); strictEqual(r2.get('value'), 2); }); - test('Add at index', function () { + test('degenerate-indexed-add', function () { var c = new openerp.web.list.Collection([ {id: 1, value: 5}, {id: 2, value: 10}, @@ -175,7 +175,7 @@ $(document).ready(function () { strictEqual(c.at(1).get('value'), 55); strictEqual(c.at(3).get('value'), 20); }); - test('Remove record', function () { + test('degenerate-remove', function () { var c = new openerp.web.list.Collection([ {id: 1, value: 5}, {id: 2, value: 10}, @@ -188,7 +188,7 @@ $(document).ready(function () { equal(c.get(2), undefined); strictEqual(c.at(1).get('value'), 20); }); - test('Remove unbind', function () { + test('degenerate-remove-bound', function () { var changed = false, c = new openerp.web.list.Collection([ {id: 1, value: 5} ]); c.bind('change', function () { changed = true; }); @@ -198,7 +198,7 @@ $(document).ready(function () { ok(!changed, 'removed records should not trigger events in their ' + 'parent collection'); }); - test('Reset', function () { + test('degenerate-reset', function () { var event, obj, c = new openerp.web.list.Collection([ {id: 1, value: 5}, {id: 2, value: 10}, @@ -218,7 +218,7 @@ $(document).ready(function () { strictEqual(c.length, 1); strictEqual(c.get(42).get('value'), 55); }); - test('Reset unbind', function () { + test('degenerate-reset-bound', function () { var changed = false, c = new openerp.web.list.Collection([ {id: 1, value: 5} ]); c.bind('change', function () { changed = true; }); @@ -229,7 +229,7 @@ $(document).ready(function () { 'parent collection'); }); - test('Events propagation', function () { + test('degenerate-propagations', function () { var values = []; var c = new openerp.web.list.Collection([ {id: 1, value: 5}, @@ -260,6 +260,82 @@ $(document).ready(function () { c.at(1).set('wealth', 5); strictEqual(total, 47); }); + test('degenerate-successor', function () { + var root = new openerp.web.list.Collection([ + {id: 1, value: 1}, + {id: 2, value: 2}, + {id: 3, value: 3}, + {id: 4, value: 5}, + {id: 5, value: 8} + ]); + + deepEqual(root.succ(root.at(2)).attributes, + root.at(3).attributes, + "should return the record at (index + 1) from the pivot"); + equal(root.succ(root.at(4)), null, + "should return null as successor to last record"); + deepEqual(root.succ(root.at(4), {wraparound: true}).attributes, + root.at(0).attributes, + "should return index 0 as successor to last record if" + + " wraparound is set"); + deepEqual(root.succ(root.at(2), {wraparound: true}).attributes, + root.at(3).attributes, + "wraparound should have no effect if not succ(last_record)"); + }); + test('successor', function () { + var root = new openerp.web.list.Collection(); + root.proxy('first').add([{id: 1, value: 1}, {id: 2, value: 2}]); + root.proxy('second').add([{id: 3, value: 3}, {id: 4, value: 5}]); + root.proxy('third').add([{id: 5, value: 8}, {id: 6, value: 13}]); + + deepEqual(root.succ(root.get(3)).attributes, + root.get(4).attributes, + "should get successor"); + equal(root.succ(root.get(4)), + null, + "successors do not cross collections"); + deepEqual(root.succ(root.get(4), {wraparound: true}).attributes, + root.get(3).attributes, + "should wraparound within a collection"); + }); + test('degenerate-predecessor', function () { + var root = new openerp.web.list.Collection([ + {id: 1, value: 1}, + {id: 2, value: 2}, + {id: 3, value: 3}, + {id: 4, value: 5}, + {id: 5, value: 8} + ]); + + deepEqual(root.pred(root.at(2)).attributes, + root.at(1).attributes, + "should return the record at (index - 1) from the pivot"); + equal(root.pred(root.at(0)), null, + "should return null as predecessor to first record"); + deepEqual(root.pred(root.at(0), {wraparound: true}).attributes, + root.at(4).attributes, + "should return last record as predecessor to first record" + + " if wraparound is set"); + deepEqual(root.pred(root.at(1), {wraparound: true}).attributes, + root.at(0).attributes, + "wraparound should have no effect if not pred(first_record)"); + }); + test('predecessor', function () { + var root = new openerp.web.list.Collection(); + root.proxy('first').add([{id: 1, value: 1}, {id: 2, value: 2}]); + root.proxy('second').add([{id: 3, value: 3}, {id: 4, value: 5}]); + root.proxy('third').add([{id: 5, value: 8}, {id: 6, value: 13}]); + + deepEqual(root.pred(root.get(4)).attributes, + root.get(3).attributes, + "should get predecessor"); + equal(root.pred(root.get(3)), + null, + "predecessor do not cross collections"); + deepEqual(root.pred(root.get(3), {wraparound: true}).attributes, + root.get(4).attributes, + "should wraparound within a collection"); + }); module('list-hofs', { setup: function () { @@ -338,4 +414,33 @@ $(document).ready(function () { ids, [1, 2, 3, 10, 20, 30], 'tree collections should be deeply iterated'); }); + + module("list-weirds", { + setup: function () { + openerp = window.openerp.init([]); + window.openerp.web.corelib(openerp); + window.openerp.web.coresetup(openerp); + window.openerp.web.chrome(openerp); + // views loader stuff + window.openerp.web.data(openerp); + window.openerp.web.views(openerp); + window.openerp.web.list(openerp); + } + }); + test('set-from-noid', function () { + var root = new openerp.web.list.Collection(); + root.add({v: 3}); + root.at(0).set('id', 42); + var record = root.get(42); + equal(root.length, 1); + equal(record.get('v'), 3, "should have fetched the original record"); + }); + test('set-from-previd', function () { + var root = new openerp.web.list.Collection(); + root.add({id: 1, v: 2}); + root.get(1).set('id', 42); + var record = root.get(42); + equal(root.length, 1); + equal(record.get('v'), 2, "should have fetched the original record"); + }); }); diff --git a/addons/web/static/test/registry.js b/addons/web/static/test/registry.js index da0cb952783..ca689a351e0 100644 --- a/addons/web/static/test/registry.js +++ b/addons/web/static/test/registry.js @@ -9,21 +9,6 @@ $(document).ready(function () { openerp.web.Foo2 = {}; } }); - test('key fetch', function () { - var reg = new openerp.web.Registry({ - foo: 'openerp.web.Foo', - bar: 'openerp.web.Bar', - quux: 'openerp.web.Quux' - }); - - strictEqual(reg.get_object('foo'), openerp.web.Foo); - raises(function () { reg.get_object('qux'); }, - openerp.web.KeyNotFound, - "Unknown keys should raise KeyNotFound"); - raises(function () { reg.get_object('quux'); }, - openerp.web.ObjectNotFound, - "Incorrect file paths should raise ObjectNotFound"); - }); test('key set', function () { var reg = new openerp.web.Registry(); diff --git a/addons/web/static/test/search.js b/addons/web/static/test/search.js index e5beab22498..6dc37f31d08 100644 --- a/addons/web/static/test/search.js +++ b/addons/web/static/test/search.js @@ -1,37 +1,8 @@ $(document).ready(function () { - 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; module('query', { setup: 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.search(instance); + instance = openerp.testing.instanceFor('search'); } }); test('Adding a facet to the query creates a facet and a value', function () { @@ -167,16 +138,11 @@ $(document).ready(function () { module('defaults', { setup: 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.search(instance); + instance = openerp.testing.instanceFor('search'); - instance.web.qweb.add_template(doc); + openerp.testing.loadTemplate(instance); - mockifyRPC(instance.connection); + openerp.testing.mockifyRPC(instance); } }); @@ -198,8 +164,8 @@ $(document).ready(function () { instance.dummy = {}; instance.dummy.DummyWidget = instance.web.search.Field.extend( dummy_widget_attributes || {}); - if (!('/web/searchview/load' in instance.connection.responses)) { - instance.connection.responses['/web/searchview/load'] = function () { + if (!('/web/searchview/load' in instance.session.responses)) { + instance.session.responses['/web/searchview/load'] = function () { return {result: {fields_view: { type: 'search', fields: { @@ -220,10 +186,10 @@ $(document).ready(function () { }}}; }; } - instance.connection.responses['/web/searchview/get_filters'] = function () { + instance.session.responses['/web/searchview/get_filters'] = function () { return {result: []}; }; - instance.connection.responses['/web/searchview/fields_get'] = function () { + instance.session.responses['/web/searchview/fields_get'] = function () { return {result: {fields: { dummy: {type: 'char', string: 'Dummy'} }}}; @@ -355,7 +321,7 @@ $(document).ready(function () { {attrs: {name: 'dummy', string: 'Dummy'}}, {relation: 'dummy.model.name'}, view); - instance.connection.responses['/web/dataset/call_kw'] = function (req) { + instance.session.responses['/web/dataset/call_kw'] = function (req) { equal(req.params.method, 'name_get', "m2o should resolve default id"); equal(req.params.model, f.attrs.relation, @@ -391,7 +357,7 @@ $(document).ready(function () { {attrs: {name: 'dummy', string: 'Dummy'}}, {relation: 'dummy.model.name'}, view); - instance.connection.responses['/web/dataset/call_kw'] = function (req) { + instance.session.responses['/web/dataset/call_kw'] = function (req) { return {result: []}; }; f.facet_for_defaults({dummy: id}) @@ -404,18 +370,11 @@ $(document).ready(function () { module('completions', { setup: 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); - // date complete - window.openerp.web.formats(instance); - window.openerp.web.search(instance); - - instance.web.qweb.add_template(doc); - - mockifyRPC(instance.connection); + instance = openerp.testing.instanceFor('search'); + + openerp.testing.loadTemplate(instance); + + openerp.testing.mockifyRPC(instance); } }); asyncTest('calling', 4, function () { @@ -432,10 +391,7 @@ $(document).ready(function () { } }); view.appendTo($('#qunit-fixture')) - .always(start) - .fail(function (error) { ok(false, error.message); }) .done(function () { - stop(); view.complete_global_search({term: "dum"}, function (completions) { start(); equal(completions.length, 1, "should have a single completion"); @@ -454,7 +410,11 @@ $(document).ready(function () { var completion = { label: "Dummy", facet: { - field: {get_domain: noop, get_context: noop, get_groupby: noop}, + field: { + get_domain: openerp.testing.noop, + get_context: openerp.testing.noop, + get_groupby: openerp.testing.noop + }, category: 'Dummy', values: [{label: 'dummy', value: 42}] } @@ -476,7 +436,11 @@ $(document).ready(function () { }); }); asyncTest('facet selection: new value existing facet', 3, function () { - var field = {get_domain: noop, get_context: noop, get_groupby: noop}; + var field = { + get_domain: openerp.testing.noop, + get_context: openerp.testing.noop, + get_groupby: openerp.testing.noop + }; var completion = { label: "Dummy", facet: { @@ -609,7 +573,7 @@ $(document).ready(function () { }); }); asyncTest("M2O", 15, function () { - instance.connection.responses['/web/dataset/call_kw'] = function (req) { + instance.session.responses['/web/dataset/call_kw'] = function (req) { equal(req.params.method, "name_search"); equal(req.params.model, "dummy.model"); deepEqual(req.params.args, []); @@ -643,7 +607,7 @@ $(document).ready(function () { }); }); asyncTest("M2O no match", 5, function () { - instance.connection.responses['/web/dataset/call_kw'] = function (req) { + instance.session.responses['/web/dataset/call_kw'] = function (req) { equal(req.params.method, "name_search"); equal(req.params.model, "dummy.model"); deepEqual(req.params.args, []); @@ -663,16 +627,11 @@ $(document).ready(function () { module('search-serialization', { setup: 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.search(instance); + instance = openerp.testing.instanceFor('search'); - instance.web.qweb.add_template(doc); + openerp.testing.loadTemplate(instance); - mockifyRPC(instance.connection); + openerp.testing.mockifyRPC(instance); } }); asyncTest('No facet, no call', 6, function () { @@ -843,6 +802,25 @@ $(document).ready(function () { deepEqual(f.get_domain(facet), [['foo', '=', 42]], "m2o should use identity if default domain"); + deepEqual(f.get_context(facet), {default_foo: 42}, + "m2o should use value as context default"); + }); + test("M2O default multiple values", function () { + var f = new instance.web.search.ManyToOneField( + {}, {name: 'foo'}, {inputs: []}); + var facet = new instance.web.search.Facet({ + field: f, + values: [ + {label: "Foo", value: 42}, + {label: "Bar", value: 36} + ] + }); + + deepEqual(f.get_domain(facet).__domains, + [['|'], [['foo', '=', 42]], [['foo', '=', 36]]], + "m2o should or multiple values"); + equal(f.get_context(facet), null, + "m2o should not have default context in case of multiple values"); }); test("M2O custom operator", function () { var f = new instance.web.search.ManyToOneField( @@ -854,6 +832,8 @@ $(document).ready(function () { deepEqual(f.get_domain(facet), [['foo', 'boos', 'Foo']], "m2o should use label with custom operators"); + deepEqual(f.get_context(facet), {default_foo: 42}, + "m2o should use value as context default"); }); test("M2O custom domain & context", function () { var f = new instance.web.search.ManyToOneField({attrs: { @@ -919,16 +899,11 @@ $(document).ready(function () { module('removal', { setup: 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.search(instance); + instance = openerp.testing.instanceFor('search'); - instance.web.qweb.add_template(doc); + openerp.testing.loadTemplate(instance); - mockifyRPC(instance.connection); + openerp.testing.mockifyRPC(instance); } }); asyncTest('clear button', function () { @@ -954,16 +929,11 @@ $(document).ready(function () { module('drawer', { setup: 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.search(instance); + instance = openerp.testing.instanceFor('search'); - instance.web.qweb.add_template(doc); + openerp.testing.loadTemplate(instance); - mockifyRPC(instance.connection); + openerp.testing.mockifyRPC(instance); } }); asyncTest('is-drawn', 2, function () { @@ -982,16 +952,11 @@ $(document).ready(function () { module('filters', { setup: 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.search(instance); + instance = openerp.testing.instanceFor('search'); - instance.web.qweb.add_template(doc); + openerp.testing.loadTemplate(instance); - mockifyRPC(instance.connection, { + openerp.testing.mockifyRPC(instance, { '/web/searchview/load': function () { // view with a single group of filters return {result: {fields_view: { @@ -1094,19 +1059,73 @@ $(document).ready(function () { }); }); + module('saved_filters', { + setup: function () { + instance = openerp.testing.instanceFor('search'); + + openerp.testing.loadTemplate(instance); + + openerp.testing.mockifyRPC(instance); + } + }); + asyncTest('checkboxing', 6, function () { + var view = makeSearchView(); + instance.session.responses['/web/searchview/get_filters'] = function () { + return {result: [{ + name: "filter name", + user_id: 42 + }]}; + }; + var $fix = $('#qunit-fixture'); + + view.appendTo($fix) + .always(start) + .fail(function (error) { ok(false, error.message); }) + .done(function () { + var $row = $fix.find('.oe_searchview_custom li:first').click(); + + ok($row.hasClass('oe_selected'), "should check/select the filter's row"); + ok($row.hasClass("oe_searchview_custom_private"), + "should have private filter note/class"); + equal(view.query.length, 1, "should have only one facet"); + var values = view.query.at(0).values; + equal(values.length, 1, + "should have only one value in the facet"); + equal(values.at(0).get('label'), 'filter name', + "displayed label should be the name of the filter"); + equal(values.at(0).get('value'), null, + "should have no value set"); + }) + }); + asyncTest('removal', 1, function () { + var view = makeSearchView(); + instance.session.responses['/web/searchview/get_filters'] = function () { + return {result: [{ + name: "filter name", + user_id: 42 + }]}; + }; + var $fix = $('#qunit-fixture'); + + view.appendTo($fix) + .always(start) + .fail(function (error) { ok(false, error.message); }) + .done(function () { + var $row = $fix.find('.oe_searchview_custom li:first').click(); + + view.query.remove(view.query.at(0)); + ok(!$row.hasClass('oe_selected'), + "should not be checked anymore"); + }) + }); + module('advanced', { setup: 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.formats(instance); - window.openerp.web.search(instance); + instance = openerp.testing.instanceFor('search'); - instance.web.qweb.add_template(doc); + openerp.testing.loadTemplate(instance); - mockifyRPC(instance.connection); + openerp.testing.mockifyRPC(instance); } }); asyncTest('single-advanced', 6, function () { diff --git a/addons/web/static/test/test.html b/addons/web/static/test/test.html index e352f63c17c..209723af5a0 100644 --- a/addons/web/static/test/test.html +++ b/addons/web/static/test/test.html @@ -2,7 +2,7 @@ <html style="height: 100%"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> - <title>OpenERP</title> + <title>OpenERP Web Test Suite</title> <link rel="shortcut icon" href="/web/static/src/img/favicon.ico" type="image/x-icon"/> <link rel="stylesheet" href="/web/static/lib/qunit/qunit.css"> @@ -13,7 +13,7 @@ <script src="/web/static/lib/backbone/backbone.js" type="text/javascript"></script> <!-- jquery --> - <script src="/web/static/lib/jquery/jquery-1.7.2b1.js"></script> + <script src="/web/static/lib/jquery/jquery-1.7.2.js"></script> <script src="/web/static/lib/jquery.ui/js/jquery-ui-1.8.17.custom.min.js"></script> <script src="/web/static/lib/jquery.ba-bbq/jquery.ba-bbq.js"></script> @@ -38,13 +38,15 @@ <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> + + <script src="/web/static/test/testing.js"></script> + <script type="text/javascript"> + QUnit.config.testTimeout = 2000; + </script> </head> <body id="oe" class="openerp"> - <h1 id="qunit-header">OpenERP web Test Suite</h1> - <h2 id="qunit-banner"></h2> - <div id="qunit-testrunner-toolbar"></div> - <h2 id="qunit-userAgent"></h2> - <ol id="qunit-tests"></ol> + <div id="qunit"></div> <div id="qunit-fixture"></div> </body> <script type="text/javascript" src="/web/static/test/class.js"></script> @@ -55,4 +57,6 @@ <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/Widget.js"></script> + <script type="text/javascript" src="/web/static/test/list-editable.js"></script> </html> diff --git a/addons/web/static/test/testing.js b/addons/web/static/test/testing.js new file mode 100644 index 00000000000..1be8e94e74b --- /dev/null +++ b/addons/web/static/test/testing.js @@ -0,0 +1,97 @@ +// Test support structures and methods for OpenERP +openerp.testing = (function () { + 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 dependencies = { + corelib: [], + coresetup: ['corelib'], + data: ['corelib', 'coresetup'], + dates: [], + formats: ['coresetup', 'dates'], + chrome: ['corelib', 'coresetup'], + views: ['corelib', 'coresetup', 'data', 'chrome'], + search: ['data', 'coresetup', 'formats'], + list: ['views', 'data'], + form: ['data', 'views', 'list', 'formats'], + list_editable: ['list', 'form', 'data'], + }; + + return { + /** + * Function which does not do anything + */ + noop: function () { }, + /** + * Loads 'base.xml' template file into qweb for the provided instance + * + * @param instance openerp instance being initialized, to load the template file in + */ + loadTemplate: function (instance) { + instance.web.qweb.add_template(doc); + }, + /** + * Alter provided instance's ``session`` attribute to make response + * mockable: + * + * * The ``responses`` parameter can be used to provide a map of (RPC) + * paths (e.g. ``/web/view/load``) to a function returning a response + * to the query. + * * ``instance.session`` grows a ``responses`` attribute which is + * a map of the same (and is in fact initialized to the ``responses`` + * parameter if one is provided) + * + * Note that RPC requests to un-mocked URLs will be rejected with an + * error message: only explicitly specified urls will get a response. + * + * Mocked sessions will *never* perform an actual RPC connection. + * + * @param instance openerp instance being initialized + * @param {Object} [responses] + */ + mockifyRPC: function (instance, responses) { + var session = instance.session; + session.responses = responses || {}; + session.rpc_function = function (url, payload) { + var fn = this.responses[url.url + ':' + payload.params.method] + || this.responses[url.url]; + + if (!fn) { + return $.Deferred().reject({}, 'failed', + _.str.sprintf("Url %s not found in mock responses, with arguments %s", + url.url, JSON.stringify(payload.params)) + ).promise(); + } + return $.when(fn(payload)); + }; + }, + /** + * Creates an openerp web instance loading the specified module after + * all of its dependencies. + * + * @param {String} module + * @returns OpenERP Web instance + */ + instanceFor: function (module) { + var instance = openerp.init([]); + this._load(instance, module); + return instance; + }, + _load: function (instance, module, loaded) { + if (!loaded) { loaded = []; } + + var deps = dependencies[module]; + if (!deps) { throw new Error("Unknown dependencies for " + module); } + + var to_load = _.difference(deps, loaded); + while (!_.isEmpty(to_load)) { + this._load(instance, to_load[0], loaded); + to_load = _.difference(deps, loaded); + } + openerp.web[module](instance); + loaded.push(module); + } + } +})(); |
