diff --git a/addons/bus/static/tests/helpers/mock_server.js b/addons/bus/static/tests/helpers/mock_server.js new file mode 100644 index 00000000000..7ee17261cee --- /dev/null +++ b/addons/bus/static/tests/helpers/mock_server.js @@ -0,0 +1,62 @@ +/** @odoo-module **/ + +import { patch } from "@web/core/utils/patch"; +import { MockServer } from "@web/../tests/helpers/mock_server"; +import { makeDeferred } from "@web/../tests/helpers/utils"; + +patch(MockServer.prototype, 'bus', { + init() { + this._super(...arguments); + this.pendingLongpollingPromise = null; + this.notificationsToBeResolved = []; + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @override + */ + async _performRPC(route, args) { + if (route === '/longpolling/poll') { + const longpollingPromise = makeDeferred(); + if (this.notificationsToBeResolved.length) { + longpollingPromise.resolve(this.notificationsToBeResolved); + this.notificationsToBeResolved = []; + } else { + this.pendingLongpollingPromise = longpollingPromise; + } + return longpollingPromise; + } + return this._super(route, args); + }, + /** + * Simulates `_sendone` on `bus.bus`. + * + * @param {string} channel + * @param {string} notificationType + * @param {any} message + */ + _mockBusBus__sendone(channel, notificationType, message) { + this._mockBusBus__sendmany([[channel, notificationType, message]]); + }, + /** + * Simulates `_sendmany` on `bus.bus`. + * + * @param {Array} notifications + */ + _mockBusBus__sendmany(notifications) { + const values = []; + for (const notification of notifications) { + const [type, payload] = notification.slice(1, notification.length); + values.push({ message: { payload, type } }); + } + if (this.pendingLongpollingPromise) { + this.pendingLongpollingPromise.resolve(values); + this.pendingLongpollingPromise = null; + } else { + this.notificationsToBeResolved.push(...values); + } + }, +}); diff --git a/addons/mail/static/tests/helpers/mock_server.js b/addons/mail/static/tests/helpers/mock_server.js index 4e758195002..568df1cb6e4 100644 --- a/addons/mail/static/tests/helpers/mock_server.js +++ b/addons/mail/static/tests/helpers/mock_server.js @@ -578,29 +578,6 @@ patch(MockServer.prototype, 'mail', { // Private Mocked Methods //-------------------------------------------------------------------------- - /** - * Simulates `_sendone` on `bus.bus`. - * - * @param {string} channel - * @param {string} notificationType - * @param {any} message - */ - _mockBusBus__sendone(channel, notificationType, message) { - this._mockBusBus__sendmany([[channel, notificationType, message]]); - }, - /** - * Simulates `_sendmany` on `bus.bus`. - * - * @param {Array} notifications - */ - _mockBusBus__sendmany(notifications) { - const values = []; - for (const notification of notifications) { - const [type, payload] = notification.slice(1, notification.length); - values.push({ payload, type }); - } - owl.Component.env.services['bus_service'].trigger('notification', values); - }, /** * Simulates `_attachment_format` on `ir.attachment`. * diff --git a/addons/mail/static/tests/helpers/webclient_setup.js b/addons/mail/static/tests/helpers/webclient_setup.js index 01a67fa4b8d..9b75490197b 100644 --- a/addons/mail/static/tests/helpers/webclient_setup.js +++ b/addons/mail/static/tests/helpers/webclient_setup.js @@ -18,7 +18,8 @@ import { registry } from '@web/core/registry'; import { patchWithCleanup } from "@web/../tests/helpers/utils"; import { createWebClient } from "@web/../tests/webclient/helpers"; -const WEBCLIENT_LOAD_ROUTES = [ +const ROUTES_TO_IGNORE = [ + '/longpolling/poll', '/web/webclient/load_menus', '/web/dataset/call_kw/res.users/load_views', '/web/dataset/call_kw/res.users/systray_get_activities' @@ -90,7 +91,6 @@ function setupMessagingServiceRegistries({ const originalService = busService.start(...arguments); Object.assign(originalService, { _beep() {}, // Do nothing - _poll() {}, // Do nothing _registerWindowUnload() {}, // Do nothing updateOption() {}, }); @@ -156,5 +156,5 @@ function setupMessagingServiceRegistries({ export { getWebClientReady, - WEBCLIENT_LOAD_ROUTES, + ROUTES_TO_IGNORE, }; diff --git a/addons/mail/static/tests/qunit_suite_tests/chatter_tests.js b/addons/mail/static/tests/qunit_suite_tests/chatter_tests.js index 69326a553e6..5398a3b2278 100644 --- a/addons/mail/static/tests/qunit_suite_tests/chatter_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/chatter_tests.js @@ -1,7 +1,7 @@ /** @odoo-module **/ import { start, startServer } from '@mail/../tests/helpers/test_utils'; -import { WEBCLIENT_LOAD_ROUTES } from '@mail/../tests/helpers/webclient_setup'; +import { ROUTES_TO_IGNORE } from '@mail/../tests/helpers/webclient_setup'; import testUtils from 'web.test_utils'; import { clickEdit, patchWithCleanup, selectDropdownItem } from '@web/../tests/helpers/utils'; @@ -21,7 +21,7 @@ QUnit.test('list activity widget with no activity', async function (assert) { mockRPC: function (route, args) { if ( args.method !== 'get_views' && - !['/mail/init_messaging', '/mail/load_message_failures', '/longpolling/im_status', ...WEBCLIENT_LOAD_ROUTES].includes(route) + !['/mail/init_messaging', '/mail/load_message_failures', '/longpolling/im_status', ...ROUTES_TO_IGNORE].includes(route) ) { assert.step(route); } @@ -70,7 +70,7 @@ QUnit.test('list activity widget with activities', async function (assert) { mockRPC: function (route, args) { if ( args.method !== 'get_views' && - !['/mail/init_messaging', '/mail/load_message_failures', '/longpolling/im_status', ...WEBCLIENT_LOAD_ROUTES].includes(route) + !['/mail/init_messaging', '/mail/load_message_failures', '/longpolling/im_status', ...ROUTES_TO_IGNORE].includes(route) ) { assert.step(route); } @@ -115,7 +115,7 @@ QUnit.test('list activity widget with exception', async function (assert) { mockRPC: function (route, args) { if ( args.method !== 'get_views' && - !['/mail/init_messaging', '/mail/load_message_failures', '/longpolling/im_status', ...WEBCLIENT_LOAD_ROUTES].includes(route) + !['/mail/init_messaging', '/mail/load_message_failures', '/longpolling/im_status', ...ROUTES_TO_IGNORE].includes(route) ) { assert.step(route); } @@ -172,7 +172,7 @@ QUnit.test('list activity widget: open dropdown', async function (assert) { mockRPC: function (route, args) { if ( args.method !== 'get_views' && - !['/mail/init_messaging', '/mail/load_message_failures', '/longpolling/im_status', ...WEBCLIENT_LOAD_ROUTES].includes(route) + !['/mail/init_messaging', '/mail/load_message_failures', '/longpolling/im_status', ...ROUTES_TO_IGNORE].includes(route) ) { assert.step(args.method || route); } diff --git a/addons/web/static/tests/webclient/helpers.js b/addons/web/static/tests/webclient/helpers.js index 326322b7027..827f24db852 100644 --- a/addons/web/static/tests/webclient/helpers.js +++ b/addons/web/static/tests/webclient/helpers.js @@ -52,6 +52,7 @@ import Widget from "web.Widget"; import { uiService } from "@web/core/ui/ui_service"; import { ClientActionAdapter, ViewAdapter } from "@web/legacy/action_adapters"; import { commandService } from "@web/core/commands/command_service"; +import { ConnectionAbortedError } from "@web/core/network/rpc_service"; import { CustomFavoriteItem } from "@web/search/favorite_menu/custom_favorite_item"; import { standaloneAdapter } from "web.OwlCompatibility"; @@ -215,7 +216,7 @@ export async function addLegacyMockEnvironment(env, legacyParams = {}) { const legacyMockServer = new LegacyMockServer(legacyParams.models, { widget }); await legacyMockServer.setup(); const originalRPC = env.services.rpc; - env.services.rpc = async (...args) => { + const rpc = async (...args) => { try { return await originalRPC(...args); } catch (e) { @@ -226,6 +227,15 @@ export async function addLegacyMockEnvironment(env, legacyParams = {}) { } } }; + env.services.rpc = function () { + let rejectFn; + const rpcProm = new Promise((resolve, reject) => { + rejectFn = reject; + rpc(...arguments).then(resolve).catch(reject); + }); + rpcProm.abort = () => rejectFn(new ConnectionAbortedError("XmlHttpRequestError abort")); + return rpcProm; + }; } }