diff options
| author | Aaron Bohy <aab@odoo.com> | 2017-10-27 11:32:10 +0200 |
|---|---|---|
| committer | Géry Debongnie <ged@odoo.com> | 2017-11-10 10:24:42 +0100 |
| commit | 9bc5009481de188b72da21bd7a0d246a60a070ef (patch) | |
| tree | 1522af8ae79a362728cd293b641c399f59b7d280 /addons/web | |
| parent | b4debf7e1b19710ef3dcc39448d08a698b5657b0 (diff) | |
[FIX] web(_editor): enable mobile tests
This rev. introduces a new test suite meant to test the webclient
components on mobile devices. The key 'config.device.isMobile' is
forced to true in this test suite, so that mobile specific JS files
are properly executed, which isn't the case in the classic JS test
suite (setting isMobile to true in the test definition is too late,
as the JS files are already processed).
For now, this new test suite contains a single test, which was
skipped until this rev. as it couldn't be executed in the classical
JS test suite.
Both suites are executed at each build of the runbot, and they
can be manually executed from the webclient as well (via the debug
manager).
Diffstat (limited to 'addons/web')
| -rw-r--r-- | addons/web/controllers/main.py | 4 | ||||
| -rw-r--r-- | addons/web/static/src/js/widgets/debug_manager.js | 15 | ||||
| -rw-r--r-- | addons/web/static/src/xml/base.xml | 1 | ||||
| -rw-r--r-- | addons/web/static/tests/views/kanban_mobile_tests.js | 101 | ||||
| -rw-r--r-- | addons/web/static/tests/views/kanban_tests.js | 49 | ||||
| -rw-r--r-- | addons/web/tests/test_js.py | 5 | ||||
| -rw-r--r-- | addons/web/views/webclient_templates.xml | 144 |
7 files changed, 219 insertions, 100 deletions
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index b16c0c0c2cb..82329378975 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -612,6 +612,10 @@ class WebClient(http.Controller): def test_suite(self, mod=None, **kwargs): return request.render('web.qunit_suite') + @http.route('/web/tests/mobile', type='http', auth="none") + def test_mobile_suite(self, mod=None, **kwargs): + return request.render('web.qunit_mobile_suite') + @http.route('/web/benchmarks', type='http', auth="none") def benchmarks(self, mod=None, **kwargs): return request.render('web.benchmark_suite') diff --git a/addons/web/static/src/js/widgets/debug_manager.js b/addons/web/static/src/js/widgets/debug_manager.js index a214d8b55a4..8007dc2ab7e 100644 --- a/addons/web/static/src/js/widgets/debug_manager.js +++ b/addons/web/static/src/js/widgets/debug_manager.js @@ -6,7 +6,6 @@ var dialogs = require('web.view_dialogs'); var core = require('web.core'); var Dialog = require('web.Dialog'); var field_utils = require('web.field_utils'); -var framework = require('web.framework'); var session = require('web.session'); var SystrayMenu = require('web.SystrayMenu'); var utils = require('web.utils'); @@ -189,6 +188,9 @@ var DebugManager = Widget.extend({ } }).open(); }, + /** + * Runs the JS (desktop) tests + */ perform_js_tests: function () { this.do_action({ name: _t("JS Tests"), @@ -197,6 +199,17 @@ var DebugManager = Widget.extend({ url: '/web/tests?mod=*' }); }, + /** + * Runs the JS mobile tests + */ + perform_js_mobile_tests: function () { + this.do_action({ + name: _t("JS Mobile Tests"), + target: 'new', + type: 'ir.actions.act_url', + url: '/web/tests/mobile?mod=*' + }); + }, split_assets: function() { window.location = $.param.querystring(window.location.href, 'debug=assets'); }, diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 12f979a3c37..79baca71589 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -220,6 +220,7 @@ </t> <t t-name="WebClient.DebugManager.Global"> <li><a href="#" data-action="perform_js_tests">Run JS Tests</a></li> + <li><a href="#" data-action="perform_js_mobile_tests">Run JS Mobile Tests</a></li> <li><a href="#" data-action="select_view">Open View</a></li> <t t-if="manager._events"> <li class="divider"/> diff --git a/addons/web/static/tests/views/kanban_mobile_tests.js b/addons/web/static/tests/views/kanban_mobile_tests.js new file mode 100644 index 00000000000..d777f5bd87b --- /dev/null +++ b/addons/web/static/tests/views/kanban_mobile_tests.js @@ -0,0 +1,101 @@ +odoo.define('web.kanban_mobile_tests', function (require) { +"use strict"; + +var KanbanView = require('web.KanbanView'); +var testUtils = require('web.test_utils'); + +var createView = testUtils.createView; + +QUnit.module('Views', { + beforeEach: function () { + this.data = { + partner: { + fields: { + foo: {string: "Foo", type: "char"}, + bar: {string: "Bar", type: "boolean"}, + int_field: {string: "int_field", type: "integer", sortable: true}, + qux: {string: "my float", type: "float"}, + product_id: {string: "something_id", type: "many2one", relation: "product"}, + category_ids: { string: "categories", type: "many2many", relation: 'category'}, + state: { string: "State", type: "selection", selection: [["abc", "ABC"], ["def", "DEF"], ["ghi", "GHI"]]}, + date: {string: "Date Field", type: 'date'}, + datetime: {string: "Datetime Field", type: 'datetime'}, + }, + records: [ + {id: 1, bar: true, foo: "yop", int_field: 10, qux: 0.4, product_id: 3, state: "abc", category_ids: []}, + {id: 2, bar: true, foo: "blip", int_field: 9, qux: 13, product_id: 5, state: "def", category_ids: [6]}, + {id: 3, bar: true, foo: "gnap", int_field: 17, qux: -3, product_id: 3, state: "ghi", category_ids: [7]}, + {id: 4, bar: false, foo: "blip", int_field: -4, qux: 9, product_id: 5, state: "ghi", category_ids: []}, + ] + }, + product: { + fields: { + id: {string: "ID", type: "integer"}, + name: {string: "Display Name", type: "char"}, + }, + records: [ + {id: 3, name: "hello"}, + {id: 5, name: "xmo"}, + ] + }, + category: { + fields: { + name: {string: "Category Name", type: "char"}, + color: {string: "Color index", type: "integer"}, + }, + records: [ + {id: 6, name: "gold", color: 2}, + {id: 7, name: "silver", color: 5}, + ] + }, + }; + }, +}, function () { + + QUnit.module('KanbanView Mobile'); + + QUnit.test('mobile grouped rendering', function (assert) { + assert.expect(8); + + var kanban = createView({ + View: KanbanView, + model: 'partner', + data: this.data, + arch: '<kanban class="o_kanban_test o_kanban_small_column" on_create="quick_create">' + + '<templates><t t-name="kanban-box">' + + '<div><field name="foo"/></div>' + + '</t></templates>' + + '</kanban>', + groupBy: ['product_id'], + }); + + // basic rendering tests + assert.strictEqual(kanban.$('.o_kanban_group').length, 2, "should have 2 columns" ); + assert.ok(kanban.$('.o_kanban_mobile_tab:first').hasClass('o_current'), + "first tab is the active tab with class 'o_current'"); + assert.strictEqual(kanban.$('.o_kanban_group:first > div.o_kanban_record').length, 2, + "there are 2 records in active tab"); + assert.strictEqual(kanban.$('.o_kanban_group:nth(1) > div.o_kanban_record').length, 0, + "there is no records in next tab. Records will be loaded when it will be opened"); + + // quick create in first column + kanban.$buttons.find('.o-kanban-button-new').click(); + assert.ok(kanban.$('.o_kanban_group:nth(0) > div:nth(1)').hasClass('o_kanban_quick_create'), + "clicking on create should open the quick_create in the first column"); + + // move to second column + kanban.$('.o_kanban_mobile_tab:nth(1)').trigger('click'); + assert.ok(kanban.$('.o_kanban_mobile_tab:nth(1)').hasClass('o_current'), + "second tab is now active with class 'o_current'"); + assert.strictEqual(kanban.$('.o_kanban_group:nth(1) > div.o_kanban_record').length, 2, + "the 2 records of the second group have now been loaded"); + + // quick create in second column + kanban.$buttons.find('.o-kanban-button-new').click(); + assert.ok(kanban.$('.o_kanban_group:nth(1) > div:nth(1)').hasClass('o_kanban_quick_create'), + "clicking on create should open the quick_create in the second column"); + + kanban.destroy(); + }); +}); +}); diff --git a/addons/web/static/tests/views/kanban_tests.js b/addons/web/static/tests/views/kanban_tests.js index cfd9e1210ba..f614fa9af64 100644 --- a/addons/web/static/tests/views/kanban_tests.js +++ b/addons/web/static/tests/views/kanban_tests.js @@ -2129,55 +2129,6 @@ QUnit.module('Views', { "quick create should have been added in the first column"); } }); - - QUnit.skip('mobile grouped rendering', function (assert) { - // Temporarily disable this test until we introduce a mobile test suite, as - // the code of the kanban renderer for mobile is in a specific file which isn't - // executed in desktop (so setting 'isMobile: True' in the test is useless). - // So to re-activate this test, it will need to be moved in another file - // included in the bundle of the mobile test suite. - assert.expect(8); - var done = assert.async(); - - createAsyncView({ - View: KanbanView, - model: 'partner', - data: this.data, - arch: '<kanban class="o_kanban_test o_kanban_small_column" on_create="quick_create">' + - '<templates><t t-name="kanban-box">' + - '<div><field name="foo"/></div>' + - '</t></templates>' + - '</kanban>', - groupBy: ['product_id'], - config: {device: {isMobile: true}}, - }).then(function (kanban) { - - // Dummy dom update trigger for activate mobile tabs and move to first column - core.bus.trigger("DOM_updated"); - - assert.equal(kanban.$el.find('.o_kanban_group').length, 2, "2 colomns are created" ); - - kanban.$buttons.find('.o-kanban-button-new').click(); // Click on 'Create' - assert.ok(kanban.$('.o_kanban_group:nth(0) > div:nth(1)').hasClass('o_kanban_quick_create'), - "clicking on create should open the quick_create in the first column"); - - assert.equal(kanban.$el.find('.o_kanban_mobile_tab.current > span').html(), "hello", "First tab 'hello' is active tab with class 'current'" ); - assert.equal(kanban.$el.find('.o_kanban_group.current > div.o_kanban_record').length, "2", "there is 2 record in active 'hello' tab" ); - assert.equal(kanban.$el.find('.o_kanban_group.next > div.o_kanban_record').length, "0", "there is 0 record in next tab. Records will load when click on next tab"); - - kanban.$el.find('.o_kanban_mobile_tab.next').trigger('click'); // Moving to next tab - assert.equal(kanban.$el.find('.o_kanban_mobile_tab.current > span').html(), "xmo", "Second tab 'xmo' is active with class 'current'" ); - assert.equal(kanban.$el.find('.o_kanban_group.current > div.o_kanban_record').length, "2", "there is 2 record in active 'xmo' tab. Records are loaded after click on tab"); - - kanban.$buttons.find('.o-kanban-button-new').click(); // Click on 'Create' - assert.ok(kanban.$('.o_kanban_group:nth(1) > div:nth(1)').hasClass('o_kanban_quick_create'), - "clicking on create should open the quick_create in the second column"); - - kanban.destroy(); - done(); - }); - }); - }); }); diff --git a/addons/web/tests/test_js.py b/addons/web/tests/test_js.py index 17eb5c8beb2..0b1f8ed3763 100644 --- a/addons/web/tests/test_js.py +++ b/addons/web/tests/test_js.py @@ -11,8 +11,13 @@ class WebSuite(odoo.tests.HttpCase): at_install = False def test_01_js(self): + # webclient desktop test suite self.phantom_js('/web/tests?mod=web', "", "", login='admin', timeout=300) + def test_02_js(self): + # webclient mobile test suite + self.phantom_js('/web/tests/mobile?mod=web', "", "", login='admin', timeout=300) + def test_check_suite(self): # verify no js test is using `QUnit.only` as it forbid any other test to be executed re_only = re.compile('QUnit\.only\(') diff --git a/addons/web/views/webclient_templates.xml b/addons/web/views/webclient_templates.xml index 77a5c4bedba..5117d1e633c 100644 --- a/addons/web/views/webclient_templates.xml +++ b/addons/web/views/webclient_templates.xml @@ -396,60 +396,67 @@ </a> </template> + <template id="web.js_tests_assets"> + <link type="text/css" rel="stylesheet" href="/web/static/lib/qunit/qunit-2.2.1.css"/> + <script type="text/javascript" src="/web/static/lib/qunit/qunit-2.2.1.js"></script> + <script type="text/javascript" src="/web/static/tests/helpers/qunit_config.js"></script> + + <t t-call-assets="web.assets_common" t-js="false"/> + <t t-call-assets="web.assets_backend" t-js="false"/> + <t t-call-assets="web.assets_common" t-css="false"/> + <t t-call-assets="web.assets_backend" t-css="false"/> + + <!-- add lazy-loaded libs to make tests synchronous --> + <link rel="stylesheet" href="/web/static/lib/fullcalendar/css/fullcalendar.css"/> + <script type="text/javascript" src="/web/static/lib/fullcalendar/js/fullcalendar.js"></script> + <link rel="stylesheet" type="text/css" href="/web/static/lib/nvd3/nv.d3.css"/> + <script type="text/javascript" src="/web/static/lib/nvd3/d3.v3.js"></script> + <script type="text/javascript" src="/web/static/lib/nvd3/nv.d3.js"></script> + <script type="text/javascript" src="/web/static/src/js/libs/nvd3.js"></script> + <script type="text/javascript" src="/web/static/lib/ace/ace.odoo-custom.js"></script> + <script type="text/javascript" src="/web/static/lib/ace/mode-python.js"></script> + <script type="text/javascript" src="/web/static/lib/ace/mode-xml.js"></script> + + <script type="text/javascript"> + // define the 'web.web_client' module because some other modules require it + odoo.define('web.web_client', function (require) { + var WebClient = require('web.WebClient'); + var web_client = new WebClient(); + // override _call_service to prevent the web_client from doing RPCs + web_client._call_service = function () {}; + return web_client; + }); + </script> + + <style> + body { + position: relative; // bootstrap-datepicker needs this + } + body:not(.debug) .modal-backdrop, body:not(.debug) .modal, body:not(.debug) .ui-autocomplete { + opacity: 0 !important; + } + #qunit-testrunner-toolbar label { + font-weight: inherit; + margin-bottom: inherit; + } + #qunit-testrunner-toolbar input[type=text] { + width: inherit; + display: inherit; + } + </style> + + <script type="text/javascript" src="/web/static/tests/helpers/test_utils.js"></script> + <script type="text/javascript" src="/web/static/tests/helpers/mock_server.js"></script> + + <script type="text/javascript" src="/web/static/tests/boot_tests.js"></script> + </template> + <template id="web.qunit_suite"> <t t-call="web.layout"> <t t-set="html_data" t-value="{'style': 'height: 100%;'}"/> <t t-set="title">Web Tests</t> <t t-set="head"> - <link type="text/css" rel="stylesheet" href="/web/static/lib/qunit/qunit-2.2.1.css"/> - <script type="text/javascript" src="/web/static/lib/qunit/qunit-2.2.1.js"></script> - <script type="text/javascript" src="/web/static/tests/helpers/qunit_config.js"></script> - - <t t-call-assets="web.assets_common" t-js="false"/> - <t t-call-assets="web.assets_backend" t-js="false"/> - <t t-call-assets="web.assets_common" t-css="false"/> - <t t-call-assets="web.assets_backend" t-css="false"/> - - <!-- add lazy-loaded libs --> - <link rel="stylesheet" href="/web/static/lib/fullcalendar/css/fullcalendar.css"/> - <script type="text/javascript" src="/web/static/lib/fullcalendar/js/fullcalendar.js"></script> - <link rel="stylesheet" type="text/css" href="/web/static/lib/nvd3/nv.d3.css"/> - <script type="text/javascript" src="/web/static/lib/nvd3/d3.v3.js"></script> - <script type="text/javascript" src="/web/static/lib/nvd3/nv.d3.js"></script> - <script type="text/javascript" src="/web/static/src/js/libs/nvd3.js"></script> - <script type="text/javascript" src="/web/static/lib/ace/ace.odoo-custom.js"></script> - <script type="text/javascript" src="/web/static/lib/ace/mode-python.js"></script> - <script type="text/javascript" src="/web/static/lib/ace/mode-xml.js"></script> - - <script type="text/javascript"> - // define the 'web.web_client' module because some other modules require it - odoo.define('web.web_client', function (require) { - var WebClient = require('web.WebClient'); - var web_client = new WebClient(); - // override _call_service to prevent the web_client from doing RPCs - web_client._call_service = function () {}; - return web_client; - }); - </script> - - <style> - body { - position: relative; // bootstrap-datepicker needs this - } - body:not(.debug) .modal-backdrop, body:not(.debug) .modal, body:not(.debug) .ui-autocomplete { - opacity: 0 !important; - } - #qunit-testrunner-toolbar label { - font-weight: inherit; - margin-bottom: inherit; - } - #qunit-testrunner-toolbar input[type=text] { - width: inherit; - display: inherit; - } - </style> - <script type="text/javascript" src="/web/static/tests/helpers/test_utils.js"></script> - <script type="text/javascript" src="/web/static/tests/helpers/mock_server.js"></script> + <t t-call="web.js_tests_assets"/> <script type="text/javascript" src="/web/static/tests/fields/basic_fields_tests.js"></script> <script type="text/javascript" src="/web/static/tests/fields/field_utils_tests.js"></script> @@ -486,8 +493,45 @@ <script type="text/javascript" src="/web/static/tests/widgets/domain_selector_tests.js"/> <script type="text/javascript" src="/web/static/tests/widgets/model_field_selector_tests.js"/> <script type="text/javascript" src="/web/static/tests/widgets/rainbow_man_tests.js"/> + </t> + + <div id="qunit"/> + <div id="qunit-fixture"/> + </t> + </template> + + <template id="web.qunit_mobile_suite"> + <t t-call="web.layout"> + <t t-set="html_data" t-value="{'style': 'height: 100%;'}"/> + <t t-set="title">Web Mobile Tests</t> + <t t-set="head"> + <script> + // force the config.device.isMobile key to be true so that + // mobile specific files aren't rejected + window.odoo = {}; + var odooDefine; + Object.defineProperty(window.odoo, 'define', { + get: function () { + return odooDefine; + }, + set: function (define) { + odooDefine = function () { + define.apply(this, arguments); + if (arguments[0] === 'web.config') { + define.call(this, 'web.config.patch', function (require) { + var config = require('web.config'); + config.device.isMobile = true; + }); + } + }; + }, + }); + </script> + + <t t-call="web.js_tests_assets"/> + <script type="text/javascript" src="/web/static/lib/jquery.touchSwipe/jquery.touchSwipe.js"></script> - <script type="text/javascript" src="/web/static/tests/boot_tests.js"></script> + <script type="text/javascript" src="/web/static/tests/views/kanban_mobile_tests.js"></script> </t> <div id="qunit"/> |
