Files
odoo_source/addons/web/static/tests/setup.js
T
Julien Mougenot db63ff2259 [REF] web: Owl imports adaptation
In the next version of Owl, all exported terms are directly available
from the top level `owl` object. This commit aims to adapt existing
imports to this new system. This is done by importing any Owl property
used in files at the top, right after the `import` or `require`
statements.

closes odoo/odoo#82736

Related: odoo/enterprise#23609
Signed-off-by: Géry Debongnie <ged@odoo.com>
2022-01-20 11:03:01 +00:00

224 lines
7.8 KiB
JavaScript

/** @odoo-module **/
import core from "web.core";
import session from "web.session";
import { _t } from "web.core";
import { browser, makeRAMLocalStorage } from "@web/core/browser/browser";
import { patchWithCleanup } from "@web/../tests/helpers/utils";
import { legacyProm } from "web.test_legacy";
import { registerCleanup } from "./helpers/cleanup";
import { prepareRegistriesWithCleanup } from "./helpers/mock_env";
import { session as sessionInfo } from "@web/session";
import { prepareLegacyRegistriesWithCleanup } from "./helpers/legacy_env_utils";
const { QWeb, config, loadFile, whenReady } = owl;
config.enableTransitions = false;
QWeb.dev = true;
function stringifyObjectValues(obj, properties) {
let res = "";
for (const dotted of properties) {
const keys = dotted.split(".");
let val = obj;
for (const k of keys) {
val = val[k];
}
res += JSON.stringify(val);
}
return res;
}
function checkGlobalObjectsIntegrity() {
const objects = [
[session, ["user_context", "currencies"]],
[_t, ["database.multi_lang", "database.parameters"]],
];
const initials = objects.map((obj) => stringifyObjectValues(obj[0], obj[1]));
registerCleanup((infos) => {
const finals = objects.map((obj) => stringifyObjectValues(obj[0], obj[1]));
for (const index in initials) {
if (initials[index] !== finals[index]) {
const [global, keys] = objects[index];
throw new Error(
`The keys "${keys}" of some global objects (usually session or _t) may have been polluted by the test "${infos.testName}" in module "${infos.moduleName}"`
);
}
}
});
}
function forceLocaleAndTimezoneWithCleanup() {
const originalLocale = luxon.Settings.defaultLocale;
luxon.Settings.defaultLocale = "en";
const originalZone = luxon.Settings.defaultZone;
luxon.Settings.defaultZone = "Europe/Brussels";
registerCleanup(() => {
luxon.Settings.defaultLocale = originalLocale;
luxon.Settings.defaultZone = originalZone;
});
}
function makeMockLocation(hasListeners = () => true) {
const locationLink = Object.assign(document.createElement("a"), {
href: window.location.origin + window.location.pathname,
assign(url) {
this.href = url;
},
reload() {},
});
return new Proxy(locationLink, {
get(target, p) {
return target[p];
},
set(target, p, value) {
if (p === "hash") {
const oldURL = new URL(locationLink.href).toString();
target[p] = value;
const newURL = new URL(locationLink.href).toString();
if (!hasListeners()) {
return true;
}
// the event hashchange must be triggered in a nonBlocking stack
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#scroll-to-fragid
window.setTimeout(() => {
window.dispatchEvent(new HashChangeEvent("hashchange", { oldURL, newURL }));
});
return true;
}
target[p] = value;
return true;
},
});
}
function patchBrowserWithCleanup() {
const originalAddEventListener = browser.addEventListener;
const originalRemoveEventListener = browser.removeEventListener;
let hasHashChangeListeners = false;
const mockLocation = makeMockLocation(() => hasHashChangeListeners);
patchWithCleanup(
browser,
{
// patch addEventListner to automatically remove listeners bound (via
// browser.addEventListener) during a test (e.g. during the deployment of a service)
addEventListener(evName) {
if (evName === "hashchange") {
hasHashChangeListeners = true;
}
originalAddEventListener(...arguments);
registerCleanup(() => {
originalRemoveEventListener(...arguments);
});
},
navigator: {
userAgent: browser.navigator.userAgent.replace(/\([^)]*\)/, "(X11; Linux x86_64)"),
},
// in tests, we never want to interact with the real url or reload the page
location: mockLocation,
history: {
pushState(state, title, url) {
mockLocation.assign(url);
},
replaceState(state, title, url) {
mockLocation.assign(url);
},
},
// in tests, we never want to interact with the real local/session storages.
localStorage: makeRAMLocalStorage(),
sessionStorage: makeRAMLocalStorage(),
},
{ pure: true }
);
}
function patchLegacyCoreBus() {
// patch core.bus.on to automatically remove listners bound on the legacy bus
// during a test (e.g. during the deployment of a service)
const originalOn = core.bus.on.bind(core.bus);
const originalOff = core.bus.off.bind(core.bus);
patchWithCleanup(core.bus, {
on() {
originalOn(...arguments);
registerCleanup(() => {
originalOff(...arguments);
});
},
});
}
function patchOdoo() {
patchWithCleanup(odoo, {
debug: "",
});
}
function patchSessionInfo() {
patchWithCleanup(sessionInfo, {
cache_hashes: {
load_menus: "161803",
translations: "314159",
},
currencies: {
1: { name: "USD", digits: [69, 2], position: "before", symbol: "$" },
2: { name: "EUR", digits: [69, 2], position: "after", symbol: "€" },
},
user_context: {
lang: "en",
uid: 7,
tz: "taht",
},
qweb: "owl",
uid: 7,
name: "Mitchell",
username: "The wise",
is_admin: true,
is_system: true,
partner_id: 7,
// Commit: 3e847fc8f499c96b8f2d072ab19f35e105fd7749
// to see what user_companies is
user_companies: {
allowed_companies: { 1: { id: 1, name: "Hermit" } },
current_company: 1,
},
db: "test",
server_version: "1.0",
server_version_info: ["1.0"],
});
}
export async function setupTests() {
QUnit.testStart(() => {
checkGlobalObjectsIntegrity();
prepareRegistriesWithCleanup();
prepareLegacyRegistriesWithCleanup();
forceLocaleAndTimezoneWithCleanup();
patchBrowserWithCleanup();
patchLegacyCoreBus();
patchOdoo();
patchSessionInfo();
});
const templatesUrl = `/web/webclient/qweb/${new Date().getTime()}?bundle=web.assets_qweb`;
// TODO replace by `processTemplates` when the legacy system is removed
let templates = await loadFile(templatesUrl);
// as we currently have two qweb engines (owl and legacy), owl templates are
// flagged with attribute `owl="1"`. The following lines removes the 'owl'
// attribute from the templates, so that it doesn't appear in the DOM. For now,
// we make the assumption that 'templates' only contains owl templates. We
// might need at some point to handle the case where we have both owl and
// legacy templates. At the end, we'll get rid of all this.
const doc = new DOMParser().parseFromString(templates, "text/xml");
const owlTemplates = [];
for (let child of doc.querySelectorAll("templates > [owl]")) {
child.removeAttribute("owl");
owlTemplates.push(child.outerHTML);
}
templates = `<templates> ${owlTemplates.join("\n")} </templates>`;
window.__ODOO_TEMPLATES__ = templates;
await Promise.all([whenReady(), legacyProm]);
}