summaryrefslogtreecommitdiff
path: root/addons/web/static/test
diff options
context:
space:
mode:
authorOlivier Dony <odo@openerp.com>2012-10-01 16:53:08 +0200
committerOlivier Dony <odo@openerp.com>2012-10-01 16:53:08 +0200
commit9e6920415e41a052cffa7b898bf044dbf82b5ccb (patch)
tree05e8d64788da1ff9f65e7406e3ff3d96d58a5762 /addons/web/static/test
parent4ed79f3457a0252dcee4780385dc474ff2af356e (diff)
parent1370ae133d4477d0a7a2239732f529a1eef39824 (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.js239
-rw-r--r--addons/web/static/test/evals.js20
-rw-r--r--addons/web/static/test/fulltest.html12
-rw-r--r--addons/web/static/test/fulltest/dataset.js30
-rw-r--r--addons/web/static/test/list-editable.js349
-rw-r--r--addons/web/static/test/list-utils.js121
-rw-r--r--addons/web/static/test/registry.js15
-rw-r--r--addons/web/static/test/search.js227
-rw-r--r--addons/web/static/test/test.html18
-rw-r--r--addons/web/static/test/testing.js97
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);
+ }
+ }
+})();