[REF] web,mail: remove legacy MockServer and related utils
This commit removes the legacy implementation of the MockServer and test utils making it available in the test environment (e.g. addMockEnvironment). Part of task~3439226 closes odoo/odoo#130671 Related: odoo/enterprise#45141 Signed-off-by: Francois Georis (fge) <fge@odoo.com>
This commit is contained in:
@@ -15,13 +15,7 @@ const ROUTES_TO_IGNORE = [
|
||||
"/web/dataset/call_kw/res.users/load_views",
|
||||
"/web/dataset/call_kw/res.users/systray_get_activities",
|
||||
];
|
||||
const WEBCLIENT_PARAMETER_NAMES = new Set([
|
||||
"legacyParams",
|
||||
"mockRPC",
|
||||
"serverData",
|
||||
"target",
|
||||
"webClientClass",
|
||||
]);
|
||||
const WEBCLIENT_PARAMETER_NAMES = new Set(["mockRPC", "serverData", "target", "webClientClass"]);
|
||||
const SERVICES_PARAMETER_NAMES = new Set([
|
||||
"legacyServices",
|
||||
"loadingBaseDelayDuration",
|
||||
@@ -129,17 +123,14 @@ export const setupManager = {
|
||||
*/
|
||||
setupServiceRegistries({ loadingBaseDelayDuration = 0, messagingBus, services = {} } = {}) {
|
||||
const OriginalAudio = window.Audio;
|
||||
patchWithCleanup(
|
||||
window,
|
||||
{
|
||||
Audio: function () {
|
||||
const audio = new OriginalAudio();
|
||||
audio.preload = "none";
|
||||
audio.play = () => {};
|
||||
return audio;
|
||||
},
|
||||
}
|
||||
);
|
||||
patchWithCleanup(window, {
|
||||
Audio: function () {
|
||||
const audio = new OriginalAudio();
|
||||
audio.preload = "none";
|
||||
audio.play = () => {};
|
||||
return audio;
|
||||
},
|
||||
});
|
||||
patchWithCleanup(session, { show_effect: true });
|
||||
services["messagingValues"] = services["messagingValues"] ?? {
|
||||
start() {
|
||||
|
||||
@@ -7,12 +7,7 @@ import Widget from "@web/legacy/js/core/widget";
|
||||
var ESCAPE_KEY = $.Event("keyup", { which: 27 });
|
||||
|
||||
async function createEmptyParent(debug) {
|
||||
var widget = new Widget();
|
||||
|
||||
await testUtils.mock.addMockEnvironment(widget, {
|
||||
debug: debug || false,
|
||||
});
|
||||
return widget;
|
||||
return new Widget();
|
||||
}
|
||||
|
||||
QUnit.module('core', {}, function () {
|
||||
|
||||
@@ -5,6 +5,8 @@ import core from "@web/legacy/js/services/core";
|
||||
import Dialog from "@web/legacy/js/core/dialog";
|
||||
import QWeb from "@web/legacy/js/core/qweb";
|
||||
import Widget from "@web/legacy/js/core/widget";
|
||||
import session from "web.session";
|
||||
import { patchWithCleanup } from "@web/../tests/helpers/utils";
|
||||
import testUtils from "@web/../tests/legacy/helpers/test_utils";
|
||||
|
||||
QUnit.module('core', {}, function () {
|
||||
@@ -401,18 +403,19 @@ QUnit.module('core', {}, function () {
|
||||
|
||||
var def;
|
||||
var parent = new Widget();
|
||||
await testUtils.mock.addMockEnvironment(parent, {
|
||||
session: {
|
||||
rpc: function () {
|
||||
def = testUtils.makeTestPromise();
|
||||
def.abort = def.reject;
|
||||
return def;
|
||||
},
|
||||
},
|
||||
services: {
|
||||
ajax: AjaxService
|
||||
patchWithCleanup(session, {
|
||||
rpc: () => {
|
||||
def = testUtils.makeTestPromise();
|
||||
def.abort = def.reject;
|
||||
return def;
|
||||
},
|
||||
});
|
||||
var ajaxService = new AjaxService();
|
||||
testUtils.mock.intercept(parent, 'call_service', function ({ data }) {
|
||||
if (data.service === "ajax" && data.method === "rpc") {
|
||||
data.callback(ajaxService.rpc(...data.args));
|
||||
}
|
||||
});
|
||||
var widget = new Widget(parent);
|
||||
|
||||
widget._rpc({route: '/a/route'}).then(function () {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import KeyboardNavigationMixin from "@web/legacy/frontend/keyboard_navigation_mixin";
|
||||
import testUtils from "@web/../tests/legacy/helpers/test_utils";
|
||||
import Widget from "@web/legacy/js/core/widget";
|
||||
|
||||
QUnit.module('KeyboardNavigationMixin', function () {
|
||||
@@ -25,7 +24,7 @@ QUnit.module('KeyboardNavigationMixin', function () {
|
||||
return this._super(...arguments);
|
||||
},
|
||||
});
|
||||
var parent = await testUtils.createParent({});
|
||||
var parent = new Widget();
|
||||
var w = new KeyboardWidget(parent);
|
||||
await w.appendTo($target);
|
||||
|
||||
@@ -66,7 +65,7 @@ QUnit.module('KeyboardNavigationMixin', function () {
|
||||
return this._super(...arguments);
|
||||
},
|
||||
});
|
||||
var parent = await testUtils.createParent({});
|
||||
var parent = new Widget();
|
||||
var w = new KeyboardWidget(parent);
|
||||
await w.appendTo($target);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,6 @@
|
||||
import testUtilsFields from "@web/../tests/legacy/helpers/test_utils_fields";
|
||||
import testUtilsFile from "@web/../tests/legacy/helpers/test_utils_file";
|
||||
import testUtilsMock from "@web/../tests/legacy/helpers/test_utils_mock";
|
||||
import Widget from "@web/legacy/js/core/widget";
|
||||
|
||||
function deprecated(fn, type) {
|
||||
return function () {
|
||||
@@ -22,19 +21,6 @@
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a widget parent from given parameters.
|
||||
*
|
||||
* @param {Object} params This object will be given to addMockEnvironment, so
|
||||
* any parameters from that method applies
|
||||
* @returns {Promise<Widget>}
|
||||
*/
|
||||
async function createParent(params) {
|
||||
const widget = new Widget();
|
||||
await testUtilsMock.addMockEnvironment(widget, params);
|
||||
return widget;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function, make a promise with a public resolve function. Note that
|
||||
* this is not standard and should not be used outside of tests...
|
||||
@@ -99,8 +85,6 @@
|
||||
}
|
||||
|
||||
export const mock = {
|
||||
addMockEnvironment: testUtilsMock.addMockEnvironment,
|
||||
addMockEnvironmentOwl: testUtilsMock.addMockEnvironmentOwl,
|
||||
intercept: testUtilsMock.intercept,
|
||||
patch: testUtilsMock.patch,
|
||||
patchDate: testUtilsMock.patchDate,
|
||||
@@ -137,14 +121,12 @@
|
||||
fields,
|
||||
file,
|
||||
|
||||
createParent,
|
||||
makeTestPromise: makeTestPromise,
|
||||
makeTestPromiseWithAssert: makeTestPromiseWithAssert,
|
||||
nextMicrotaskTick: nextMicrotaskTick,
|
||||
nextTick: nextTick,
|
||||
|
||||
// backward-compatibility
|
||||
addMockEnvironment: deprecated(testUtilsMock.addMockEnvironment, 'mock'),
|
||||
dragAndDrop: deprecated(testUtilsDom.dragAndDrop, 'dom'),
|
||||
getView: deprecated(testUtilsMock.getView, 'mock'),
|
||||
intercept: deprecated(testUtilsMock.intercept, 'mock'),
|
||||
|
||||
@@ -9,199 +9,10 @@
|
||||
* testUtils file.
|
||||
*/
|
||||
|
||||
import AbstractStorageService from "@web/legacy/js/core/abstract_storage_service";
|
||||
import AjaxService from "@web/legacy/js/services/ajax_service";
|
||||
import Bus from "@web/legacy/js/core/bus";
|
||||
import config from "@web/legacy/js/services/config";
|
||||
import core from "@web/legacy/js/services/core";
|
||||
import dom from "@web/legacy/js/core/dom";
|
||||
import makeTestEnvironment from "@web/../tests/legacy/helpers/test_env";
|
||||
import MockServer from "@web/../tests/legacy/helpers/mock_server";
|
||||
import RamStorage from "@web/legacy/js/core/ram_storage";
|
||||
import session from "web.session";
|
||||
import { patchWithCleanup, patchDate } from "@web/../tests/helpers/utils";
|
||||
import { browser } from "@web/core/browser/browser";
|
||||
import { assets } from "@web/core/assets";
|
||||
import { patchDate } from "@web/../tests/helpers/utils";
|
||||
|
||||
import { Component } from "@odoo/owl";
|
||||
import { uniqueId } from "@web/core/utils/functions";
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private functions
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns a mocked environment to be used by OWL components in tests, with
|
||||
* requested services (+ ajax, local_storage and session_storage) deployed.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} params
|
||||
* @param {Bus} [params.bus]
|
||||
* @param {Object} [params.env]
|
||||
* @param {Bus} [params.env.bus]
|
||||
* @param {Object} [params.env.services]
|
||||
* @param {Object} [params.services]
|
||||
* @param {Object} [params.session]
|
||||
* @param {MockServer} [mockServer]
|
||||
* @returns {Promise<Object>} env
|
||||
*/
|
||||
async function _getMockedOwlEnv(params, mockServer) {
|
||||
params.env = params.env || {};
|
||||
|
||||
const database = {parameters: params.translateParameters || {}};
|
||||
|
||||
// build the env
|
||||
const services = {};
|
||||
const env = Object.assign({}, params.env, {
|
||||
_t: params.env && params.env._t || Object.assign((s => s), { database }),
|
||||
browser: Object.assign({
|
||||
fetch: (resource, init) => mockServer.performFetch(resource, init),
|
||||
}, params.env.browser),
|
||||
bus: params.bus || params.env.bus || new Bus(),
|
||||
services: Object.assign(services, params.env.services),
|
||||
session: params.env.session || params.session || {},
|
||||
});
|
||||
|
||||
// deploy services into the env
|
||||
// determine services to instantiate (classes), and already register function services
|
||||
const servicesToDeploy = {};
|
||||
for (const name in params.services || {}) {
|
||||
const Service = params.services[name];
|
||||
if (Service.constructor.name === 'Class') {
|
||||
servicesToDeploy[name] = Service;
|
||||
} else {
|
||||
services[name] = Service;
|
||||
}
|
||||
}
|
||||
// always deploy ajax, local storage and session storage
|
||||
if (!servicesToDeploy.ajax) {
|
||||
const MockedAjaxService = AjaxService.extend({
|
||||
rpc: mockServer.performRpc.bind(mockServer),
|
||||
});
|
||||
services.ajax = new MockedAjaxService(env);
|
||||
}
|
||||
const RamStorageService = AbstractStorageService.extend({
|
||||
storage: new RamStorage(),
|
||||
});
|
||||
if (!servicesToDeploy.local_storage) {
|
||||
services.local_storage = new RamStorageService(env);
|
||||
}
|
||||
if (!servicesToDeploy.session_storage) {
|
||||
services.session_storage = new RamStorageService(env);
|
||||
}
|
||||
// deploy other requested services
|
||||
let done = false;
|
||||
while (!done) {
|
||||
const serviceName = Object.keys(servicesToDeploy).find(serviceName => {
|
||||
const Service = servicesToDeploy[serviceName];
|
||||
return Service.prototype.dependencies.every(depName => {
|
||||
return env.services[depName];
|
||||
});
|
||||
});
|
||||
if (serviceName) {
|
||||
const Service = servicesToDeploy[serviceName];
|
||||
services[serviceName] = new Service(env);
|
||||
delete servicesToDeploy[serviceName];
|
||||
services[serviceName].start();
|
||||
} else {
|
||||
const serviceNames = Object.keys(servicesToDeploy);
|
||||
if (serviceNames.length) {
|
||||
console.warn("Non loaded services:", serviceNames);
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
// wait for asynchronous services to properly start
|
||||
await new Promise(setTimeout);
|
||||
|
||||
return env;
|
||||
}
|
||||
/**
|
||||
* This function is used to mock global objects (session, config...) in tests.
|
||||
* It is necessary for legacy widgets. It returns a cleanUp function to call at
|
||||
* the end of the test.
|
||||
*
|
||||
* The function could be removed as soon as we do not support legacy widgets
|
||||
* anymore.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} params
|
||||
* @param {Object} [params.config] if given, it is used to extend the global
|
||||
* config,
|
||||
* @param {Object} [params.session] if given, it is used to extend the current,
|
||||
* real session.
|
||||
* @param {Object} [params.translateParameters] if given, it will be used to
|
||||
* extend the core._t.database.parameters object.
|
||||
* @returns {function} a cleanUp function to restore everything, to call at the
|
||||
* end of the test
|
||||
*/
|
||||
function _mockGlobalObjects(params) {
|
||||
// store initial session state (for restoration)
|
||||
const initialSession = Object.assign({}, session);
|
||||
const sessionPatch = Object.assign({
|
||||
getTZOffset() { return 0; },
|
||||
async user_has_group() { return false; },
|
||||
}, params.session);
|
||||
// patch session
|
||||
Object.assign(session, sessionPatch);
|
||||
|
||||
// patch config
|
||||
let initialConfig;
|
||||
if ('config' in params) {
|
||||
initialConfig = Object.assign({}, config);
|
||||
initialConfig.device = Object.assign({}, config.device);
|
||||
if ('device' in params.config) {
|
||||
Object.assign(config.device, params.config.device);
|
||||
}
|
||||
if ('debug' in params.config) {
|
||||
odoo.debug = params.config.debug;
|
||||
}
|
||||
}
|
||||
|
||||
// patch translate params
|
||||
let initialParameters;
|
||||
if ('translateParameters' in params) {
|
||||
initialParameters = Object.assign({}, core._t.database.parameters);
|
||||
Object.assign(core._t.database.parameters, params.translateParameters);
|
||||
}
|
||||
|
||||
// build the cleanUp function to restore everything at the end of the test
|
||||
function cleanUp() {
|
||||
let key;
|
||||
for (key in sessionPatch) {
|
||||
delete session[key];
|
||||
}
|
||||
Object.assign(session, initialSession);
|
||||
if ('config' in params) {
|
||||
for (key in config) {
|
||||
delete config[key];
|
||||
}
|
||||
Object.assign(config, initialConfig);
|
||||
}
|
||||
if ('translateParameters' in params) {
|
||||
for (key in core._t.database.parameters) {
|
||||
delete core._t.database.parameters[key];
|
||||
}
|
||||
Object.assign(core._t.database.parameters, initialParameters);
|
||||
}
|
||||
}
|
||||
|
||||
return cleanUp;
|
||||
}
|
||||
/**
|
||||
* logs all event going through the target widget.
|
||||
*
|
||||
* @param {Widget} widget
|
||||
*/
|
||||
function _observe(widget) {
|
||||
var _trigger_up = widget._trigger_up.bind(widget);
|
||||
widget._trigger_up = function (event) {
|
||||
console.log('%c[event] ' + event.name, 'color: blue; font-weight: bold;', event);
|
||||
_trigger_up(event);
|
||||
};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public functions
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -230,241 +41,6 @@ function intercept(widget, eventName, fn, propagate) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a mock environment to test Owl Components. This function generates a test
|
||||
* env and sets it on the given Component. It also has several side effects,
|
||||
* like patching the global session or config objects. It returns a cleanup
|
||||
* function to call at the end of the test.
|
||||
*
|
||||
* @param {Component} Component
|
||||
* @param {Object} [params]
|
||||
* @param {Object} [params.actions]
|
||||
* @param {Object} [params.archs]
|
||||
* @param {string} [params.currentDate]
|
||||
* @param {Object} [params.data]
|
||||
* @param {boolean} [params.debug]
|
||||
* @param {function} [params.mockFetch]
|
||||
* @param {function} [params.mockRPC]
|
||||
* @param {number} [params.fieldDebounce=0] the value of the DEBOUNCE attribute
|
||||
* of fields
|
||||
* @param {boolean} [params.mockSRC=false] if true, redirect src GET requests to
|
||||
* the mockServer
|
||||
* @param {MockServer} [mockServer]
|
||||
* @returns {Promise<function>} the cleanup function
|
||||
*/
|
||||
async function addMockEnvironmentOwl(Component, params, mockServer) {
|
||||
params = params || {};
|
||||
|
||||
// instantiate a mockServer if not provided
|
||||
if (!mockServer) {
|
||||
let Server = MockServer;
|
||||
if (params.mockFetch) {
|
||||
Server = Server.extend({ _performFetch: params.mockFetch });
|
||||
}
|
||||
if (params.mockRPC) {
|
||||
Server = Server.extend({ _performRpc: params.mockRPC });
|
||||
}
|
||||
mockServer = new Server(params.data, {
|
||||
actions: params.actions,
|
||||
archs: params.archs,
|
||||
currentDate: params.currentDate,
|
||||
debug: params.debug,
|
||||
});
|
||||
}
|
||||
|
||||
patchWithCleanup(browser, {
|
||||
fetch: async (url, args) => {
|
||||
const result = await mockServer.performFetch(url, args || {});
|
||||
return {
|
||||
json: () => result,
|
||||
text: () => result,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
if (params.mockFetch) {
|
||||
const { loadJS, loadCSS } = assets;
|
||||
patchWithCleanup(assets, {
|
||||
loadJS: async function (ressource) {
|
||||
let res = await params.mockFetch(ressource, {});
|
||||
if (res === undefined) {
|
||||
res = await loadJS(ressource);
|
||||
} else {
|
||||
console.log("%c[assets] fetch (mock) JS ressource " + ressource, "color: #66e; font-weight: bold;");
|
||||
}
|
||||
return res;
|
||||
},
|
||||
loadCSS: async function (ressource) {
|
||||
let res = await params.mockFetch(ressource, {});
|
||||
if (res === undefined) {
|
||||
res = await loadCSS(ressource);
|
||||
} else {
|
||||
console.log("%c[assets] fetch (mock) CSS ressource " + ressource, "color: #66e; font-weight: bold;");
|
||||
}
|
||||
return res;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const initialDOMDebounceValue = dom.DEBOUNCE;
|
||||
dom.DEBOUNCE = 0;
|
||||
|
||||
|
||||
// mock global objects for legacy widgets (session, config...)
|
||||
const restoreMockedGlobalObjects = _mockGlobalObjects(params);
|
||||
|
||||
// set the test env on owl Component
|
||||
const env = await _getMockedOwlEnv(params, mockServer);
|
||||
const originalEnv = Component.env;
|
||||
const __env = makeTestEnvironment(env, mockServer.performRpc.bind(mockServer));
|
||||
owl.Component.env = __env;
|
||||
|
||||
// while we have a mix between Owl and legacy stuff, some of them triggering
|
||||
// events on the env.bus (a new Bus instance especially created for the current
|
||||
// test), the others using core.bus, we have to ensure that events triggered
|
||||
// on env.bus are also triggered on core.bus (note that outside the testing
|
||||
// environment, both are the exact same instance of Bus)
|
||||
const envBusTrigger = env.bus.trigger;
|
||||
env.bus.trigger = function () {
|
||||
core.bus.trigger(...arguments);
|
||||
envBusTrigger.call(env.bus, ...arguments);
|
||||
};
|
||||
|
||||
// build the clean up function to call at the end of the test
|
||||
function cleanUp() {
|
||||
env.bus.destroy();
|
||||
Object.keys(env.services).forEach(function (s) {
|
||||
var service = env.services[s] || {};
|
||||
if (service.destroy && !service.isDestroyed()) {
|
||||
service.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
dom.DEBOUNCE = initialDOMDebounceValue;
|
||||
|
||||
// clear the caches (e.g. data_manager, ModelFieldSelector) at the end
|
||||
// of each test to avoid collisions
|
||||
core.bus.trigger('clear_cache');
|
||||
|
||||
$('body').off('DOMNodeInserted.removeSRC');
|
||||
$('.blockUI').remove(); // fixme: move to qunit_config in OdooAfterTestHook?
|
||||
|
||||
restoreMockedGlobalObjects();
|
||||
|
||||
Component.env = originalEnv;
|
||||
}
|
||||
|
||||
return cleanUp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a mock environment to a widget. This helper function can simulate
|
||||
* various kind of side effects, such as mocking RPCs, changing the session,
|
||||
* or the translation settings.
|
||||
*
|
||||
* @param {Widget} widget
|
||||
* @param {Object} params
|
||||
* @param {Object} [params.archs] a map of string [model,view_id,view_type] to
|
||||
* a arch object. It is used to mock answers to 'load_views' custom events.
|
||||
* This is useful when the widget instantiate a formview dialog that needs
|
||||
* to load a particular arch.
|
||||
* @param {string} [params.currentDate] a string representation of the current
|
||||
* date. It is given to the mock server.
|
||||
* @param {Object} params.data the data given to the created mock server. It is
|
||||
* used to generate mock answers for every kind of routes supported by odoo
|
||||
* @param {number} [params.debug] if set to true, logs RPCs and uncaught Odoo
|
||||
* events.
|
||||
* @param {Object} [params.bus] the instance of Bus that will be used (in the env)
|
||||
* @param {function} [params.mockFetch] a function that will be used to override
|
||||
* the _performFetch method from the mock server. It is really useful to add
|
||||
* some custom fetch mocks, or to check some assertions.
|
||||
* @param {function} [params.mockRPC] a function that will be used to override
|
||||
* the _performRpc method from the mock server. It is really useful to add
|
||||
* some custom rpc mocks, or to check some assertions.
|
||||
* @param {Object} [params.session] if it is given, it will be used as answer
|
||||
* for all calls to this.getSession() by the widget, of its children. Also,
|
||||
* it will be used to extend the current, real session. This side effect is
|
||||
* undone when the widget is destroyed.
|
||||
* @param {Object} [params.translateParameters] if given, it will be used to
|
||||
* extend the core._t.database.parameters object. After the widget
|
||||
* destruction, the original parameters will be restored.
|
||||
* @param {Object} [params.intercepts] an object with event names as key, and
|
||||
* callback as value. Each key,value will be used to intercept the event.
|
||||
* Note that this is particularly useful if you want to intercept events going
|
||||
* up in the init process of the view, because there are no other way to do it
|
||||
* after this method returns. Some events ('call_service', "load_views",
|
||||
* "get_session", "load_filters") have a special treatment beforehand.
|
||||
* @param {Object} [params.services={}] list of services to load in
|
||||
* addition to the ajax service. For instance, if a test needs the local
|
||||
* storage service in order to work, it can provide a mock version of it.
|
||||
* @param {boolean} [debounce=true] set to false to completely remove the
|
||||
* debouncing, forcing the handler to be called directly (not on the next
|
||||
* execution stack, like it does with delay=0).
|
||||
* @param {boolean} [throttle=false] set to true to keep the throttling, which
|
||||
* is completely removed by default.
|
||||
*
|
||||
* @returns {Promise<MockServer>} the instance of the mock server, created by this
|
||||
* function. It is necessary for createView so that method can call some
|
||||
* other methods on it.
|
||||
*/
|
||||
async function addMockEnvironment(widget, params) {
|
||||
// log events triggered up if debug flag is true
|
||||
if (params.debug) {
|
||||
_observe(widget);
|
||||
var separator = window.location.href.indexOf('?') !== -1 ? "&" : "?";
|
||||
var url = window.location.href + separator + 'testId=' + QUnit.config.current.testId;
|
||||
console.log('%c[debug] debug mode activated', 'color: blue; font-weight: bold;', url);
|
||||
}
|
||||
|
||||
// instantiate mock server
|
||||
var Server = MockServer;
|
||||
if (params.mockFetch) {
|
||||
Server = MockServer.extend({ _performFetch: params.mockFetch });
|
||||
}
|
||||
if (params.mockRPC) {
|
||||
Server = Server.extend({ _performRpc: params.mockRPC });
|
||||
}
|
||||
var mockServer = new Server(params.data, {
|
||||
actions: params.actions,
|
||||
archs: params.archs,
|
||||
currentDate: params.currentDate,
|
||||
debug: params.debug,
|
||||
widget: widget,
|
||||
});
|
||||
|
||||
// build and set the Owl env on Component
|
||||
if (!('mockSRC' in params)) { // redirect src rpcs to the mock server
|
||||
params.mockSRC = true;
|
||||
}
|
||||
const cleanUp = await addMockEnvironmentOwl(Component, params, mockServer);
|
||||
const env = Component.env;
|
||||
|
||||
// ensure to clean up everything when the widget will be destroyed
|
||||
const destroy = widget.destroy;
|
||||
widget.destroy = function () {
|
||||
cleanUp();
|
||||
destroy.call(this, ...arguments);
|
||||
};
|
||||
|
||||
// intercept service/data manager calls and redirect them to the env
|
||||
intercept(widget, 'call_service', function (ev) {
|
||||
if (env.services[ev.data.service]) {
|
||||
var service = env.services[ev.data.service];
|
||||
const result = service[ev.data.method].apply(service, ev.data.args || []);
|
||||
ev.data.callback(result);
|
||||
}
|
||||
});
|
||||
intercept(widget, "get_session", ev => {
|
||||
ev.data.callback(session);
|
||||
});
|
||||
// make sure all other Odoo events bubbling up are intercepted
|
||||
Object.keys(params.intercepts || {}).forEach(function (name) {
|
||||
intercept(widget, name, params.intercepts[name]);
|
||||
});
|
||||
|
||||
return mockServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch window.Date so that the time starts its flow from the provided Date.
|
||||
*
|
||||
@@ -580,8 +156,6 @@ function unpatch(target) {
|
||||
}
|
||||
|
||||
export default {
|
||||
addMockEnvironment: addMockEnvironment,
|
||||
addMockEnvironmentOwl: addMockEnvironmentOwl,
|
||||
intercept: intercept,
|
||||
patchDate: legacyPatchDate,
|
||||
patch: patch,
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import MockServer from '@web/../tests/legacy/helpers/mock_server';
|
||||
|
||||
QUnit.module('web', {}, function () {
|
||||
QUnit.module('legacy', {}, function () {
|
||||
QUnit.module('mock_relational_fields_tests.js', {
|
||||
beforeEach() {
|
||||
this.data = {
|
||||
foo: {
|
||||
fields: {
|
||||
one2many_field: { type: 'one2many', relation: 'bar', inverse_fname_by_model_name: { bar: 'many2one_field' } },
|
||||
many2one_field: { type: 'many2one', relation: 'bar', inverse_fname_by_model_name: { bar: 'one2many_field' } },
|
||||
many2many_field: { type: 'many2many', relation: 'bar', inverse_fname_by_model_name: { bar: 'many2many_field' } },
|
||||
many2one_reference: { type: 'many2one_reference', model_name_ref_fname: 'res_model', inverse_fname_by_model_name: { bar: 'one2many_field' } },
|
||||
res_model: { type: 'char' },
|
||||
|
||||
},
|
||||
records: [],
|
||||
},
|
||||
bar: {
|
||||
fields: {
|
||||
many2one_field: { type: 'many2one', relation: 'foo' },
|
||||
one2many_field: { type: 'one2many', relation: 'foo', inverse_fname_by_model_name: { foo: 'many2one_field' } },
|
||||
many2many_field: { type: 'many2many', relation: 'foo', inverse_fname_by_model_name: { foo: 'many2many_field' } },
|
||||
},
|
||||
records: [],
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
QUnit.test('many2one_ref should auto fill inverse field', async function (assert) {
|
||||
this.data['bar'].records.push({ id: 1 });
|
||||
this.data['foo'].records.push({
|
||||
id: 2,
|
||||
res_model: 'bar',
|
||||
many2one_reference: 1,
|
||||
});
|
||||
const mockServer = new MockServer(this.data, {});
|
||||
assert.deepEqual([2], mockServer.data['bar'].records[0].one2many_field);
|
||||
|
||||
mockServer._mockUnlink('foo', [2]);
|
||||
assert.deepEqual([], mockServer.data['bar'].records[0].one2many_field);
|
||||
});
|
||||
|
||||
QUnit.test('many2one should auto fill inverse field', async function (assert) {
|
||||
this.data['bar'].records.push({ id: 1 });
|
||||
this.data['foo'].records.push({
|
||||
id: 2,
|
||||
many2one_field: 1,
|
||||
});
|
||||
const mockServer = new MockServer(this.data, {});
|
||||
assert.deepEqual([2], mockServer.data['bar'].records[0].one2many_field);
|
||||
|
||||
mockServer._mockUnlink('foo', [2]);
|
||||
assert.deepEqual([], mockServer.data['bar'].records[0].one2many_field);
|
||||
});
|
||||
|
||||
QUnit.test('one2many should auto fill inverse field', async function (assert) {
|
||||
this.data['bar'].records.push({ id: 1 });
|
||||
this.data['bar'].records.push({ id: 2 });
|
||||
this.data['foo'].records.push({
|
||||
id: 3,
|
||||
one2many_field: [1, 2],
|
||||
});
|
||||
const mockServer = new MockServer(this.data, {});
|
||||
assert.strictEqual(3, mockServer.data['bar'].records[0].many2one_field);
|
||||
assert.strictEqual(3, mockServer.data['bar'].records[1].many2one_field);
|
||||
|
||||
mockServer._mockUnlink('foo', [3]);
|
||||
assert.strictEqual(false, mockServer.data['bar'].records[0].many2one_field);
|
||||
assert.strictEqual(false, mockServer.data['bar'].records[1].many2one_field);
|
||||
});
|
||||
|
||||
QUnit.test('many2many should auto fill inverse field', async function (assert) {
|
||||
this.data['bar'].records.push({ id: 1 });
|
||||
this.data['foo'].records.push({
|
||||
id: 2,
|
||||
many2many_field: [1],
|
||||
});
|
||||
const mockServer = new MockServer(this.data, {});
|
||||
assert.deepEqual([2], mockServer.data['bar'].records[0].many2many_field);
|
||||
|
||||
mockServer._mockUnlink('foo', [2]);
|
||||
assert.deepEqual([], mockServer.data['bar'].records[0].many2many_field);
|
||||
});
|
||||
|
||||
QUnit.test('one2many update should update inverse field', async function (assert) {
|
||||
this.data['bar'].records.push({ id: 1 });
|
||||
this.data['bar'].records.push({ id: 2 });
|
||||
this.data['foo'].records.push({
|
||||
id: 3,
|
||||
one2many_field: [1, 2],
|
||||
});
|
||||
const mockServer = new MockServer(this.data, {});
|
||||
mockServer._mockWrite('foo', [[3], { one2many_field: [1] }]);
|
||||
assert.strictEqual(3, mockServer.data['bar'].records[0].many2one_field);
|
||||
assert.strictEqual(false, mockServer.data['bar'].records[1].many2one_field);
|
||||
});
|
||||
|
||||
QUnit.test('many2many update should update inverse field', async function (assert) {
|
||||
this.data['bar'].records.push({ id: 1 });
|
||||
this.data['foo'].records.push({
|
||||
id: 2,
|
||||
many2many_field: [1],
|
||||
});
|
||||
const mockServer = new MockServer(this.data, {});
|
||||
mockServer._mockWrite('foo', [[2], { many2many_field: [] }]);
|
||||
assert.deepEqual([], mockServer.data['bar'].records[0].many2many_field);
|
||||
});
|
||||
|
||||
QUnit.test('many2one update should update inverse field', async function (assert) {
|
||||
this.data['bar'].records.push({ id: 1 });
|
||||
this.data['foo'].records.push({
|
||||
id: 2,
|
||||
many2one_field: 1,
|
||||
});
|
||||
const mockServer = new MockServer(this.data, {});
|
||||
mockServer._mockWrite('foo', [[2], { many2one_field: false }]);
|
||||
assert.deepEqual([], mockServer.data['bar'].records[0].one2many_field);
|
||||
});
|
||||
|
||||
QUnit.test('many2one_ref update should update inverse field', async function (assert) {
|
||||
this.data['bar'].records.push({ id: 1 });
|
||||
this.data['foo'].records.push({
|
||||
id: 2,
|
||||
res_model: 'bar',
|
||||
many2one_reference: 1,
|
||||
});
|
||||
const mockServer = new MockServer(this.data, {});
|
||||
mockServer._mockWrite('foo', [[2], { many2one_reference: false }]);
|
||||
assert.deepEqual([], mockServer.data['bar'].records[0].one2many_field);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
@@ -1,465 +0,0 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import MockServer from "@web/../tests/legacy/helpers/mock_server";
|
||||
|
||||
QUnit.module("Legacy MockServer", {
|
||||
beforeEach() {
|
||||
this.data = {
|
||||
"res.partner": {
|
||||
fields: {
|
||||
name: {
|
||||
string: "Name",
|
||||
type: "string",
|
||||
},
|
||||
email: {
|
||||
string: "Email",
|
||||
type: "string",
|
||||
},
|
||||
active: {
|
||||
string: "Active",
|
||||
type: "bool",
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
records: [
|
||||
{ id: 1, name: "Jean-Michel", email: "jean.michel@example.com" },
|
||||
{ id: 2, name: "Raoul", email: "raoul@example.com", active: false },
|
||||
],
|
||||
},
|
||||
bar: {
|
||||
fields: {
|
||||
foo: {
|
||||
string: "Foo",
|
||||
type: "integer",
|
||||
searchable: true,
|
||||
group_operator: "sum",
|
||||
},
|
||||
date: { string: "Date", type: "date", store: true, sortable: true },
|
||||
datetime: {
|
||||
string: "DateTime",
|
||||
type: "datetime",
|
||||
store: true,
|
||||
sortable: true,
|
||||
},
|
||||
partners: { string: "Buddies", type: "many2many", relation: "res.partner" },
|
||||
},
|
||||
records: [
|
||||
{
|
||||
id: 1,
|
||||
foo: 12,
|
||||
date: "2016-12-14",
|
||||
datetime: "2016-12-14 12:34:56",
|
||||
partners: [1, 2],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
foo: 1,
|
||||
date: "2016-10-26",
|
||||
datetime: "2016-10-26 12:34:56",
|
||||
partners: [1],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
foo: 17,
|
||||
date: "2016-12-15",
|
||||
datetime: "2016-12-15 12:34:56",
|
||||
partners: [2],
|
||||
},
|
||||
{ id: 4, foo: 2, date: "2016-04-11", datetime: "2016-04-11 12:34:56" },
|
||||
{ id: 5, foo: 0, date: "2016-12-15", datetime: "2016-12-15 12:34:56" },
|
||||
{ id: 6, foo: 42, date: "2019-12-30", datetime: "2019-12-30 12:34:56" },
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
}, function () {
|
||||
QUnit.test("performRpc: search_read with an empty array of fields", async function (assert) {
|
||||
assert.expect(1);
|
||||
const server = new MockServer(this.data, {});
|
||||
const result = await server.performRpc("", {
|
||||
model: "res.partner",
|
||||
method: "search_read",
|
||||
args: [],
|
||||
kwargs: {
|
||||
fields: [],
|
||||
},
|
||||
});
|
||||
const expectedFields = ["id", "email", "name", "display_name"];
|
||||
assert.strictEqual(
|
||||
expectedFields.filter((x) => Object.keys(result[0]).indexOf(x) < 0).length,
|
||||
0,
|
||||
"should contains all the fields"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("performRpc: search_read without fields", async function (assert) {
|
||||
assert.expect(1);
|
||||
const server = new MockServer(this.data, {});
|
||||
const result = await server.performRpc("", {
|
||||
model: "res.partner",
|
||||
method: "search_read",
|
||||
args: [],
|
||||
kwargs: {},
|
||||
});
|
||||
const expectedFields = ["id", "email", "name", "display_name"];
|
||||
assert.strictEqual(
|
||||
expectedFields.filter((x) => Object.keys(result[0]).indexOf(x) < 0).length,
|
||||
0,
|
||||
"should contains all the fields"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("performRpc: search with active_test=false", async function (assert) {
|
||||
assert.expect(1);
|
||||
const server = new MockServer(this.data, {});
|
||||
const result = await server.performRpc("", {
|
||||
model: "res.partner",
|
||||
method: "search",
|
||||
args: [[]],
|
||||
kwargs: {
|
||||
context: { active_test: false },
|
||||
},
|
||||
});
|
||||
assert.deepEqual(result, [1, 2]);
|
||||
});
|
||||
|
||||
QUnit.test("performRpc: search with active_test=true", async function (assert) {
|
||||
assert.expect(1);
|
||||
const server = new MockServer(this.data, {});
|
||||
const result = await server.performRpc("", {
|
||||
model: "res.partner",
|
||||
method: "search",
|
||||
args: [[]],
|
||||
kwargs: {
|
||||
context: { active_test: true },
|
||||
},
|
||||
});
|
||||
assert.deepEqual(result, [1]);
|
||||
});
|
||||
|
||||
QUnit.test("performRpc: search_read with active_test=false", async function (assert) {
|
||||
assert.expect(1);
|
||||
const server = new MockServer(this.data, {});
|
||||
const result = await server.performRpc("", {
|
||||
model: "res.partner",
|
||||
method: "search_read",
|
||||
args: [[]],
|
||||
kwargs: {
|
||||
fields: ["name"],
|
||||
context: { active_test: false },
|
||||
},
|
||||
});
|
||||
assert.deepEqual(result, [{id: 1, name: "Jean-Michel"}, {id: 2, name: "Raoul"}]);
|
||||
});
|
||||
|
||||
QUnit.test("performRpc: search_read with active_test=true", async function (assert) {
|
||||
assert.expect(1);
|
||||
const server = new MockServer(this.data, {});
|
||||
const result = await server.performRpc("", {
|
||||
model: "res.partner",
|
||||
method: "search_read",
|
||||
args: [[]],
|
||||
kwargs: {
|
||||
fields: ["name"],
|
||||
context: { active_test: true },
|
||||
},
|
||||
});
|
||||
assert.deepEqual(result, [{id: 1, name: "Jean-Michel"}]);
|
||||
});
|
||||
|
||||
QUnit.test("performRpc: read_group, group by date", async function (assert) {
|
||||
assert.expect(10);
|
||||
const server = new MockServer(this.data, {});
|
||||
let result = await server.performRpc("", {
|
||||
model: "bar",
|
||||
method: "read_group",
|
||||
args: [[]],
|
||||
kwargs: {
|
||||
fields: ["foo"],
|
||||
domain: [],
|
||||
groupby: ["date"], //Month by default
|
||||
},
|
||||
});
|
||||
assert.deepEqual(
|
||||
result.map((x) => x.date),
|
||||
["December 2016", "October 2016", "April 2016", "December 2019"]
|
||||
);
|
||||
assert.deepEqual(
|
||||
result.map((x) => x.date_count),
|
||||
[3, 1, 1, 1]
|
||||
);
|
||||
|
||||
result = await server.performRpc("", {
|
||||
model: "bar",
|
||||
method: "read_group",
|
||||
args: [[]],
|
||||
kwargs: {
|
||||
fields: ["foo"],
|
||||
domain: [],
|
||||
groupby: ["date:day"],
|
||||
},
|
||||
});
|
||||
assert.deepEqual(
|
||||
result.map((x) => x["date:day"]),
|
||||
["2016-12-14", "2016-10-26", "2016-12-15", "2016-04-11", "2019-12-30"]
|
||||
);
|
||||
assert.deepEqual(
|
||||
result.map((x) => x.date_count),
|
||||
[1, 1, 2, 1, 1]
|
||||
);
|
||||
|
||||
result = await server.performRpc("", {
|
||||
model: "bar",
|
||||
method: "read_group",
|
||||
args: [[]],
|
||||
kwargs: {
|
||||
fields: ["foo"],
|
||||
domain: [],
|
||||
groupby: ["date:week"],
|
||||
},
|
||||
});
|
||||
assert.deepEqual(
|
||||
result.map((x) => x["date:week"]),
|
||||
["W50 2016", "W43 2016", "W15 2016", "W01 2020"]
|
||||
);
|
||||
assert.deepEqual(
|
||||
result.map((x) => x.date_count),
|
||||
[3, 1, 1, 1]
|
||||
);
|
||||
|
||||
result = await server.performRpc("", {
|
||||
model: "bar",
|
||||
method: "read_group",
|
||||
args: [[]],
|
||||
kwargs: {
|
||||
fields: ["foo"],
|
||||
domain: [],
|
||||
groupby: ["date:quarter"],
|
||||
},
|
||||
});
|
||||
assert.deepEqual(
|
||||
result.map((x) => x["date:quarter"]),
|
||||
["Q4 2016", "Q2 2016", "Q4 2019"]
|
||||
);
|
||||
assert.deepEqual(
|
||||
result.map((x) => x.date_count),
|
||||
[4, 1, 1]
|
||||
);
|
||||
|
||||
result = await server.performRpc("", {
|
||||
model: "bar",
|
||||
method: "read_group",
|
||||
args: [[]],
|
||||
kwargs: {
|
||||
fields: ["foo"],
|
||||
domain: [],
|
||||
groupby: ["date:year"],
|
||||
},
|
||||
});
|
||||
assert.deepEqual(
|
||||
result.map((x) => x["date:year"]),
|
||||
["2016", "2019"]
|
||||
);
|
||||
assert.deepEqual(
|
||||
result.map((x) => x.date_count),
|
||||
[5, 1]
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("performRpc: read_group, group by datetime", async function (assert) {
|
||||
const server = new MockServer(this.data, {});
|
||||
let result = await server.performRpc("", {
|
||||
model: "bar",
|
||||
method: "read_group",
|
||||
args: [[]],
|
||||
kwargs: {
|
||||
fields: ["foo"],
|
||||
domain: [],
|
||||
groupby: ["datetime"], //Month by default
|
||||
},
|
||||
});
|
||||
assert.deepEqual(
|
||||
result.map((x) => x.datetime),
|
||||
["December 2016", "October 2016", "April 2016", "December 2019"]
|
||||
);
|
||||
assert.deepEqual(
|
||||
result.map((x) => x.datetime_count),
|
||||
[3, 1, 1, 1]
|
||||
);
|
||||
|
||||
result = await server.performRpc("", {
|
||||
model: "bar",
|
||||
method: "read_group",
|
||||
args: [[]],
|
||||
kwargs: {
|
||||
fields: ["foo"],
|
||||
domain: [],
|
||||
groupby: ["datetime:hour"],
|
||||
},
|
||||
});
|
||||
assert.deepEqual(
|
||||
result.map((x) => x["datetime:hour"]),
|
||||
["13:00 14 Dec", "13:00 26 Oct", "13:00 15 Dec", "13:00 11 Apr", "13:00 30 Dec"]
|
||||
);
|
||||
assert.deepEqual(
|
||||
result.map((x) => x.datetime_count),
|
||||
[1, 1, 2, 1, 1]
|
||||
);
|
||||
|
||||
result = await server.performRpc("", {
|
||||
model: "bar",
|
||||
method: "read_group",
|
||||
args: [[]],
|
||||
kwargs: {
|
||||
fields: ["foo"],
|
||||
domain: [],
|
||||
groupby: ["datetime:day"],
|
||||
},
|
||||
});
|
||||
assert.deepEqual(
|
||||
result.map((x) => x["datetime:day"]),
|
||||
["2016-12-14", "2016-10-26", "2016-12-15", "2016-04-11", "2019-12-30"]
|
||||
);
|
||||
assert.deepEqual(
|
||||
result.map((x) => x.datetime_count),
|
||||
[1, 1, 2, 1, 1]
|
||||
);
|
||||
|
||||
result = await server.performRpc("", {
|
||||
model: "bar",
|
||||
method: "read_group",
|
||||
args: [[]],
|
||||
kwargs: {
|
||||
fields: ["foo"],
|
||||
domain: [],
|
||||
groupby: ["datetime:week"],
|
||||
},
|
||||
});
|
||||
assert.deepEqual(
|
||||
result.map((x) => x["datetime:week"]),
|
||||
["W50 2016", "W43 2016", "W15 2016", "W01 2020"]
|
||||
);
|
||||
assert.deepEqual(
|
||||
result.map((x) => x.datetime_count),
|
||||
[3, 1, 1, 1]
|
||||
);
|
||||
|
||||
result = await server.performRpc("", {
|
||||
model: "bar",
|
||||
method: "read_group",
|
||||
args: [[]],
|
||||
kwargs: {
|
||||
fields: ["foo"],
|
||||
domain: [],
|
||||
groupby: ["datetime:quarter"],
|
||||
},
|
||||
});
|
||||
assert.deepEqual(
|
||||
result.map((x) => x["datetime:quarter"]),
|
||||
["Q4 2016", "Q2 2016", "Q4 2019"]
|
||||
);
|
||||
assert.deepEqual(
|
||||
result.map((x) => x.datetime_count),
|
||||
[4, 1, 1]
|
||||
);
|
||||
|
||||
result = await server.performRpc("", {
|
||||
model: "bar",
|
||||
method: "read_group",
|
||||
args: [[]],
|
||||
kwargs: {
|
||||
fields: ["foo"],
|
||||
domain: [],
|
||||
groupby: ["datetime:year"],
|
||||
},
|
||||
});
|
||||
assert.deepEqual(
|
||||
result.map((x) => x["datetime:year"]),
|
||||
["2016", "2019"]
|
||||
);
|
||||
assert.deepEqual(
|
||||
result.map((x) => x.datetime_count),
|
||||
[5, 1]
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("performRpc: read_group, group by m2m", async function (assert) {
|
||||
const server = new MockServer(this.data, {});
|
||||
const result = await server.performRpc("", {
|
||||
model: "bar",
|
||||
method: "read_group",
|
||||
args: [[]],
|
||||
kwargs: {
|
||||
fields: ["partners"],
|
||||
domain: [],
|
||||
groupby: ["partners"],
|
||||
},
|
||||
});
|
||||
assert.deepEqual(
|
||||
result,
|
||||
[
|
||||
{
|
||||
__domain: [["partners", "=", 1]],
|
||||
partners: [1, "Jean-Michel"],
|
||||
partners_count: 2,
|
||||
},
|
||||
{
|
||||
__domain: [["partners", "=", 2]],
|
||||
partners: [2, "Raoul"],
|
||||
partners_count: 2,
|
||||
},
|
||||
{
|
||||
__domain: [["partners", "=", false]],
|
||||
partners: false,
|
||||
partners_count: 3,
|
||||
},
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("performRpc: read_group, group by integer", async function (assert) {
|
||||
const server = new MockServer(this.data, {});
|
||||
const result = await server.performRpc("", {
|
||||
model: "bar",
|
||||
method: "read_group",
|
||||
args: [[]],
|
||||
kwargs: {
|
||||
fields: ["foo"],
|
||||
domain: [],
|
||||
groupby: ["foo"],
|
||||
},
|
||||
});
|
||||
assert.deepEqual(result, [
|
||||
{
|
||||
__domain: [["foo", "=", 12]],
|
||||
foo: 12,
|
||||
foo_count: 1,
|
||||
},
|
||||
{
|
||||
__domain: [["foo", "=", 1]],
|
||||
foo: 1,
|
||||
foo_count: 1,
|
||||
},
|
||||
{
|
||||
__domain: [["foo", "=", 17]],
|
||||
foo: 17,
|
||||
foo_count: 1,
|
||||
},
|
||||
{
|
||||
__domain: [["foo", "=", 2]],
|
||||
foo: 2,
|
||||
foo_count: 1,
|
||||
},
|
||||
{
|
||||
__domain: [["foo", "=", 0]],
|
||||
foo: 0,
|
||||
foo_count: 1,
|
||||
},
|
||||
{
|
||||
__domain: [["foo", "=", 42]],
|
||||
foo: 42,
|
||||
foo_count: 1,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
const makeTestPromise = testUtils.makeTestPromise;
|
||||
const nextTick = testUtils.nextTick;
|
||||
const addMockEnvironmentOwl = testUtils.mock.addMockEnvironmentOwl;
|
||||
|
||||
const {
|
||||
Component,
|
||||
@@ -426,40 +425,6 @@
|
||||
assert.verifySteps(['a', 'b']);
|
||||
});
|
||||
|
||||
QUnit.test("sub widget that calls _rpc", async function (assert) {
|
||||
assert.expect(3);
|
||||
|
||||
const MyWidget = Widget.extend({
|
||||
willStart: function () {
|
||||
return this._rpc({ route: 'some/route', params: { val: 2 } });
|
||||
},
|
||||
});
|
||||
class Parent extends LegacyComponent {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.MyWidget = MyWidget;
|
||||
}
|
||||
}
|
||||
Parent.template = xml`
|
||||
<div>
|
||||
<ComponentAdapter Component="MyWidget"/>
|
||||
</div>`;
|
||||
Parent.components = { ComponentAdapter };
|
||||
const cleanUp = await addMockEnvironmentOwl(Parent, {
|
||||
mockRPC: function (route, args) {
|
||||
assert.step(`${route} ${args.val}`);
|
||||
return Promise.resolve();
|
||||
},
|
||||
});
|
||||
|
||||
const target = getFixture();
|
||||
const parent = await mount(Parent, target, { env: owl.Component.env });
|
||||
|
||||
assert.strictEqual(parent.el.innerHTML, '<div></div>');
|
||||
assert.verifySteps(['some/route 2']);
|
||||
cleanUp();
|
||||
});
|
||||
|
||||
QUnit.test("sub widget that calls a service", async function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
@@ -501,34 +466,6 @@
|
||||
await mount(Parent, target, { env });
|
||||
});
|
||||
|
||||
QUnit.test("sub widget that requests the session", async function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
const MyWidget = Widget.extend({
|
||||
start: function () {
|
||||
assert.strictEqual(this.getSession().key, 'value');
|
||||
},
|
||||
});
|
||||
class Parent extends LegacyComponent {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.MyWidget = MyWidget;
|
||||
}
|
||||
}
|
||||
Parent.template = xml`
|
||||
<div>
|
||||
<ComponentAdapter Component="MyWidget"/>
|
||||
</div>`;
|
||||
Parent.components = { ComponentAdapter };
|
||||
const cleanUp = await addMockEnvironmentOwl(Parent, {
|
||||
session: { key: 'value' },
|
||||
});
|
||||
|
||||
const target = getFixture();
|
||||
await mount(Parent, target, { env: owl.Component.env });
|
||||
cleanUp();
|
||||
});
|
||||
|
||||
QUnit.test("sub widgets in a t-if/t-else", async function (assert) {
|
||||
assert.expect(3);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { NameAndSignature } from "@web/legacy/js/widgets/name_and_signature";
|
||||
import testUtils from "@web/../tests/legacy/helpers/test_utils";
|
||||
|
||||
const MockedNameAndSignature = NameAndSignature.extend({
|
||||
events: {
|
||||
...NameAndSignature.prototype.events,
|
||||
@@ -14,10 +15,10 @@
|
||||
async function MockedNameAndSignatureGenerator (options) {
|
||||
const parent = $("#qunit-fixture");
|
||||
const mockedNameAndSignature = new MockedNameAndSignature(parent, options);
|
||||
await testUtils.mock.addMockEnvironment(mockedNameAndSignature, {
|
||||
mockRPC: function (route, args) {
|
||||
if (route == "/web/sign/get_fonts/") {
|
||||
return Promise.resolve();
|
||||
testUtils.mock.intercept(mockedNameAndSignature, 'call_service', function ({ data }) {
|
||||
if (data.service === "ajax" && data.method === "rpc") {
|
||||
if (data.args[0] === "/web/sign/get_fonts/") {
|
||||
data.callback(Promise.resolve());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -4242,7 +4242,6 @@ QUnit.module("Fields", (hooks) => {
|
||||
};
|
||||
const webClient = await createWebClient({
|
||||
serverData,
|
||||
legacyParams: { withLegacyMockServer: true },
|
||||
mockRPC: function (route, args) {
|
||||
if (args.method === "get_formview_action") {
|
||||
assert.step("get_formview_action");
|
||||
|
||||
@@ -10443,10 +10443,6 @@ QUnit.module("Fields", (hooks) => {
|
||||
mockRPC(route, args) {
|
||||
assert.step(args.method);
|
||||
},
|
||||
// we set a fieldDebounce to precisely mock the behavior of the webclient: changes are
|
||||
// not sent to the model at keystrokes, but when the input is left
|
||||
|
||||
// legacyParams: { fieldDebounce: 5000 }, // WOWL keep this in view API?
|
||||
});
|
||||
|
||||
await addRow(target);
|
||||
|
||||
@@ -17,7 +17,6 @@ import {
|
||||
setupControlPanelFavoriteMenuRegistry,
|
||||
setupControlPanelServiceRegistry,
|
||||
} from "../search/helpers";
|
||||
import { addLegacyMockEnvironment } from "../webclient/helpers";
|
||||
|
||||
import { Component, useSubEnv, xml } from "@odoo/owl";
|
||||
|
||||
@@ -52,11 +51,9 @@ async function _makeView(params, inDialog = false) {
|
||||
...getDefaultConfig(),
|
||||
...props.config,
|
||||
};
|
||||
const legacyParams = props.legacyParams || {};
|
||||
|
||||
delete props.serverData;
|
||||
delete props.mockRPC;
|
||||
delete props.legacyParams;
|
||||
delete props.config;
|
||||
|
||||
if (props.arch) {
|
||||
@@ -73,22 +70,6 @@ async function _makeView(params, inDialog = false) {
|
||||
const env = await makeTestEnv({ serverData, mockRPC });
|
||||
Object.assign(env, createDebugContext(env)); // This is needed if the views are in debug mode
|
||||
|
||||
/** Legacy Environment, for compatibility sakes
|
||||
* Remove this as soon as we drop the legacy support
|
||||
*/
|
||||
const models = params.serverData.models;
|
||||
if (legacyParams && legacyParams.withLegacyMockServer && models) {
|
||||
legacyParams.models = Object.assign({}, 0);
|
||||
// In lagacy, data may not be sole models, but can contain some other variables
|
||||
// So we filter them out for our WOWL mockServer
|
||||
Object.entries(legacyParams.models).forEach(([k, v]) => {
|
||||
if (!(v instanceof Object) || !("fields" in v)) {
|
||||
delete models[k];
|
||||
}
|
||||
});
|
||||
}
|
||||
await addLegacyMockEnvironment(env, legacyParams);
|
||||
|
||||
const target = getFixture();
|
||||
const viewEnv = Object.assign(Object.create(env), { config });
|
||||
|
||||
|
||||
@@ -6,21 +6,12 @@ import { ormService } from "@web/core/orm_service";
|
||||
import { popoverService } from "@web/core/popover/popover_service";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { legacyServiceProvider } from "@web/legacy/legacy_service_provider";
|
||||
import {
|
||||
makeLegacyNotificationService,
|
||||
mapLegacyEnvToWowlEnv,
|
||||
makeLegacySessionService,
|
||||
} from "@web/legacy/utils";
|
||||
import { makeLegacyActionManagerService } from "@web/legacy/backend_utils";
|
||||
import { viewService } from "@web/views/view_service";
|
||||
import { actionService } from "@web/webclient/actions/action_service";
|
||||
import { effectService } from "@web/core/effects/effect_service";
|
||||
import { hotkeyService } from "@web/core/hotkeys/hotkey_service";
|
||||
import { menuService } from "@web/webclient/menus/menu_service";
|
||||
import { WebClient } from "@web/webclient/webclient";
|
||||
import AbstractService from "@web/legacy/js/core/abstract_service";
|
||||
import core from "@web/legacy/js/services/core";
|
||||
import makeTestEnvironment from "@web/../tests/legacy/helpers/test_env";
|
||||
import { registerCleanup } from "../helpers/cleanup";
|
||||
import { makeTestEnv } from "../helpers/mock_env";
|
||||
import {
|
||||
@@ -31,15 +22,10 @@ import {
|
||||
makeFakeHTTPService,
|
||||
makeFakeUserService,
|
||||
} from "../helpers/mock_services";
|
||||
import { getFixture, mount, nextTick, patchWithCleanup } from "../helpers/utils";
|
||||
import session from "web.session";
|
||||
import LegacyMockServer from "@web/../tests/legacy/helpers/mock_server";
|
||||
import Widget from "@web/legacy/js/core/widget";
|
||||
import { getFixture, mount, nextTick } from "../helpers/utils";
|
||||
import { uiService } from "@web/core/ui/ui_service";
|
||||
import { commandService } from "@web/core/commands/command_service";
|
||||
import { ConnectionAbortedError } from "@web/core/network/rpc_service";
|
||||
import { CustomFavoriteItem } from "@web/search/custom_favorite_item/custom_favorite_item";
|
||||
import { standaloneAdapter } from "@web/legacy/js/owl_compatibility";
|
||||
import { overlayService } from "@web/core/overlay/overlay_service";
|
||||
|
||||
import { Component, xml } from "@odoo/owl";
|
||||
@@ -99,87 +85,6 @@ export function setupWebClientRegistries() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove this as soon as we drop the legacy support
|
||||
*/
|
||||
export async function addLegacyMockEnvironment(env, legacyParams = {}) {
|
||||
// setup a legacy env
|
||||
let localSession;
|
||||
if (legacyParams && legacyParams.getTZOffset) {
|
||||
patchWithCleanup(session, {
|
||||
getTZOffset: legacyParams.getTZOffset,
|
||||
});
|
||||
localSession = { getTZOffset: legacyParams.getTZOffset };
|
||||
}
|
||||
|
||||
const baseEnv = { bus: core.bus, session: localSession };
|
||||
const legacyEnv = makeTestEnvironment(Object.assign(baseEnv, legacyParams.env));
|
||||
|
||||
if (legacyParams.serviceRegistry) {
|
||||
const legacyServiceMap = core.serviceRegistry.map;
|
||||
core.serviceRegistry.map = legacyParams.serviceRegistry.map;
|
||||
// notification isn't a deployed service, but it is added by `makeTestEnvironment`.
|
||||
// Here, we want full control on the deployed services, so we simply remove it.
|
||||
delete legacyEnv.services.notification;
|
||||
AbstractService.prototype.deployServices(legacyEnv);
|
||||
registerCleanup(() => {
|
||||
core.serviceRegistry.map = legacyServiceMap;
|
||||
});
|
||||
}
|
||||
|
||||
Component.env = legacyEnv;
|
||||
mapLegacyEnvToWowlEnv(legacyEnv, env);
|
||||
function patchLegacySession() {
|
||||
const userContext = Object.getOwnPropertyDescriptor(session, "user_context");
|
||||
registerCleanup(() => {
|
||||
Object.defineProperty(session, "user_context", userContext);
|
||||
});
|
||||
}
|
||||
patchLegacySession();
|
||||
serviceRegistry.add("legacy_session", makeLegacySessionService(legacyEnv, session));
|
||||
// deploy the legacyActionManagerService (in Wowl env)
|
||||
const legacyActionManagerService = makeLegacyActionManagerService(legacyEnv);
|
||||
serviceRegistry.add("legacy_action_manager", legacyActionManagerService);
|
||||
serviceRegistry.add("legacy_notification", makeLegacyNotificationService(legacyEnv));
|
||||
// deploy wowl services into the legacy env.
|
||||
const wowlToLegacyServiceMappers = registry.category("wowlToLegacyServiceMappers").getEntries();
|
||||
for (const [legacyServiceName, wowlToLegacyServiceMapper] of wowlToLegacyServiceMappers) {
|
||||
serviceRegistry.add(legacyServiceName, wowlToLegacyServiceMapper(legacyEnv));
|
||||
}
|
||||
|
||||
if (legacyParams.withLegacyMockServer) {
|
||||
const adapter = standaloneAdapter({ Component });
|
||||
registerCleanup(() => adapter.__owl__.app.destroy());
|
||||
adapter.env = legacyEnv;
|
||||
const W = Widget.extend({ do_push_state() {} });
|
||||
const widget = new W(adapter);
|
||||
const legacyMockServer = new LegacyMockServer(legacyParams.models, { widget });
|
||||
const originalRPC = env.services.rpc;
|
||||
const rpc = async (...args) => {
|
||||
try {
|
||||
return await originalRPC(...args);
|
||||
} catch (e) {
|
||||
if (e.message.includes("Unimplemented")) {
|
||||
return legacyMockServer._performRpc(...args);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
};
|
||||
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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method create a web client instance properly configured.
|
||||
*
|
||||
@@ -191,26 +96,12 @@ export async function addLegacyMockEnvironment(env, legacyParams = {}) {
|
||||
export async function createWebClient(params) {
|
||||
setupWebClientRegistries();
|
||||
|
||||
const legacyParams = params.legacyParams;
|
||||
params.serverData = params.serverData || {};
|
||||
const models = params.serverData.models;
|
||||
if (legacyParams && legacyParams.withLegacyMockServer && models) {
|
||||
legacyParams.models = Object.assign({}, models);
|
||||
// In lagacy, data may not be sole models, but can contain some other variables
|
||||
// So we filter them out for our WOWL mockServer
|
||||
Object.entries(legacyParams.models).forEach(([k, v]) => {
|
||||
if (!(v instanceof Object) || !("fields" in v)) {
|
||||
delete models[k];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const mockRPC = params.mockRPC || undefined;
|
||||
const env = await makeTestEnv({
|
||||
serverData: params.serverData,
|
||||
mockRPC,
|
||||
});
|
||||
await addLegacyMockEnvironment(env, legacyParams);
|
||||
|
||||
const WebClientClass = params.WebClientClass || WebClient;
|
||||
const target = params && params.target ? params.target : getFixture();
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import ajax from "@web/legacy/js/core/ajax";
|
||||
import { MockServer } from "@web/../tests/helpers/mock_server";
|
||||
import MockServerLegacy from "@web/../tests/legacy/helpers/mock_server";
|
||||
import testUtils from "@web/../tests/legacy/helpers/test_utils";
|
||||
import * as coreUtils from "@web/core/utils/patch";
|
||||
import * as OdooEditorLib from "@web_editor/js/editor/odoo-editor/src/OdooEditor";
|
||||
@@ -117,28 +116,6 @@ coreUtils.patch(MockServer.prototype, {
|
||||
return super._performRPC(...arguments);
|
||||
},
|
||||
});
|
||||
MockServerLegacy.include({
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
* @private
|
||||
* @returns {Promise}
|
||||
*/
|
||||
async _performRpc(route, args) {
|
||||
if (args.model === "ir.ui.view" && args.method === 'render_public_asset') {
|
||||
if (args.args[0] === "web_editor.colorpicker") {
|
||||
return COLOR_PICKER_TEMPLATE;
|
||||
}
|
||||
if (args.args[0] === "web_editor.snippets") {
|
||||
return SNIPPETS_TEMPLATE;
|
||||
}
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Options with animation and edition for test.
|
||||
|
||||
Reference in New Issue
Block a user