diff --git a/addons/barcodes/static/tests/barcode_tests.js b/addons/barcodes/static/tests/barcode_tests.js index 142fc0feca3..0e2996d8608 100644 --- a/addons/barcodes/static/tests/barcode_tests.js +++ b/addons/barcodes/static/tests/barcode_tests.js @@ -65,11 +65,13 @@ QUnit.test('Button with barcode_trigger', function (assert) { '' + '', res_id: 2, - services: [NotificationService.extend({ - notify: function (params) { - assert.step(params.type); - } - })], + services: { + notification: NotificationService.extend({ + notify: function (params) { + assert.step(params.type); + } + }), + }, intercepts: { execute_action: function (event) { assert.strictEqual(event.data.action_data.name, 'do_something', @@ -512,11 +514,13 @@ QUnit.test('barcode_scanned only trigger error for active view', function (asser '', }, res_id: 1, - services: [NotificationService.extend({ - notify: function (params) { - assert.step(params.type); - } - })], + services: { + notification: NotificationService.extend({ + notify: function (params) { + assert.step(params.type); + } + }), + }, viewOptions: { mode: 'edit', }, diff --git a/addons/bus/static/src/js/services/bus_service.js b/addons/bus/static/src/js/services/bus_service.js index 9a40abae930..e0bf8b42636 100644 --- a/addons/bus/static/src/js/services/bus_service.js +++ b/addons/bus/static/src/js/services/bus_service.js @@ -7,7 +7,6 @@ var AbstractService = require('web.AbstractService'); var core = require('web.core'); var BusService = AbstractService.extend({ - name: 'bus_service', /** * @override */ diff --git a/addons/mail/static/src/js/services/mail_manager.js b/addons/mail/static/src/js/services/mail_manager.js index 6f159951436..d04028267c2 100644 --- a/addons/mail/static/src/js/services/mail_manager.js +++ b/addons/mail/static/src/js/services/mail_manager.js @@ -44,7 +44,6 @@ var _lt = core._lt; var PREVIEW_MSG_MAX_SIZE = 350; // optimal for native english speakers var MailManager = AbstractService.extend({ - name: 'mail_service', dependencies: ['ajax', 'bus_service', 'local_storage'], _ODOOBOT_ID: "ODOOBOT", // default authorID for transient messages diff --git a/addons/mail/static/tests/chatter_tests.js b/addons/mail/static/tests/chatter_tests.js index c7c082148a0..17f304b067a 100644 --- a/addons/mail/static/tests/chatter_tests.js +++ b/addons/mail/static/tests/chatter_tests.js @@ -424,7 +424,7 @@ QUnit.test('chatter: post, receive and star messages', function (assert) { var done = assert.async(); assert.expect(27); - var bus = this.services[1].prototype.bus; + var bus = this.services.bus_service.prototype.bus; this.data.partner.records[0].message_ids = [1]; this.data['mail.message'].records = [{ @@ -784,7 +784,7 @@ QUnit.test('chatter: discard changes on message post with post_refresh "recipien var getSuggestionsDef = $.Deferred(); var messages = []; - var bus = this.services[1].prototype.bus; + var bus = this.services.bus_service.prototype.bus; var form = createView({ View: FormView, model: 'partner', diff --git a/addons/mail/static/tests/discuss_moderation_tests.js b/addons/mail/static/tests/discuss_moderation_tests.js index 8940efa1185..65efc32cc36 100644 --- a/addons/mail/static/tests/discuss_moderation_tests.js +++ b/addons/mail/static/tests/discuss_moderation_tests.js @@ -533,7 +533,7 @@ QUnit.test('author: send message in moderated channel', function (assert) { assert.expect(4); var done = assert.async(); - var bus = this.services[1].prototype.bus; + var bus = this.services.bus_service.prototype.bus; var messagePostDef = $.Deferred(); @@ -613,7 +613,7 @@ QUnit.test('author: sent message accepted in moderated channel', function (asser assert.expect(8); var done = assert.async(); - var bus = this.services[1].prototype.bus; + var bus = this.services.bus_service.prototype.bus; this.data.initMessaging = { channel_slots: { @@ -696,7 +696,7 @@ QUnit.test('author: sent message rejected in moderated channel', function (asser assert.expect(5); var done = assert.async(); - var bus = this.services[1].prototype.bus; + var bus = this.services.bus_service.prototype.bus; this.data.initMessaging = { channel_slots: { diff --git a/addons/mail/static/tests/discuss_tests.js b/addons/mail/static/tests/discuss_tests.js index a061873c39b..9d61a0d2446 100644 --- a/addons/mail/static/tests/discuss_tests.js +++ b/addons/mail/static/tests/discuss_tests.js @@ -146,7 +146,7 @@ QUnit.test('@ mention in channel', function (assert) { assert.expect(34); var done = assert.async(); - var bus = this.services[1].prototype.bus; + var bus = this.services.bus_service.prototype.bus; var fetchListenersDef = $.Deferred(); var receiveMessageDef = $.Deferred(); @@ -432,7 +432,7 @@ QUnit.test('"Unstar all" button should reset the starred counter', function (ass assert.expect(2); var done = assert.async(); - var bus = this.services[1].prototype.bus; + var bus = this.services.bus_service.prototype.bus; var messageData = []; _.each(_.range(1, 41), function (num) { messageData.push({ @@ -624,7 +624,7 @@ QUnit.test('convert emoji sources to unicodes on message_post', function (assert assert.expect(2); var done = assert.async(); - var bus = this.services[1].prototype.bus; + var bus = this.services.bus_service.prototype.bus; var receiveMessageDef = $.Deferred(); this.data.initMessaging = { diff --git a/addons/mail/static/tests/helpers/mock_server.js b/addons/mail/static/tests/helpers/mock_server.js index b7e5f91c87d..4f396b76df5 100644 --- a/addons/mail/static/tests/helpers/mock_server.js +++ b/addons/mail/static/tests/helpers/mock_server.js @@ -21,11 +21,8 @@ MockServer.include({ this.initMessagingData = data.initMessaging; delete data.initMessaging; } - var BusService = _.find(options.services, function (Service) { - return Service.prototype.name === 'bus_service'; - }); - if (BusService) { - this.busBus = BusService.prototype.bus; + if (options.services && options.services.bus_service) { + this.busBus = options.services.bus_service.prototype.bus; } this._super.apply(this, arguments); diff --git a/addons/mail/static/tests/helpers/test_utils.js b/addons/mail/static/tests/helpers/test_utils.js index ff5370d57ab..f90a86bdd41 100644 --- a/addons/mail/static/tests/helpers/test_utils.js +++ b/addons/mail/static/tests/helpers/test_utils.js @@ -74,7 +74,6 @@ function getMailServices() { is_odoo_focused: function () { return true; }, }); var BusService = AbstractService.extend({ - name: 'bus_service', bus: new MockBus(), //-------------------------------------------------------------------------- @@ -89,10 +88,13 @@ function getMailServices() { } }); var LocalStorageService = AbstractStorageService.extend({ - name: 'local_storage', storage: new RamStorage(), }); - return [MailService, BusService, LocalStorageService]; + return { + mail_service: MailService, + bus_service: BusService, + local_storage: LocalStorageService, + }; } return { diff --git a/addons/mail/static/tests/systray/systray_messaging_menu_tests.js b/addons/mail/static/tests/systray/systray_messaging_menu_tests.js index e1c5ef1851c..347233efd31 100644 --- a/addons/mail/static/tests/systray/systray_messaging_menu_tests.js +++ b/addons/mail/static/tests/systray/systray_messaging_menu_tests.js @@ -149,7 +149,7 @@ QUnit.test('messaging menu widget: messaging menu with 1 record', function (asse QUnit.test('messaging menu widget: no crash when clicking on inbox notification not associated to a document', function (assert) { assert.expect(3); - var bus = this.services[1].prototype.bus; + var bus = this.services.bus_service.prototype.bus; var messagingMenu = new MessagingMenu(); testUtils.addMockEnvironment(messagingMenu, { diff --git a/addons/mail/static/tests/thread_window_tests.js b/addons/mail/static/tests/thread_window_tests.js index 724d24f901e..620aae407f6 100644 --- a/addons/mail/static/tests/thread_window_tests.js +++ b/addons/mail/static/tests/thread_window_tests.js @@ -28,30 +28,26 @@ QUnit.module('mail', { }, }; this.services = mailTestUtils.getMailServices(); - - // backup original thread window append to selector - this.MailService = _.find(this.services, function (Service) { - return Service.prototype.name === 'mail_service'; - }); - this.ORIGINAL_THREAD_WINDOW_APPENDTO = this.MailService.prototype.THREAD_WINDOW_APPENDTO; + this.ORIGINAL_THREAD_WINDOW_APPENDTO = this.services.mail_service.prototype.THREAD_WINDOW_APPENDTO; this.createParent = function (params) { var widget = new Widget(); // in non-debug mode, append thread windows in qunit-fixture if (params.debug) { - self.MailService.prototype.THREAD_WINDOW_APPENDTO = 'body'; + self.services.mail_service.prototype.THREAD_WINDOW_APPENDTO = 'body'; } else { - self.MailService.prototype.THREAD_WINDOW_APPENDTO = '#qunit-fixture'; + self.services.mail_service.prototype.THREAD_WINDOW_APPENDTO = '#qunit-fixture'; } + params.services = _.clone(params.services); testUtils.addMockEnvironment(widget, params); return widget; }; }, afterEach: function () { // reset thread window append to body - this.MailService.prototype.THREAD_WINDOW_APPENDTO = 'body'; + this.services.mail_service.prototype.THREAD_WINDOW_APPENDTO = 'body'; }, }, function () { diff --git a/addons/web/static/src/js/core/abstract_service.js b/addons/web/static/src/js/core/abstract_service.js index e6840cc92f9..c907b28f7c8 100644 --- a/addons/web/static/src/js/core/abstract_service.js +++ b/addons/web/static/src/js/core/abstract_service.js @@ -7,7 +7,6 @@ var ServicesMixin = require('web.ServicesMixin'); var AbstractService = Class.extend(Mixins.EventDispatcherMixin, ServicesMixin, { dependencies: [], - name: null, init: function (parent) { Mixins.EventDispatcherMixin.init.call(this, arguments); this.setParent(parent); diff --git a/addons/web/static/src/js/core/service_mixins.js b/addons/web/static/src/js/core/service_mixins.js index 850e9983a74..170d5dd098a 100644 --- a/addons/web/static/src/js/core/service_mixins.js +++ b/addons/web/static/src/js/core/service_mixins.js @@ -20,12 +20,18 @@ var ServiceProviderMixin = { // add already registered services from the service registry _.each(core.serviceRegistry.map, function (Service, serviceName) { + if (serviceName in self.UndeployedServices) { + throw new Error('Service "' + serviceName + '" is already loaded.'); + } self.UndeployedServices[serviceName] = Service; }); this._deployServices(); // listen on newly added services core.serviceRegistry.onAdd(function (serviceName, Service) { + if (serviceName in self.services || serviceName in self.UndeployedServices) { + throw new Error('Service "' + serviceName + '" is already loaded.'); + } self.UndeployedServices[serviceName] = Service; self._deployServices(); }); @@ -42,16 +48,16 @@ var ServiceProviderMixin = { var self = this; var done = false; while (!done) { - var Service = _.find(this.UndeployedServices, function (Service) { + var serviceName = _.findKey(this.UndeployedServices, function (Service) { // no missing dependency return !_.some(Service.prototype.dependencies, function (depName) { return !self.services[depName]; }); }); - if (Service) { - var service = new Service(this); - this.services[Service.prototype.name] = service; - delete this.UndeployedServices[Service.prototype.name]; + if (serviceName) { + var service = new this.UndeployedServices[serviceName](this); + this.services[serviceName] = service; + delete this.UndeployedServices[serviceName]; service.start(); } else { done = true; diff --git a/addons/web/static/src/js/services/ajax_service.js b/addons/web/static/src/js/services/ajax_service.js index 3446f651a59..bf754792932 100644 --- a/addons/web/static/src/js/services/ajax_service.js +++ b/addons/web/static/src/js/services/ajax_service.js @@ -6,7 +6,6 @@ var core = require('web.core'); var session = require('web.session'); var AjaxService = AbstractService.extend({ - name: 'ajax', rpc: function (route, args, options, target) { return $.Deferred(function (def) { session.rpc(route, args, options).then(function () { diff --git a/addons/web/static/src/js/services/local_storage_service.js b/addons/web/static/src/js/services/local_storage_service.js index 016ed08f2b7..694dc6dacd0 100644 --- a/addons/web/static/src/js/services/local_storage_service.js +++ b/addons/web/static/src/js/services/local_storage_service.js @@ -10,7 +10,6 @@ var core = require('web.core'); var localStorage = require('web.local_storage'); var LocalStorageService = AbstractStorageService.extend({ - name: 'local_storage', storage: localStorage, }); diff --git a/addons/web/static/src/js/services/notification_service.js b/addons/web/static/src/js/services/notification_service.js index 2196626a4f5..cc87305a6a2 100644 --- a/addons/web/static/src/js/services/notification_service.js +++ b/addons/web/static/src/js/services/notification_service.js @@ -18,7 +18,6 @@ var id = 0; */ var NotificationService = AbstractService.extend({ - name: 'notification', custom_events: { close: '_onCloseNotification', diff --git a/addons/web/static/src/js/services/report_service.js b/addons/web/static/src/js/services/report_service.js index cfd62c0499f..006c546041a 100644 --- a/addons/web/static/src/js/services/report_service.js +++ b/addons/web/static/src/js/services/report_service.js @@ -9,7 +9,6 @@ var AbstractService = require('web.AbstractService'); var core = require('web.core'); var ReportService = AbstractService.extend({ - name: 'report', dependencies: ['ajax'], /** diff --git a/addons/web/static/src/js/services/session_storage_service.js b/addons/web/static/src/js/services/session_storage_service.js index b9441f2e173..41c47af3923 100644 --- a/addons/web/static/src/js/services/session_storage_service.js +++ b/addons/web/static/src/js/services/session_storage_service.js @@ -10,7 +10,6 @@ var core = require('web.core'); var sessionStorage = require('web.sessionStorage'); var SessionStorageService = AbstractStorageService.extend({ - name: 'session_storage', storage: sessionStorage, }); diff --git a/addons/web/static/tests/chrome/action_manager_tests.js b/addons/web/static/tests/chrome/action_manager_tests.js index f59f3b30767..f68d343061f 100644 --- a/addons/web/static/tests/chrome/action_manager_tests.js +++ b/addons/web/static/tests/chrome/action_manager_tests.js @@ -1044,7 +1044,6 @@ QUnit.module('ActionManager', { assert.expect(14); var RamStorageService = AbstractStorageService.extend({ - name: 'session_storage', storage: new RamStorage(), }); @@ -1052,7 +1051,9 @@ QUnit.module('ActionManager', { actions: this.actions, archs: this.archs, data: this.data, - services: [RamStorageService], + services: { + session_storage: RamStorageService, + }, mockRPC: function (route, args) { assert.step(args.method || route); return this._super.apply(this, arguments); @@ -1821,7 +1822,9 @@ QUnit.module('ActionManager', { actions: this.actions, archs: this.archs, data: this.data, - services: [ReportService], + services: { + report: ReportService, + }, mockRPC: function (route, args) { assert.step(args.method || route); if (route === '/report/check_wkhtmltopdf') { @@ -1862,11 +1865,14 @@ QUnit.module('ActionManager', { actions: this.actions, archs: this.archs, data: this.data, - services: [ReportService, NotificationService.extend({ - notify: function (params) { - assert.step(params.type || 'notification'); - } - })], + services: { + report: ReportService, + notification: NotificationService.extend({ + notify: function (params) { + assert.step(params.type || 'notification'); + } + }), + }, mockRPC: function (route, args) { assert.step(args.method || route); if (route === '/report/check_wkhtmltopdf') { @@ -1916,11 +1922,14 @@ QUnit.module('ActionManager', { actions: this.actions, archs: this.archs, data: this.data, - services: [ReportService, NotificationService.extend({ - notify: function (params) { - assert.step(params.type || 'notification'); - } - })], + services: { + report: ReportService, + notification: NotificationService.extend({ + notify: function (params) { + assert.step(params.type || 'notification'); + } + }) + }, mockRPC: function (route, args) { assert.step(args.method || route); if (route === '/report/check_wkhtmltopdf') { @@ -2979,12 +2988,14 @@ QUnit.module('ActionManager', { actions: this.actions, archs: this.archs, data: this.data, - services: [SessionStorageService.extend({ - setItem: function (key, value) { - assert.strictEqual(value, JSON.stringify(expectedAction), - "should store the executed action in the sessionStorage"); - }, - })], + services: { + session_storage: SessionStorageService.extend({ + setItem: function (key, value) { + assert.strictEqual(value, JSON.stringify(expectedAction), + "should store the executed action in the sessionStorage"); + }, + }), + }, }); actionManager.doAction(3); @@ -3010,14 +3021,16 @@ QUnit.module('ActionManager', { actions: this.actions, archs: this.archs, data: this.data, - services: [SessionStorageService.extend({ - setItem: function (key, value) { - if (checkSessionStorage) { - assert.strictEqual(value, JSON.stringify(expectedAction), - "should correctly store the executed action in the sessionStorage"); - } - }, - })], + services: { + session_storage: SessionStorageService.extend({ + setItem: function (key, value) { + if (checkSessionStorage) { + assert.strictEqual(value, JSON.stringify(expectedAction), + "should correctly store the executed action in the sessionStorage"); + } + }, + }), + }, }); // execute an action and open a record in form view diff --git a/addons/web/static/tests/helpers/test_utils.js b/addons/web/static/tests/helpers/test_utils.js index a1b2718fc1a..eb558af5deb 100644 --- a/addons/web/static/tests/helpers/test_utils.js +++ b/addons/web/static/tests/helpers/test_utils.js @@ -427,15 +427,15 @@ function addMockEnvironment(widget, params) { // Deploy services var done = false; while (!done) { - var index = _.findIndex(params.services, function (Service) { + var serviceName = _.findKey(params.services, function (Service) { return !_.some(Service.prototype.dependencies, function (depName) { return !_.has(services, depName); }); }); - if (index !== -1) { - var Service = params.services.splice(index, 1)[0]; - services[Service.prototype.name] = new Service(widget); - services[Service.prototype.name].start(); + if (serviceName) { + var service = services[serviceName] = new params.services[serviceName](widget); + delete params.services[serviceName]; + service.start(); } else { done = true; } diff --git a/addons/web/static/tests/services/notification_service_tests.js b/addons/web/static/tests/services/notification_service_tests.js index aff3de8cc39..ac8603ae6f3 100644 --- a/addons/web/static/tests/services/notification_service_tests.js +++ b/addons/web/static/tests/services/notification_service_tests.js @@ -25,7 +25,9 @@ QUnit.module('Services', { }, }, model: 'fake_model', - services: [NotificationService], + services: { + notification: NotificationService, + }, }; }, afterEach: function () { diff --git a/addons/web/static/tests/views/form_tests.js b/addons/web/static/tests/views/form_tests.js index 9d4f6a0e9ad..219972f46c9 100644 --- a/addons/web/static/tests/views/form_tests.js +++ b/addons/web/static/tests/views/form_tests.js @@ -2850,17 +2850,19 @@ QUnit.module('Views', { arch: '
' + '' + '
', - services: [NotificationService.extend({ - notify: function (params) { - if (params.type !== 'warning') { - return; + services: { + notification: NotificationService.extend({ + notify: function (params) { + if (params.type !== 'warning') { + return; + } + assert.strictEqual(params.title, 'The following fields are invalid:', + "should have a warning with correct title"); + assert.strictEqual(params.message, '', + "should have a warning with correct message"); } - assert.strictEqual(params.title, 'The following fields are invalid:', - "should have a warning with correct title"); - assert.strictEqual(params.message, '', - "should have a warning with correct message"); - } - })], + }), + }, }); form.$buttons.find('.o_form_button_save').click(); @@ -4934,11 +4936,13 @@ QUnit.module('Views', { } return result; }, - services: [NotificationService.extend({ - notify: function (params) { - assert.step(params.type); - } - })], + services: { + notification: NotificationService.extend({ + notify: function (params) { + assert.step(params.type); + } + }), + }, }); form.$buttons.find('.o_form_button_edit').click(); diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js index 1b4b8f64153..b63ba83ae85 100644 --- a/addons/web/static/tests/views/list_tests.js +++ b/addons/web/static/tests/views/list_tests.js @@ -2154,13 +2154,15 @@ QUnit.module('Views', { '' + '' + '', - services: [NotificationService.extend({ - notify: function (params) { - if (params.type === 'warning') { - warnings++; + services: { + notification: NotificationService.extend({ + notify: function (params) { + if (params.type === 'warning') { + warnings++; + } } - } - })], + }), + }, }); // Start first line edition diff --git a/addons/web_settings_dashboard/static/tests/dashboard_tests.js b/addons/web_settings_dashboard/static/tests/dashboard_tests.js index c96087934d1..ed66ac3ecb2 100644 --- a/addons/web_settings_dashboard/static/tests/dashboard_tests.js +++ b/addons/web_settings_dashboard/static/tests/dashboard_tests.js @@ -88,11 +88,13 @@ QUnit.module('settings_dashboard', function () { } return this._super.apply(this, arguments); }, - services: [NotificationService.extend({ - notify: function (params) { - assert.step(params.type); - } - })], + services: { + notification: NotificationService.extend({ + notify: function (params) { + assert.step(params.type); + } + }), + }, }); // enter an invalid email address to invite @@ -167,11 +169,13 @@ QUnit.module('settings_dashboard', function () { } return this._super.apply(this, arguments); }, - services: [NotificationService.extend({ - notify: function (params) { - assert.step(params.type); - } - })], + services: { + notification: NotificationService.extend({ + notify: function (params) { + assert.step(params.type); + } + }), + }, }); // simulate a copy paste of multiple email addresses