diff options
| author | Xavier Morel <xmo@openerp.com> | 2012-10-26 10:45:43 +0200 |
|---|---|---|
| committer | Xavier Morel <xmo@openerp.com> | 2012-10-26 10:45:43 +0200 |
| commit | 04282ff00e8fa70c3eb0e9a48ba0cd32aa0e1cd7 (patch) | |
| tree | 4750c6e5f62d2f20924807ef33a334c55c5be0f0 | |
| parent | 99a2dd3938c7d7d4b7e9c724ec8acbb5eeedf35f (diff) | |
[IMP] port search test to new framework, add handling of web.{submodule} dependencies
bzr revid: xmo@openerp.com-20121026084543-fobkc3ta5q2jc3q6
| -rw-r--r-- | addons/web/doc/testing.rst | 35 | ||||
| -rw-r--r-- | addons/web/static/src/js/boot.js | 10 | ||||
| -rw-r--r-- | addons/web/static/src/js/testing.js | 111 | ||||
| -rw-r--r-- | addons/web/static/src/js/view_list.js | 2 | ||||
| -rw-r--r-- | addons/web/static/src/js/views.js | 3 | ||||
| -rw-r--r-- | addons/web/static/test/search.js | 657 |
6 files changed, 396 insertions, 422 deletions
diff --git a/addons/web/doc/testing.rst b/addons/web/doc/testing.rst index 34826201dc9..582960846e4 100644 --- a/addons/web/doc/testing.rst +++ b/addons/web/doc/testing.rst @@ -417,26 +417,49 @@ Actual RPC Testing API ----------- -.. todo:: implement options on sections +.. js:function:: openerp.testing.section(name[, options], body) + + :param String name: + :param TestOptions options: + :param body: + :type body: Function<:js:func:`~openerp.testing.case`, void> + +.. js:function:: openerp.testing.case(name[, options], callback) + + :param String name: + :param TestOptions options: + :param callback: + :type callback: Function<instance, $, Function<String, Function, void>> .. js:class:: TestOptions the various options which can be passed to :js:func:`~openerp.testing.section` or - :js:func:`~openerp.testing.case` + :js:func:`~openerp.testing.case`. Except for + :js:attr:`~TestOptions.setup` and + :js:attr:`~TestOptions.teardown`, an option on + :js:func:`~openerp.testing.case` will overwrite the corresponding + option on :js:func:`~openerp.testing.section` so + e.g. :js:attr:`~TestOptions.rpc` can be set for a + :js:func:`~openerp.testing.section` and then differently set for + some :js:func:`~openerp.testing.case` of that + :js:func:`~openerp.testing.section` .. js:attribute:: TestOptions.asserts - + An integer, the number of assertions which should run during a normal execution of the test. Mandatory for asynchronous tests. - + .. js:attribute:: TestOptions.setup - .. todo:: implement & document setup (async?) + Test case setup, run right before each test case. A section's + :js:func:`~TestOptions.setup` is run before the case's own, if + both are specified. .. js:attribute:: TestOptions.teardown - .. todo:: implement & document teardown (async?) + Test case teardown, a case's :js:func:`~TestOptions.teardown` + is run before the corresponding section if both are present. .. js:attribute:: TestOptions.fail_on_rejection diff --git a/addons/web/static/src/js/boot.js b/addons/web/static/src/js/boot.js index 05ce709e80a..631a7f8c6f5 100644 --- a/addons/web/static/src/js/boot.js +++ b/addons/web/static/src/js/boot.js @@ -19,12 +19,14 @@ /** * OpenERP instance constructor * - * @param {Array} modules list of modules to initialize + * @param {Array|String} modules list of modules to initialize */ init: function(modules) { - // By default only web will be loaded, the rest will be by loaded - // by openerp.web.Session on the first session_authenticate - modules = _.union(['web'], modules || []); + if (modules === "fuck your shit, don't load anything you cunt") { + modules = []; + } else { + modules = _.union(['web'], modules || []); + } var new_instance = { // links to the global openerp _openerp: openerp, diff --git a/addons/web/static/src/js/testing.js b/addons/web/static/src/js/testing.js index 4eadc3a5415..e4f327bf0c3 100644 --- a/addons/web/static/src/js/testing.js +++ b/addons/web/static/src/js/testing.js @@ -85,23 +85,17 @@ openerp.testing = {}; }; }; - var _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)) { - _load(instance, to_load[0], loaded); - to_load = _.difference(deps, loaded); + testing.section = function (name, options, body) { + if (_.isFunction(options)) { + body = options; + options = {}; } - openerp.web[module](instance); - loaded.push(module); - }; + _.defaults(options, { + setup: testing.noop, + teardown: testing.noop + }); - testing.section = function (name, body) { - QUnit.module(testing.current_module + '.' + name); + QUnit.module(testing.current_module + '.' + name, {_oe: options}); body(testing.case); }; testing.case = function (name, options, callback) { @@ -109,6 +103,10 @@ openerp.testing = {}; callback = options; options = {}; } + _.defaults(options, { + setup: testing.noop, + teardown: testing.noop + }); var module = testing.current_module; var module_index = _.indexOf(testing.dependencies, module); @@ -117,13 +115,66 @@ openerp.testing = {}; // returns -1 -> index becomes 0 -> replace with ``undefined`` so // Array#slice returns a full copy 0, module_index + 1 || undefined); - QUnit.test(name, function (env) { - var instance = openerp.init(module_deps); - if (_.isNumber(options.asserts)) { - expect(options.asserts) + QUnit.test(name, function () { + // module testing environment + var self = this; + var opts = _.defaults({ + // section setup + // case setup + // test + // case teardown + // section teardown + setup: function () { + if (self._oe.setup.apply(null, arguments)) { + throw new Error("Asynchronous setup not implemented"); + } + if (options.setup.apply(null, arguments)) { + throw new Error("Asynchronous setup not implemented"); + } + }, + teardown: function () { + if (options.teardown.apply(null, arguments)) { + throw new Error("Asynchronous teardown not implemented"); + } + if (self._oe.teardown(null, arguments)) { + throw new Error("Asynchronous teardown not implemented"); + } + } + }, options, this._oe); + + var instance; + if (!opts.dependencies) { + instance = openerp.init(module_deps); + } else { + // empty-but-specified dependencies actually allow running + // without loading any module into the instance + + // TODO: clean up this mess + var d = opts.dependencies.slice(); + var di = 0; + while (di < d.length) { + var m = /^web\.(\w+)$/.exec(d[di]); + if (m) { + d[di] = m[1]; + } + d.splice.apply(d, [di+1, 0].concat( + _(dependencies[d[di]]).reverse())); + ++di; + } + + instance = openerp.init("fuck your shit, don't load anything you cunt"); + _(d).chain() + .reverse() + .uniq() + .each(function (module) { + openerp.web[module](instance); + }); + } + if (_.isNumber(opts.asserts)) { + expect(opts.asserts); } - if (options.templates) { + if (opts.templates) { for(var i=0; i<module_deps.length; ++i) { var dep = module_deps[i]; var templates = testing.templates[dep]; @@ -135,8 +186,10 @@ openerp.testing = {}; } } + var $fixture = $('#qunit-fixture'); + var mock, async = false; - switch (options.rpc) { + switch (opts.rpc) { case 'mock': async = true; testing.mockifyRPC(instance); @@ -148,25 +201,29 @@ openerp.testing = {}; async = true; } - // TODO: explicit dependencies options for web sub-modules (will deprecate _load/instanceFor) - var result = callback(instance, $('#qunit-fixture'), mock); + // TODO: async setup/teardown + opts.setup(instance, $fixture, mock); + var result = callback(instance, $fixture, mock); + + // TODO: cleanup which works on errors if (!(result && _.isFunction(result.then))) { if (async) { ok(false, "asynchronous test cases must return a promise"); } + opts.teardown(instance, $fixture, mock); return; } stop(); - if (!_.isNumber(options.asserts)) { + if (!_.isNumber(opts.asserts)) { ok(false, "asynchronous test cases must specify the " + "number of assertions they expect"); } - result.then(function () { - start(); - }, function (error) { + result.always(function () { start(); + opts.teardown(instance, $fixture, mock); + }).fail(function (error) { if (options.fail_on_rejection === false) { return; } diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index 29bc81ea9ec..169398ccf91 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -1,6 +1,6 @@ openerp.web.list = function (instance) { var _t = instance.web._t, - _lt = instance.web._lt; + _lt = instance.web._lt; var QWeb = instance.web.qweb; instance.web.views.add('list', 'instance.web.ListView'); instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListView# */ { diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 9390f753be7..03aff76ca2f 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -495,7 +495,7 @@ instance.web.ViewManager = instance.web.Widget.extend({ .find('.oe_view_manager_switch a').filter('[data-view-type="' + view_type + '"]') .parent().addClass('active'); - r = $.when(view_promise).then(function () { + return $.when(view_promise).then(function () { _.each(_.keys(self.views), function(view_name) { var controller = self.views[view_name].controller; if (controller) { @@ -511,7 +511,6 @@ instance.web.ViewManager = instance.web.Widget.extend({ }); self.trigger('switch_mode', view_type, no_store, view_options); }); - return r; }, do_create_view: function(view_type) { // Lazy loading of views diff --git a/addons/web/static/test/search.js b/addons/web/static/test/search.js index 3ef4d6840e2..20534eff76a 100644 --- a/addons/web/static/test/search.js +++ b/addons/web/static/test/search.js @@ -1,11 +1,7 @@ -$(document).ready(function () { - var instance; - module('query', { - setup: function () { - instance = openerp.testing.instanceFor('search'); - } - }); - test('Adding a facet to the query creates a facet and a value', function () { +openerp.testing.section('query', { + dependencies: ['web.search'] +}, function (test) { + test('Adding a facet to the query creates a facet and a value', function (instance) { var query = new instance.web.search.SearchQuery; var field = {}; query.add({ @@ -19,7 +15,7 @@ $(document).ready(function () { equal(facet.get('field'), field); deepEqual(facet.get('values'), [{label: 'Value', value: 3}]); }); - test('Adding two facets', function () { + test('Adding two facets', function (instance) { var query = new instance.web.search.SearchQuery; query.add([ { category: 'Foo', field: {}, values: [{label: 'Value', value: 3}] }, @@ -30,7 +26,7 @@ $(document).ready(function () { equal(query.at(0).values.length, 1); equal(query.at(1).values.length, 1); }); - test('If a facet already exists, add values to it', function () { + test('If a facet already exists, add values to it', function (instance) { var query = new instance.web.search.SearchQuery; var field = {}; query.add({category: 'A', field: field, values: [{label: 'V1', value: 0}]}); @@ -43,7 +39,7 @@ $(document).ready(function () { {label: 'V2', value: 1} ]); }); - test('Facet being implicitly changed should trigger change, not add', function () { + test('Facet being implicitly changed should trigger change, not add', function (instance) { var query = new instance.web.search.SearchQuery; var field = {}, added = false, changed = false; query.add({category: 'A', field: field, values: [{label: 'V1', value: 0}]}); @@ -54,7 +50,7 @@ $(document).ready(function () { ok(!added, "query.add adding values to a facet should not trigger an add"); ok(changed, "query.add adding values to a facet should not trigger a change"); }); - test('Toggling a facet, value which does not exist should add it', function () { + test('Toggling a facet, value which does not exist should add it', function (instance) { var query = new instance.web.search.SearchQuery; var field = {}; query.toggle({category: 'A', field: field, values: [{label: 'V1', value: 0}]}); @@ -65,7 +61,7 @@ $(document).ready(function () { deepEqual(facet.get('values'), [{label: 'V1', value: 0}], "Facet's value should match input"); }); - test('Toggling a facet which exists with a value which does not should add the value to the facet', function () { + test('Toggling a facet which exists with a value which does not should add the value to the facet', function (instance) { var field = {}; var query = new instance.web.search.SearchQuery; query.add({category: 'A', field: field, values: [{label: 'V1', value: 0}]}); @@ -79,7 +75,7 @@ $(document).ready(function () { {label: 'V2', value: 1} ]); }); - test('Toggling a facet which exists with a value which does as well should remove the value from the facet', function () { + test('Toggling a facet which exists with a value which does as well should remove the value from the facet', function (instance) { var field = {}; var query = new instance.web.search.SearchQuery; query.add({category: 'A', field: field, values: [{label: 'V1', value: 0}]}); @@ -94,7 +90,7 @@ $(document).ready(function () { {label: 'V1', value: 0} ]); }); - test('Toggling off the last value of a facet should remove the facet', function () { + test('Toggling off the last value of a facet should remove the facet', function (instance) { var field = {}; var query = new instance.web.search.SearchQuery; query.add({category: 'A', field: field, values: [{label: 'V1', value: 0}]}); @@ -103,7 +99,7 @@ $(document).ready(function () { equal(query.length, 0, 'Should have removed the facet'); }); - test('Intermediate emptiness should not remove the facet', function () { + test('Intermediate emptiness should not remove the facet', function (instance) { var field = {}; var query = new instance.web.search.SearchQuery; query.add({category: 'A', field: field, values: [{label: 'V1', value: 0}]}); @@ -121,7 +117,7 @@ $(document).ready(function () { ]); }); - test('Reseting with multiple facets should still work to load defaults', function () { + test('Reseting with multiple facets should still work to load defaults', function (instance) { var query = new instance.web.search.SearchQuery; var field = {}; query.reset([ @@ -135,78 +131,75 @@ $(document).ready(function () { {label: 'V2', value: 1} ]) }); +}); - module('defaults', { - setup: function () { - instance = openerp.testing.instanceFor('search'); - - openerp.testing.loadTemplate(instance); - - openerp.testing.mockifyRPC(instance); - } - }); - - /** - * Builds a basic search view with a single "dummy" field. The dummy - * extends `instance.web.search.Field`, it does not add any (class) - * attributes beyond what is provided through ``dummy_widget_attributes``. - * - * The view is returned un-started, it is the caller's role to start it - * (or use DOM-insertion methods to start it indirectly). - * - * @param [dummy_widget_attributes={}] - * @param [defaults={}] - * @return {instance.web.SearchView} - */ - function makeSearchView(dummy_widget_attributes, defaults) { - instance.web.search.fields.add( - 'dummy', 'instance.dummy.DummyWidget'); - instance.dummy = {}; - instance.dummy.DummyWidget = instance.web.search.Field.extend( - dummy_widget_attributes || {}); - if (!('/web/searchview/load' in instance.session.responses)) { - instance.session.responses['/web/searchview/load'] = function () { - return {result: {fields_view: { - type: 'search', - fields: { - dummy: {type: 'char', string: "Dummy"} - }, - arch: { - tag: 'search', - attrs: {}, - children: [{ - tag: 'field', - attrs: { - name: 'dummy', - widget: 'dummy' - }, - children: [] - }] - } - }}}; - }; - } - instance.session.responses['/web/searchview/get_filters'] = function () { - return {result: []}; - }; - instance.session.responses['/web/searchview/fields_get'] = function () { - return {result: {fields: { - dummy: {type: 'char', string: 'Dummy'} - }}}; +/** + * Builds a basic search view with a single "dummy" field. The dummy + * extends `instance.web.search.Field`, it does not add any (class) + * attributes beyond what is provided through ``dummy_widget_attributes``. + * + * The view is returned un-started, it is the caller's role to start it + * (or use DOM-insertion methods to start it indirectly). + * + * @param instance + * @param [dummy_widget_attributes={}] + * @param [defaults={}] + * @return {instance.web.SearchView} + */ +var makeSearchView = function (instance, dummy_widget_attributes, defaults) { + instance.web.search.fields.add( + 'dummy', 'instance.dummy.DummyWidget'); + instance.dummy = {}; + instance.dummy.DummyWidget = instance.web.search.Field.extend( + dummy_widget_attributes || {}); + if (!('/web/searchview/load' in instance.session.responses)) { + instance.session.responses['/web/searchview/load'] = function () { + return {fields_view: { + type: 'search', + fields: { + dummy: {type: 'char', string: "Dummy"} + }, + arch: { + tag: 'search', + attrs: {}, + children: [{ + tag: 'field', + attrs: { + name: 'dummy', + widget: 'dummy' + }, + children: [] + }] + } + }}; }; - - var dataset = {model: 'dummy.model', get_context: function () { return {}; }}; - var view = new instance.web.SearchView(null, dataset, false, defaults); - var self = this; - view.on('invalid_search', self, function () { - ok(false, JSON.stringify([].slice(arguments))); - }); - return view; } - asyncTest('calling', 2, function () { + instance.session.responses['/web/searchview/get_filters'] = function () { + return []; + }; + instance.session.responses['/web/searchview/fields_get'] = function () { + return {fields: { + dummy: {type: 'char', string: 'Dummy'} + }}; + }; + + var dataset = {model: 'dummy.model', get_context: function () { return {}; }}; + var view = new instance.web.SearchView(null, dataset, false, defaults); + var self = this; + view.on('invalid_search', self, function () { + ok(false, JSON.stringify([].slice(arguments))); + }); + return view; +}; +openerp.testing.section('defaults', { + dependencies: ['web.search'], + rpc: 'mock', + templates: true, +}, function (test) { + test('calling', {asserts: 2}, function (instance, $s) { var defaults_called = false; - var view = makeSearchView({ + var view = makeSearchView(instance, { facet_for_defaults: function (defaults) { defaults_called = true; return $.when({ @@ -216,9 +209,7 @@ $(document).ready(function () { }); } }, {dummy: 42}); - view.appendTo($('#qunit-fixture')) - .always(start) - .fail(function (error) { ok(false, error.message); }) + return view.appendTo($s) .done(function () { ok(defaults_called, "should have called defaults"); deepEqual( @@ -227,7 +218,7 @@ $(document).ready(function () { "should have generated a facet with the default value"); }); }); - asyncTest('FilterGroup', 3, function () { + test('FilterGroup', {asserts: 3}, function (instance) { var view = {inputs: [], query: {on: function () {}}}; var filter_a = new instance.web.search.Filter( {attrs: {name: 'a'}}, view); @@ -235,9 +226,7 @@ $(document).ready(function () { {attrs: {name: 'b'}}, view); var group = new instance.web.search.FilterGroup( [filter_a, filter_b], view); - group.facet_for_defaults({a: true, b: true}) - .always(start) - .fail(function (error) { ok(false, error && error.message); }) + return group.facet_for_defaults({a: true, b: true}) .done(function (facet) { var model = facet; if (!(model instanceof instance.web.search.Facet)) { @@ -249,13 +238,11 @@ $(document).ready(function () { strictEqual(values.at(1).get('value'), filter_b); }); }); - asyncTest('Field', 4, function () { + test('Field', {asserts: 4}, function (instance) { var view = {inputs: []}; var f = new instance.web.search.Field( {attrs: {string: 'Dummy', name: 'dummy'}}, {}, view); - f.facet_for_defaults({dummy: 42}) - .always(start) - .fail(function (error) { ok(false, error && error.message); }) + return f.facet_for_defaults({dummy: 42}) .done(function (facet) { var model = facet; if (!(model instanceof instance.web.search.Facet)) { @@ -275,15 +262,13 @@ $(document).ready(function () { "facet value should match provided default"); }); }); - asyncTest('Selection: valid value', 4, function () { + test('Selection: valid value', {asserts: 4}, function (instance) { var view = {inputs: []}; var f = new instance.web.search.SelectionField( {attrs: {name: 'dummy', string: 'Dummy'}}, {selection: [[1, "Foo"], [2, "Bar"], [3, "Baz"], [4, "Qux"]]}, view); - f.facet_for_defaults({dummy: 3}) - .always(start) - .fail(function (error) { ok(false, error && error.message); }) + return f.facet_for_defaults({dummy: 3}) .done(function (facet) { var model = facet; if (!(model instanceof instance.web.search.Facet)) { @@ -303,36 +288,28 @@ $(document).ready(function () { "facet value should match provided default's selection"); }); }); - asyncTest('Selection: invalid value', 1, function () { + test('Selection: invalid value', {asserts: 1}, function (instance) { var view = {inputs: []}; var f = new instance.web.search.SelectionField( {attrs: {name: 'dummy', string: 'Dummy'}}, {selection: [[1, "Foo"], [2, "Bar"], [3, "Baz"], [4, "Qux"]]}, view); - f.facet_for_defaults({dummy: 42}) - .always(start) - .fail(function (error) { ok(false, error && error.message); }) + return f.facet_for_defaults({dummy: 42}) .done(function (facet) { ok(!facet, "an invalid value should result in a not-facet"); }); }); - asyncTest("M2O default: value", 7, function () { + test("M2O default: value", {asserts: 5}, function (instance, $s, mock) { var view = {inputs: []}, id = 4; var f = new instance.web.search.ManyToOneField( {attrs: {name: 'dummy', string: 'Dummy'}}, {relation: 'dummy.model.name'}, view); - 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, - "query model should match m2o relation"); - equal(req.params.args[0], id); - return {result: [[id, "DumDumDum"]]}; - }; - f.facet_for_defaults({dummy: id}) - .always(start) - .fail(function (error) { ok(false, error && error.message); }) + mock('dummy.model.name:name_get', function (args) { + equal(args[0], id); + return [[id, "DumDumDum"]]; + }); + return f.facet_for_defaults({dummy: id}) .done(function (facet) { var model = facet; if (!(model instanceof instance.web.search.Facet)) { @@ -352,34 +329,26 @@ $(document).ready(function () { "facet value should match provided default's selection"); }); }); - asyncTest("M2O default: value", 1, function () { + test("M2O default: value", {asserts: 1}, function (instance, $s, mock) { var view = {inputs: []}, id = 4; var f = new instance.web.search.ManyToOneField( {attrs: {name: 'dummy', string: 'Dummy'}}, {relation: 'dummy.model.name'}, view); - instance.session.responses['/web/dataset/call_kw'] = function (req) { - return {result: []}; - }; - f.facet_for_defaults({dummy: id}) - .always(start) - .fail(function (error) { ok(false, error && error.message); }) + mock('dummy.model.name:name_get', function () { return [] }); + return f.facet_for_defaults({dummy: id}) .done(function (facet) { ok(!facet, "an invalid m2o default should yield a non-facet"); }); }); - - module('completions', { - setup: function () { - instance = openerp.testing.instanceFor('search'); - - openerp.testing.loadTemplate(instance); - - openerp.testing.mockifyRPC(instance); - } - }); - asyncTest('calling', 4, function () { - var view = makeSearchView({ +}); +openerp.testing.section('completions', { + dependencies: ['web.search'], + rpc: 'mock', + templates: true +}, function (test) { + test('calling', {asserts: 4}, function (instance, $s) { + var view = makeSearchView(instance, { complete: function () { return $.when({ label: "Dummy", @@ -391,10 +360,11 @@ $(document).ready(function () { }); } }); - view.appendTo($('#qunit-fixture')) - .done(function () { + var done = $.Deferred(); + view.appendTo($s) + .then(function () { view.complete_global_search({term: "dum"}, function (completions) { - start(); + done.resolve(); equal(completions.length, 1, "should have a single completion"); var completion = completions[0]; equal(completion.label, "Dummy", @@ -405,9 +375,10 @@ $(document).ready(function () { [{label: 'dummy', value: 42}], "should have provided values"); }); - }); + }).fail(function () { done.reject.apply(done, arguments); }); + return done; }); - asyncTest('facet selection', 2, function () { + test('facet selection', {asserts: 2}, function (instance, $s) { var completion = { label: "Dummy", facet: { @@ -421,10 +392,8 @@ $(document).ready(function () { } }; - var view = makeSearchView({}); - view.appendTo($('#qunit-fixture')) - .always(start) - .fail(function (error) { ok(false, error.message); }) + var view = makeSearchView(instance); + return view.appendTo($s) .done(function () { view.select_completion( {preventDefault: function () {}}, @@ -436,7 +405,7 @@ $(document).ready(function () { "should have the right facet in the query"); }); }); - asyncTest('facet selection: new value existing facet', 3, function () { + test('facet selection: new value existing facet', {asserts: 3}, function (instance, $s) { var field = { get_domain: openerp.testing.noop, get_context: openerp.testing.noop, @@ -451,10 +420,8 @@ $(document).ready(function () { } }; - var view = makeSearchView({}); - view.appendTo($('#qunit-fixture')) - .always(start) - .fail(function (error) { ok(false, error.message); }) + var view = makeSearchView(instance); + return view.appendTo($s) .done(function () { view.query.add({field: field, category: 'Dummy', values: [{label: 'previous', value: 41}]}); @@ -470,23 +437,19 @@ $(document).ready(function () { "should have added selected value to old one"); }); }); - asyncTest('Field', 1, function () { + test('Field', {asserts: 1}, function (instance) { var view = {inputs: []}; var f = new instance.web.search.Field({attrs: {}}, {}, view); - f.complete('foo') - .always(start) - .fail(function (error) { ok(false, error.message); }) + return f.complete('foo') .done(function (completions) { ok(_(completions).isEmpty(), "field should not provide any completion"); }); }); - asyncTest('CharField', 6, function () { + test('CharField', {asserts: 6}, function (instance) { var view = {inputs: []}; var f = new instance.web.search.CharField( {attrs: {string: "Dummy"}}, {}, view); - f.complete('foo<') - .always(start) - .fail(function (error) { ok(false, error.message); }) + return f.complete('foo<') .done(function (completions) { equal(completions.length, 1, "should provide a single completion"); var c = completions[0]; @@ -503,15 +466,13 @@ $(document).ready(function () { "facet should have single value using completion item"); }); }); - asyncTest('Selection: match found', 14, function () { + test('Selection: match found', {asserts: 14}, function (instance) { var view = {inputs: []}; var f = new instance.web.search.SelectionField( {attrs: {string: "Dummy"}}, {selection: [[1, "Foo"], [2, "Bar"], [3, "Baz"], [4, "Bazador"]]}, view); - f.complete("ba") - .always(start) - .fail(function (error) { ok(false, error.message); }) + return f.complete("ba") .done(function (completions) { equal(completions.length, 4, "should provide two completions and a section title"); @@ -536,20 +497,18 @@ $(document).ready(function () { deepEqual(c3.facet.values, [{label: "Bazador", value: 4}]); }); }); - asyncTest('Selection: no match', 1, function () { + test('Selection: no match', {asserts: 1}, function (instance) { var view = {inputs: []}; var f = new instance.web.search.SelectionField( {attrs: {string: "Dummy"}}, {selection: [[1, "Foo"], [2, "Bar"], [3, "Baz"], [4, "Bazador"]]}, view); - f.complete("qux") - .always(start) - .fail(function (error) { ok(false, error.message); }) + return f.complete("qux") .done(function (completions) { ok(!completions, "if no value matches the needle, no completion shall be provided"); }); }); - asyncTest('Date', 6, function () { + test('Date', {asserts: 6}, function (instance) { instance.web._t.database.parameters = { date_format: '%Y-%m-%d', time_format: '%H:%M:%S' @@ -557,9 +516,7 @@ $(document).ready(function () { var view = {inputs: []}; var f = new instance.web.search.DateField( {attrs: {string: "Dummy"}}, {type: 'datetime'}, view); - f.complete('2012-05-21T21:21:21') - .always(start) - .fail(function (error) { ok(false, error.message); }) + return f.complete('2012-05-21T21:21:21') .done(function (completions) { equal(completions.length, 1, "should provide a single completion"); var c = completions[0]; @@ -573,21 +530,17 @@ $(document).ready(function () { new Date(2012, 4, 21, 21, 21, 21).getTime()); }); }); - asyncTest("M2O", 15, function () { - 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, []); - deepEqual(req.params.kwargs.name, 'bob'); - return {result: [[42, "choice 1"], [43, "choice @"]]} - }; + test("M2O", {asserts: 13}, function (instance, $s, mock) { + mock('dummy.model:name_search', function (args, kwargs) { + deepEqual(args, []); + strictEqual(kwargs.name, 'bob'); + return [[42, "choice 1"], [43, "choice @"]]; + }); var view = {inputs: []}; var f = new instance.web.search.ManyToOneField( {attrs: {string: 'Dummy'}}, {relation: 'dummy.model'}, view); - f.complete("bob") - .always(start) - .fail(function (error) { ok(false, error.message); }) + return f.complete("bob") .done(function (c) { equal(c.length, 3, "should return results + title"); var title = c[0]; @@ -607,38 +560,29 @@ $(document).ready(function () { deepEqual(f2.values.toJSON(), [{label: 'choice @', value: 43}]); }); }); - asyncTest("M2O no match", 5, function () { - 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, []); - deepEqual(req.params.kwargs.name, 'bob'); - return {result: []} - }; + test("M2O no match", {asserts: 3}, function (instance, $s, mock) { + mock('dummy.model:name_search', function (args, kwargs) { + deepEqual(args, []); + strictEqual(kwargs.name, 'bob'); + return []; + }); var view = {inputs: []}; var f = new instance.web.search.ManyToOneField( {attrs: {string: 'Dummy'}}, {relation: 'dummy.model'}, view); - f.complete("bob") - .always(start) - .fail(function (error) { ok(false, error.message); }) + return f.complete("bob") .done(function (c) { ok(!c, "no match should yield no completion"); }); }); - - module('search-serialization', { - setup: function () { - instance = openerp.testing.instanceFor('search'); - - openerp.testing.loadTemplate(instance); - - openerp.testing.mockifyRPC(instance); - } - }); - asyncTest('No facet, no call', 6, function () { +}); +openerp.testing.section('search-serialization', { + dependencies: ['web.search'], + rpc: 'mock', + templates: true +}, function (test) { + test('No facet, no call', {asserts: 6}, function (instance, $s) { var got_domain = false, got_context = false, got_groupby = false; - var $fix = $('#qunit-fixture'); - var view = makeSearchView({ + var view = makeSearchView(instance, { get_domain: function () { got_domain = true; return null; @@ -654,11 +598,9 @@ $(document).ready(function () { }); var ds, cs, gs; view.on('search_data', this, function (d, c, g) { - ds = d, cs = c, gs = g; + ds = d; cs = c; gs = g; }); - view.appendTo($fix) - .always(start) - .fail(function (error) { ok(false, error.message); }) + return view.appendTo($s) .done(function () { view.do_search(); ok(!got_domain, "no facet, should not have fetched domain"); @@ -671,10 +613,9 @@ $(document).ready(function () { ok(_(gs).isEmpty(), "groupby list should be empty"); }) }); - asyncTest('London, calling', 8, function () { + test('London, calling', {asserts: 8}, function (instance, $fix) { var got_domain = false, got_context = false, got_groupby = false; - var $fix = $('#qunit-fixture'); - var view = makeSearchView({ + var view = makeSearchView(instance, { get_domain: function (facet) { equal(facet.get('category'), "Dummy"); deepEqual(facet.values.toJSON(), [{label: "42", value: 42}]); @@ -692,11 +633,9 @@ $(document).ready(function () { }, {dummy: 42}); var ds, cs, gs; view.on('search_data', this, function (d, c, g) { - ds = d, cs = c, gs = g; + ds = d; cs = c; gs = g; }); - view.appendTo($fix) - .always(start) - .fail(function (error) { ok(false, error.message); }) + return view.appendTo($fix) .done(function () { view.do_search(); ok(got_domain, "should have fetched domain"); @@ -709,9 +648,8 @@ $(document).ready(function () { ok(_(gs).isEmpty(), "groupby list should be empty"); }) }); - asyncTest('Generate domains', 1, function () { - var $fix = $('#qunit-fixture'); - var view = makeSearchView({ + test('Generate domains', {asserts: 1}, function (instance, $fix) { + var view = makeSearchView(instance, { get_domain: function (facet) { return facet.values.map(function (value) { return ['win', '4', value.get('value')]; @@ -720,9 +658,7 @@ $(document).ready(function () { }, {dummy: 42}); var ds; view.on('search_data', this, function (d) { ds = d; }); - view.appendTo($fix) - .always(start) - .fail(function (error) { ok(false, error.message); }) + return view.appendTo($fix) .done(function () { view.do_search(); deepEqual(ds, [[['win', '4', 42]]], @@ -730,7 +666,9 @@ $(document).ready(function () { }); }); - test('Field single value, default domain & context', function () { + test('Field single value, default domain & context', { + rpc: false + }, function (instance) { var f = new instance.web.search.Field({}, {name: 'foo'}, {inputs: []}); var facet = new instance.web.search.Facet({ field: f, @@ -742,7 +680,9 @@ $(document).ready(function () { equal(f.get_context(facet), null, "default field context is null"); }); - test('Field multiple values, default domain & context', function () { + test('Field multiple values, default domain & context', { + rpc: false + }, function (instance) { var f = new instance.web.search.Field({}, {name: 'foo'}, {inputs: []}); var facet = new instance.web.search.Facet({ field: f, @@ -763,7 +703,9 @@ $(document).ready(function () { equal(f.get_context(facet), null, "default field context is null"); }); - test('Field single value, custom domain & context', function () { + test('Field single value, custom domain & context', { + rpc: false + }, function (instance) { var f = new instance.web.search.Field({attrs:{ context: "{'bob': self}", filter_domain: "[['edmund', 'is', self]]" @@ -793,7 +735,9 @@ $(document).ready(function () { self: "great" }, "evaluation context should hold facet value as self"); }); - test("M2O default", function () { + test("M2O default", { + rpc: false + }, function (instance) { var f = new instance.web.search.ManyToOneField( {}, {name: 'foo'}, {inputs: []}); var facet = new instance.web.search.Facet({ @@ -806,7 +750,9 @@ $(document).ready(function () { deepEqual(f.get_context(facet), {default_foo: 42}, "m2o should use value as context default"); }); - test("M2O default multiple values", function () { + test("M2O default multiple values", { + rpc: false + }, function (instance) { var f = new instance.web.search.ManyToOneField( {}, {name: 'foo'}, {inputs: []}); var facet = new instance.web.search.Facet({ @@ -823,7 +769,9 @@ $(document).ready(function () { equal(f.get_context(facet), null, "m2o should not have default context in case of multiple values"); }); - test("M2O custom operator", function () { + test("M2O custom operator", { + rpc: false + }, function (instance) { var f = new instance.web.search.ManyToOneField( {attrs: {operator: 'boos'}}, {name: 'foo'}, {inputs: []}); var facet = new instance.web.search.Facet({ @@ -836,7 +784,9 @@ $(document).ready(function () { deepEqual(f.get_context(facet), {default_foo: 42}, "m2o should use value as context default"); }); - test("M2O custom domain & context", function () { + test("M2O custom domain & context", { + rpc: false + }, function (instance) { var f = new instance.web.search.ManyToOneField({attrs: { context: "{'whee': self}", filter_domain: "[['filter', 'is', self]]" @@ -862,7 +812,7 @@ $(document).ready(function () { }, "custom context's self should be label"); }); - asyncTest('FilterGroup', 6, function () { + test('FilterGroup', {asserts: 6}, function (instance) { var view = {inputs: [], query: {on: function () {}}}; var filter_a = new instance.web.search.Filter( {attrs: {name: 'a', context: 'c1', domain: 'd1'}}, view); @@ -872,9 +822,7 @@ $(document).ready(function () { {attrs: {name: 'c', context: 'c3', domain: 'd3'}}, view); var group = new instance.web.search.FilterGroup( [filter_a, filter_b, filter_c], view); - group.facet_for_defaults({a: true, c: true}) - .always(start) - .fail(function (error) { ok(false, error && error.message); }) + return group.facet_for_defaults({a: true, c: true}) .done(function (facet) { var model = facet; if (!(model instanceof instance.web.search.Facet)) { @@ -897,19 +845,14 @@ $(document).ready(function () { ok(!context.get_eval_context(), "context should have no evaluation context"); }); }); - - module('removal', { - setup: function () { - instance = openerp.testing.instanceFor('search'); - - openerp.testing.loadTemplate(instance); - - openerp.testing.mockifyRPC(instance); - } - }); - asyncTest('clear button', function () { - var $fix = $('#qunit-fixture'); - var view = makeSearchView({ +}); +openerp.testing.section('removal', { + dependencies: ['web.search'], + rpc: 'mock', + templates: true +}, function (test) { + test('clear button', {asserts: 2}, function (instance, $fix) { + var view = makeSearchView(instance, { facet_for_defaults: function (defaults) { return $.when({ field: this, @@ -918,31 +861,22 @@ $(document).ready(function () { }); } }, {dummy: 42}); - view.appendTo($fix) - .always(start) - .fail(function (error) { ok(false, error.message); }) + return view.appendTo($fix) .done(function () { equal(view.query.length, 1, "view should have default facet"); $fix.find('.oe_searchview_clear').click(); equal(view.query.length, 0, "cleared view should not have any facet"); }); }); - - module('drawer', { - setup: function () { - instance = openerp.testing.instanceFor('search'); - - openerp.testing.loadTemplate(instance); - - openerp.testing.mockifyRPC(instance); - } - }); - asyncTest('is-drawn', 2, function () { - var view = makeSearchView(); - var $fix = $('#qunit-fixture'); - view.appendTo($fix) - .always(start) - .fail(function (error) { ok(false, error.message); }) +}); +openerp.testing.section('drawer', { + dependencies: ['web.search'], + rpc: 'mock', + templates: true +}, function (test) { + test('is-drawn', {asserts: 2}, function (instance, $fix) { + var view = makeSearchView(instance); + return view.appendTo($fix) .done(function () { ok($fix.find('.oe_searchview_filters').length, "filters drawer control has been drawn"); @@ -950,50 +884,44 @@ $(document).ready(function () { "filters advanced search has been drawn"); }); }); - - module('filters', { - setup: function () { - instance = openerp.testing.instanceFor('search'); - - openerp.testing.loadTemplate(instance); - - openerp.testing.mockifyRPC(instance, { - '/web/searchview/load': function () { - // view with a single group of filters - return {result: {fields_view: { - type: 'search', - fields: {}, - arch: { - tag: 'search', - attrs: {}, - children: [{ - tag: 'filter', - attrs: { string: "Foo1", domain: [ ['foo', '=', '1'] ] }, - children: [] - }, { - tag: 'filter', - attrs: { - name: 'foo2', - string: "Foo2", - domain: [ ['foo', '=', '2'] ] }, - children: [] - }, { - tag: 'filter', - attrs: { string: "Foo3", domain: [ ['foo', '=', '3'] ] }, - children: [] - }] - } - }}}; +}); +openerp.testing.section('filters', { + dependencies: ['web.search'], + rpc: 'mock', + templates: true, + setup: function (instance, $s, mock) { + mock('/web/searchview/load', function () { + // view with a single group of filters + return {fields_view: { + type: 'search', + fields: {}, + arch: { + tag: 'search', + attrs: {}, + children: [{ + tag: 'filter', + attrs: { string: "Foo1", domain: [ ['foo', '=', '1'] ] }, + children: [] + }, { + tag: 'filter', + attrs: { + name: 'foo2', + string: "Foo2", + domain: [ ['foo', '=', '2'] ] }, + children: [] + }, { + tag: 'filter', + attrs: { string: "Foo3", domain: [ ['foo', '=', '3'] ] }, + children: [] + }] } - }); - } - }); - asyncTest('drawn', 3, function () { - var view = makeSearchView(); - var $fix = $('#qunit-fixture'); - view.appendTo($fix) - .always(start) - .fail(function (error) { ok(false, error.message); }) + }}; + }); + } +}, function (test) { + test('drawn', {asserts: 3}, function (instance, $fix) { + var view = makeSearchView(instance); + return view.appendTo($fix) .done(function () { var $fs = $fix.find('.oe_searchview_filters ul'); // 3 filters, 1 filtergroup, 1 custom filters widget, @@ -1006,12 +934,9 @@ $(document).ready(function () { "Text content of first filter option should match filter string"); }); }); - asyncTest('click adding from empty query', 4, function () { - var view = makeSearchView(); - var $fix = $('#qunit-fixture'); - view.appendTo($fix) - .always(start) - .fail(function (error) { ok(false, error.message); }) + test('click adding from empty query', {asserts: 4}, function (instance, $fix) { + var view = makeSearchView(instance); + return view.appendTo($fix) .done(function () { var $fs = $fix.find('.oe_searchview_filters ul'); $fs.children(':eq(2)').trigger('click'); @@ -1025,12 +950,9 @@ $(document).ready(function () { "value should be third filter"); }); }); - asyncTest('click adding from existing query', 4, function () { - var view = makeSearchView({}, {foo2: true}); - var $fix = $('#qunit-fixture'); - view.appendTo($fix) - .always(start) - .fail(function (error) { ok(false, error.message); }) + test('click adding from existing query', {asserts: 4}, function (instance, $fix) { + var view = makeSearchView(instance, {}, {foo2: true}); + return view.appendTo($fix) .done(function () { var $fs = $fix.find('.oe_searchview_filters ul'); $fs.children(':eq(2)').trigger('click'); @@ -1045,16 +967,13 @@ $(document).ready(function () { "second value should be clicked filter"); }); }); - asyncTest('click removing from query', 4, function () { + test('click removing from query', {asserts: 4}, function (instance, $fix) { var calls = 0; - var view = makeSearchView({}, {foo2: true}); + var view = makeSearchView(instance, {}, {foo2: true}); view.on('search_data', null, function () { ++calls; }); - var $fix = $('#qunit-fixture'); - view.appendTo($fix) - .always(start) - .fail(function (error) { ok(false, error.message); }) + return view.appendTo($fix) .done(function () { var $fs = $fix.find('.oe_searchview_filters ul'); // sanity check @@ -1065,29 +984,19 @@ $(document).ready(function () { strictEqual(calls, 1, "one search should have been triggered"); }); }); +}); +openerp.testing.section('saved_filters', { + dependencies: ['web.search'], + rpc: 'mock', + templates: true +}, function (test) { + test('checkboxing', {asserts: 6}, function (instance, $fix, mock) { + var view = makeSearchView(instance); + mock('/web/searchview/get_filters', function () { + return [{ name: "filter name", user_id: 42 }]; + }); - 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); }) + return view.appendTo($fix) .done(function () { var $row = $fix.find('.oe_searchview_custom li:first').click(); @@ -1104,44 +1013,31 @@ $(document).ready(function () { "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'); + test('removal', {asserts: 1}, function (instance, $fix, mock) { + var view = makeSearchView(instance); + mock('/web/searchview/get_filters', function () { + return [{ name: "filter name", user_id: 42 }]; + }); - view.appendTo($fix) - .always(start) - .fail(function (error) { ok(false, error.message); }) + return view.appendTo($fix) .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 = openerp.testing.instanceFor('search'); - - openerp.testing.loadTemplate(instance); - - openerp.testing.mockifyRPC(instance); - } + }); }); - asyncTest('single-advanced', 6, function () { - var view = makeSearchView(); - var $fix = $('#qunit-fixture'); - - view.appendTo($fix) - .always(start) - .fail(function (error) { ok(false, error.message); }) +}); +openerp.testing.section('advanced', { + dependencies: ['web.search'], + rpc: 'mock', + templates: true +}, function (test) { + test('single-advanced', {asserts: 6}, function (instance, $fix) { + var view = makeSearchView(instance); + + return view.appendTo($fix) .done(function () { var $advanced = $fix.find('.oe_searchview_advanced'); // open advanced search (not actually useful) @@ -1174,13 +1070,10 @@ $(document).ready(function () { "advanced search facet should return proposed domain"); }); }); - asyncTest('multiple-advanced', 3, function () { - var view = makeSearchView(); - var $fix = $('#qunit-fixture'); + test('multiple-advanced', {asserts: 3}, function (instance, $fix) { + var view = makeSearchView(instance); - view.appendTo($fix) - .always(start) - .fail(function (error) { ok(false, error.message); }) + return view.appendTo($fix) .done(function () { var $advanced = $fix.find('.oe_searchview_advanced'); // open advanced search (not actually useful) |
