Files
odoo_source/addons/web/static/tests/helpers/utils.js
T
+1 0573acae23 [REF] web: rewrite the webclient in OWL (phase 1)
This commit is the first phase of the conversion of the web/ JS
codebase to the owl framework. The impact of this commit is two-fold.

First, it rewrites the framework part of web with a new system of
services and registries. Services allow to execute code (e.g. do rpcs,
setup things) before launching the application. They can also expose
an API to be used by other parts of the application (e.g. a notification
service would expose a function to display notifications). Services are
often a good extension point for external modules that want to execute
code at webclient startup. Registries offer another way to extend the
application. They provide well designed extension points to add
elements/behaviors from the outside (for instance, to add a systray item,
an error handler...).

Second, this commit initiates the conversion of the webclient to owl
with a top-down approach, around those notions of services and registries.
The root of the web application is now an owl application. Among others,
the WebClient, ActionManager, Navbar, UserMenu, DebugManager, Dialogs,
services (e.g. notification, ajax...) have been converted to the new
framework/architecture.

Legacy views and client actions are still supported (and used). They
will be converted in the next months, and at some point, the support
will be dropped.

Co-authored-by: Aaron Bohy <aab@odoo.com>
Co-authored-by: Bruno Boi <boi@odoo.com>
Co-authored-by: Géry Debongnie <ged@odoo.com>
Co-authored-by: Samuel Degueldre <sad@odoo.com>
Co-authored-by: Mathieu Duckerts-Antoine <dam@odoo.com>
Co-authored-by: Simon Genin (ges) <ges@odoo.com>
Co-authored-by: Francois (fge) <fge@odoo.com>
Co-authored-by: Michael Mattiello (mcm) <mcm@odoo.com>
Co-authored-by: Julien Mougenot <jum@odoo.com>
Co-authored-by: Lucas Perais (lpe) <lpe@odoo.com>
Co-authored-by: Jorge Pinna Puissant <jpp@odoo.com>
2021-06-18 21:31:27 +02:00

139 lines
3.6 KiB
JavaScript

/** @odoo-module **/
import { isMacOS } from "@web/core/browser/feature_detection";
import { patch, unpatch } from "@web/core/utils/patch";
import { registerCleanup } from "./cleanup";
import { download } from "@web/core/network/download";
const { Settings } = luxon;
/**
* Patch the native Date object
*
* Note that it will be automatically unpatched at the end of the test
*
* @param {number} [year]
* @param {number} [month]
* @param {number} [day]
* @param {number} [hours]
* @param {number} [minutes]
* @param {number} [seconds]
*/
export function patchDate(year, month, day, hours, minutes, seconds) {
const actualDate = new Date();
const fakeDate = new Date(year, month, day, hours, minutes, seconds);
const timeInterval = actualDate.getTime() - fakeDate.getTime();
const originalNow = Settings.now;
Settings.now = () => Date.now() - timeInterval;
registerCleanup(() => {
Settings.now = originalNow;
});
}
let nextId = 1;
/**
*
* @param {Object} obj object to patch
* @param {Object} patchValue the actual patch description
* @param {{pure?: boolean}} [options]
*/
export function patchWithCleanup(obj, patchValue, options) {
const patchName = `__test_patch_${nextId++}__`;
patch(obj, patchName, patchValue, options);
registerCleanup(() => {
unpatch(obj, patchName);
});
}
export function getFixture() {
if (QUnit.config.debug) {
return document.body;
} else {
return document.querySelector("#qunit-fixture");
}
}
export async function nextTick() {
await new Promise((resolve) => window.requestAnimationFrame(resolve));
await new Promise((resolve) => setTimeout(resolve));
}
export function makeDeferred() {
let resolve;
let reject;
let prom = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
prom.resolve = resolve;
prom.reject = reject;
return prom;
}
function findElement(el, selector) {
let target = el;
if (selector) {
const els = el.querySelectorAll(selector);
if (els.length === 0) {
throw new Error(`No element found (selector: ${selector})`);
}
if (els.length > 1) {
throw new Error(`Found ${els.length} elements, instead of 1 (selector: ${selector})`);
}
target = els[0];
}
return target;
}
export function triggerEvent(el, selector, eventType, eventAttrs) {
const target = findElement(el, selector);
target.dispatchEvent(new Event(eventType, eventAttrs));
return nextTick();
}
export function click(el, selector) {
return triggerEvent(el, selector, "click", { bubbles: true, cancelable: true });
}
/**
* Triggers an hotkey properly disregarding the operating system.
*
* @param {string} hotkey
* @param {boolean} altIsOptional
* @param {KeyboardEventInit} eventAttrs
*/
export function triggerHotkey(hotkey, altIsOptional = false, eventAttrs = {}) {
eventAttrs.key = hotkey.split("+").pop();
if (/shift/i.test(hotkey)) {
eventAttrs.shiftKey = true;
}
if (/control/i.test(hotkey)) {
if (isMacOS()) {
eventAttrs.metaKey = true;
} else {
eventAttrs.ctrlKey = true;
}
}
if (!altIsOptional) {
if (isMacOS()) {
eventAttrs.ctrlKey = true;
} else {
eventAttrs.altKey = true;
}
}
window.dispatchEvent(new KeyboardEvent("keydown", eventAttrs));
}
export async function legacyExtraNextTick() {
return nextTick();
}
export function mockDownload(cb) {
patchWithCleanup(download, { _download: cb });
}