Compare commits

..

1 Commits

Author SHA1 Message Date
Samuel Degueldre b15327309c [IMP] devtools: introduce basic testing infrastructure 2023-07-05 11:11:47 +02:00
16 changed files with 355 additions and 199 deletions
+2
View File
@@ -1,5 +1,7 @@
/node_modules
/dist
# compiled devtools files
/tools/devtools/assets/*.js
npm-debug.log
+18 -50
View File
@@ -175,21 +175,11 @@ function createAttrUpdater(attr) {
}
function attrsSetter(attrs) {
if (isArray(attrs)) {
if (attrs[0] === "class") {
setClass.call(this, attrs[1]);
}
else {
setAttribute.call(this, attrs[0], attrs[1]);
}
setAttribute.call(this, attrs[0], attrs[1]);
}
else {
for (let k in attrs) {
if (k === "class") {
setClass.call(this, attrs[k]);
}
else {
setAttribute.call(this, k, attrs[k]);
}
setAttribute.call(this, k, attrs[k]);
}
}
}
@@ -201,12 +191,7 @@ function attrsUpdater(attrs, oldAttrs) {
if (val === oldAttrs[1]) {
return;
}
if (name === "class") {
updateClass.call(this, val, oldAttrs[1]);
}
else {
setAttribute.call(this, name, val);
}
setAttribute.call(this, name, val);
}
else {
removeAttribute.call(this, oldAttrs[0]);
@@ -216,23 +201,13 @@ function attrsUpdater(attrs, oldAttrs) {
else {
for (let k in oldAttrs) {
if (!(k in attrs)) {
if (k === "class") {
updateClass.call(this, "", oldAttrs[k]);
}
else {
removeAttribute.call(this, k);
}
removeAttribute.call(this, k);
}
}
for (let k in attrs) {
const val = attrs[k];
if (val !== oldAttrs[k]) {
if (k === "class") {
updateClass.call(this, val, oldAttrs[k]);
}
else {
setAttribute.call(this, k, val);
}
setAttribute.call(this, k, val);
}
}
}
@@ -3900,10 +3875,6 @@ class CodeGenerator {
})
.join("");
}
translate(str) {
const match = translationRE.exec(str);
return match[1] + this.translateFn(match[2]) + match[3];
}
/**
* @returns the newly created block name, if any
*/
@@ -3981,7 +3952,8 @@ class CodeGenerator {
let { block, forceNewBlock } = ctx;
let value = ast.value;
if (value && ctx.translate !== false) {
value = this.translate(value);
const match = translationRE.exec(value);
value = match[1] + this.translateFn(match[2]) + match[3];
}
if (!ctx.inPreTag) {
value = value.replace(whitespaceRE, " ");
@@ -4522,12 +4494,11 @@ class CodeGenerator {
else {
let value;
if (ast.defaultValue) {
const defaultValue = ctx.translate ? this.translate(ast.defaultValue) : ast.defaultValue;
if (ast.value) {
value = `withDefault(${expr}, \`${defaultValue}\`)`;
value = `withDefault(${expr}, \`${ast.defaultValue}\`)`;
}
else {
value = `\`${defaultValue}\``;
value = `\`${ast.defaultValue}\``;
}
}
else {
@@ -4908,10 +4879,10 @@ function parseDOMNode(node, ctx) {
let model = null;
for (let attr of nodeAttrsNames) {
const value = node.getAttribute(attr);
if (attr === "t-on" || attr === "t-on-") {
throw new OwlError("Missing event name with t-on directive");
}
if (attr.startsWith("t-on-")) {
if (attr.startsWith("t-on")) {
if (attr === "t-on") {
throw new OwlError("Missing event name with t-on directive");
}
on = on || {};
on[attr.slice(5)] = value;
}
@@ -5535,7 +5506,7 @@ function compile(template, options = {}) {
}
// do not modify manually. This file is generated by the release script.
const version = "2.1.3";
const version = "2.1.2";
// -----------------------------------------------------------------------------
// Scheduler
@@ -5614,8 +5585,6 @@ window.__OWL_DEVTOOLS__ || (window.__OWL_DEVTOOLS__ = {
apps: new Set(),
Fiber: Fiber,
RootFiber: RootFiber,
toRaw: toRaw,
reactive: reactive,
});
class App extends TemplateSet {
constructor(Root, config = {}) {
@@ -5868,9 +5837,8 @@ function useChildSubEnv(envExtension) {
* will run a cleanup function before patching and before unmounting the
* the component.
*
* @template T
* @param {Effect<T>} effect the effect to run on component mount and/or patch
* @param {()=>T} [computeDependencies=()=>[NaN]] a callback to compute
* @param {Effect} effect the effect to run on component mount and/or patch
* @param {()=>any[]} [computeDependencies=()=>[NaN]] a callback to compute
* dependencies that will decide if the effect needs to be cleaned up and
* run again. If the dependencies did not change, the effect will not run
* again. The default value returns an array containing only NaN because
@@ -5952,6 +5920,6 @@ TemplateSet.prototype._compileTemplate = function _compileTemplate(name, templat
export { App, Component, EventBus, OwlError, __info__, blockDom, loadFile, markRaw, markup, mount, onError, onMounted, onPatched, onRendered, onWillDestroy, onWillPatch, onWillRender, onWillStart, onWillUnmount, onWillUpdateProps, reactive, status, toRaw, useChildSubEnv, useComponent, useEffect, useEnv, useExternalListener, useRef, useState, useSubEnv, validate, validateType, whenReady, xml };
__info__.date = '2023-06-28T09:17:13.630Z';
__info__.hash = '432ff44';
__info__.date = '2023-04-29T07:45:54.333Z';
__info__.hash = 'aabb755';
__info__.url = 'https://github.com/odoo/owl';
+22
View File
@@ -0,0 +1,22 @@
{
"testEnvironment": "jsdom",
"roots": [
"<rootDir>/tests"
],
"setupFiles": [
"./tests/mocks/mockEventTarget.js"
],
"transform": {
"^.+\\.ts?$": "ts-jest"
},
"verbose": false,
"testRegex": "(/tests/.*(test|spec))\\.ts?$",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json",
"node"
]
}
+44 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@odoo/owl",
"version": "2.1.4",
"version": "2.1.3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -1048,6 +1048,31 @@
"@babel/types": "^7.3.0"
}
},
"@types/chrome": {
"version": "0.0.114",
"resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.114.tgz",
"integrity": "sha512-i7qRr74IrxHtbnrZSKUuP5Uvd5EOKwlwJq/yp7+yTPihOXnPhNQO4Z5bqb1XTnrjdbUKEJicaVVbhcgtRijmLA==",
"dev": true,
"requires": {
"@types/filesystem": "*",
"@types/har-format": "*"
}
},
"@types/filesystem": {
"version": "0.0.32",
"resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.32.tgz",
"integrity": "sha512-Yuf4jR5YYMR2DVgwuCiP11s0xuVRyPKmz8vo6HBY3CGdeMj8af93CFZX+T82+VD1+UqHOxTq31lO7MI7lepBtQ==",
"dev": true,
"requires": {
"@types/filewriter": "*"
}
},
"@types/filewriter": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.29.tgz",
"integrity": "sha512-BsPXH/irW0ht0Ji6iw/jJaK8Lj3FJemon2gvEqHKpCdDCeemHa+rI3WBGq5z7cDMZgoLjY40oninGxqk+8NzNQ==",
"dev": true
},
"@types/fs-extra": {
"version": "8.1.2",
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.2.tgz",
@@ -1076,6 +1101,12 @@
"@types/node": "*"
}
},
"@types/har-format": {
"version": "1.2.11",
"resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.11.tgz",
"integrity": "sha512-T232/TneofqK30AD1LRrrf8KnjLvzrjWDp7eWST5KoiSzrBfRsLrWDPk4STQPW4NZG6v2MltnduBVmakbZOBIQ==",
"dev": true
},
"@types/istanbul-lib-coverage": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
@@ -3338,6 +3369,15 @@
}
}
},
"jest-chrome": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/jest-chrome/-/jest-chrome-0.8.0.tgz",
"integrity": "sha512-39RR1GT9nI4e4jsuH1vIf4l5ApxxkcstjGJr+GsOURL8f4Db0UlbRnsZaM+ZRniaGtokqklUH5VFKGZZ6YztUg==",
"dev": true,
"requires": {
"@types/chrome": "^0.0.114"
}
},
"jest-circus": {
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz",
@@ -5594,9 +5634,9 @@
}
},
"tough-cookie": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
"integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz",
"integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==",
"dev": true,
"requires": {
"psl": "^1.1.33",
+10 -29
View File
@@ -1,6 +1,6 @@
{
"name": "@odoo/owl",
"version": "2.1.4",
"version": "2.1.3",
"description": "Odoo Web Library (OWL)",
"main": "dist/owl.cjs.js",
"module": "dist/owl.es.js",
@@ -21,15 +21,19 @@
"dev:devtools-firefox": "npm run build:devtools -- --config-browser=firefox",
"build:devtools-chrome": "npm run dev:devtools-chrome -- --config-env=production",
"build:devtools-firefox": "npm run dev:devtools-firefox -- --config-env=production",
"test": "jest",
"test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand --watch --testTimeout=5000000",
"test:watch": "jest --watch",
"test-owl": "jest",
"test-owl:debug": "node --inspect-brk node_modules/.bin/jest --runInBand --watch --testTimeout=5000000",
"test-owl:watch": "jest --watch",
"test-devtools": "npm run build:devtools-chrome && jest --config=tools/devtools/tests/jest.config.json",
"test-devtools:debug": "npm run build:devtools-chrome && node --inspect-brk node_modules/.bin/jest --config=tools/devtools/tests/jest.config.json --runInBand --watch --testTimeout=5000000",
"test-devtools:watch": "jest --config=tools/devtools/tests/jest.config.json --watch",
"test": "npm run test-owl && npm run test-devtools",
"playground:serve": "python3 tools/playground_server.py || python tools/playground_server.py",
"playground": "npm run build && npm run playground:serve",
"preplayground:watch": "npm run build",
"playground:watch": "npm-run-all --parallel playground:serve \"build:* -- --watch\"",
"prettier": "prettier {src/*.ts,src/**/*.ts,tests/*.ts,tests/**/*.ts,doc/*.md,doc/**/*.md,tools/devtools/**/*.js} --write",
"check-formatting": "prettier {src/*.ts,src/**/*.ts,tests/*.ts,tests/**/*.ts,doc/*.md,doc/**/*.md,tools/devtools/**/*.js} --check",
"check-formatting": "npm run prettier -- --check",
"lint": "eslint src/**/*.ts tests/**/*.ts",
"release": "node tools/release.js",
"compile_templates": "node tools/compile_xml.js"
@@ -55,13 +59,13 @@
"git-rev-sync": "^3.0.2",
"github-api": "^3.3.0",
"jest": "^27.1.0",
"jest-chrome": "^0.8.0",
"jest-diff": "^27.3.1",
"jest-environment-jsdom": "^27.1.0",
"npm-run-all": "^4.1.5",
"prettier": "2.4.1",
"rollup": "^2.56.3",
"rollup-plugin-copy": "^3.3.0",
"rollup-plugin-delete": "^2.0.0",
"rollup-plugin-dts": "^4.2.2",
"rollup-plugin-execute": "^1.1.1",
"rollup-plugin-string": "^3.0.0",
@@ -71,29 +75,6 @@
"ts-jest": "^27.0.5",
"typescript": "4.5.2"
},
"jest": {
"testEnvironment": "jsdom",
"roots": [
"<rootDir>/src",
"<rootDir>/tests"
],
"setupFiles": [
"./tests/mocks/mockEventTarget.js"
],
"transform": {
"^.+\\.ts?$": "ts-jest"
},
"verbose": false,
"testRegex": "(/tests/.*(test|spec))\\.ts?$",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json",
"node"
]
},
"prettier": {
"printWidth": 100,
"endOfLine": "auto"
+1 -1
View File
@@ -1,2 +1,2 @@
// do not modify manually. This file is generated by the release script.
export const version = "2.1.4";
export const version = "2.1.3";
+9 -13
View File
@@ -1,7 +1,6 @@
import terser from "rollup-plugin-terser";
import copy from "rollup-plugin-copy";
import execute from "rollup-plugin-execute";
import del from "rollup-plugin-delete";
import { string } from "rollup-plugin-string";
const isWindows = process.platform === "win32";
@@ -37,12 +36,12 @@ export default ({ "config-browser": browser, "config-env": env }) => {
},
];
function generateRule(input, format = "esm") {
function generateRule(input, plugins = []) {
return {
input: input,
input,
output: [
{
format: format,
format: "esm",
file: input.replace("tools/devtools/src", "dist/devtools"),
},
],
@@ -51,6 +50,7 @@ export default ({ "config-browser": browser, "config-env": env }) => {
include: "**/page_scripts/owl_devtools_global_hook.js",
}),
isProduction && terser.terser(),
...plugins,
],
};
}
@@ -58,7 +58,6 @@ export default ({ "config-browser": browser, "config-env": env }) => {
commands[1] = isWindows
? "npm run compile_templates -- tools\\devtools\\src && move templates.js tools\\devtools\\assets\\templates.js"
: "npm run compile_templates -- tools/devtools/src && mv templates.js tools/devtools/assets/templates.js";
const firstRule = generateRule("tools/devtools/src/page_scripts/owl_devtools_global_hook.js");
if (isProduction) {
commands[0] = isWindows
? "npm run build && copy dist\\owl.iife.js tools\\devtools\\assets\\owl.js && npm run build:compiler"
@@ -68,19 +67,16 @@ export default ({ "config-browser": browser, "config-env": env }) => {
? "copy dist\\owl.iife.js tools\\devtools\\assets\\owl.js"
: "cp dist/owl.iife.js tools/devtools/assets/owl.js";
}
firstRule.plugins.push(execute(commands, true));
const secondRule = generateRule("tools/devtools/src/content.js");
secondRule.plugins.push(copy({ targets: filesToMove }));
const lastRule = generateRule("tools/devtools/src/background.js");
lastRule.plugins.push(del({ targets: "tools/devtools/assets/*.js" }));
return [
firstRule,
secondRule,
generateRule("tools/devtools/src/page_scripts/owl_devtools_global_hook.js", [
execute(commands, true),
]),
generateRule("tools/devtools/src/content.js", [copy({ targets: filesToMove })]),
generateRule("tools/devtools/src/devtools_app/devtools.js"),
generateRule("tools/devtools/src/utils.js"),
generateRule("tools/devtools/src/devtools_app/devtools_panel.js"),
generateRule("tools/devtools/src/popup_app/popup.js"),
lastRule,
generateRule("tools/devtools/src/background.js"),
];
};
@@ -3,8 +3,10 @@
import { DevtoolsWindow } from "./devtools_window/devtools_window";
const { mount } = owl;
import { templates } from "../../assets/templates.js";
import { createStore } from "./store/store";
for (const template in templates) {
owl.App.registerTemplate(template, templates[template]);
}
createStore();
mount(DevtoolsWindow, document.body, { dev: true });
@@ -47,7 +47,7 @@ export class ObjectTreeElement extends Component {
classFor(object) {
// Prototype items will be dyed down to appear less important
if (object.path.some((item) => item?.type === "prototype") && !object.keepLit) {
if (object.path.some((item) => item?.type === "prototype")) {
return "attenuate";
}
// Same for subscription items which are not present in the keys while the keys will be bold
+5 -35
View File
@@ -102,7 +102,7 @@ export const store = reactive({
if (IS_FIREFOX) {
await evalInWindow("window.$0 = $0;", this.activeFrame);
}
const [apps, details] = await evalFunctionInWindow(
const [apps, component] = await evalFunctionInWindow(
"getComponentsTree",
fromOld && this.activeComponent
? [this.activeComponent.path, this.apps, this.activeComponent]
@@ -113,8 +113,7 @@ export const store = reactive({
if (!fromOld && this.settings.expandByDefault) {
this.apps.forEach((tree) => expandNodes(tree, true));
}
keepEnvLit(details);
this.activeComponent = details;
this.activeComponent = component;
},
// Select a component by retrieving its details from the page based on its path
@@ -151,11 +150,9 @@ export const store = reactive({
[component.path],
this.activeFrame
);
if (!details) {
this.activeComponent = details;
if (!this.activeComponent) {
await this.loadComponentsTree(false);
} else {
keepEnvLit(details);
this.activeComponent = details;
}
if (this.page !== "ComponentsTab") {
this.switchTab("ComponentsTab");
@@ -628,9 +625,7 @@ export function useStore() {
return useState(store);
}
init();
async function init() {
export async function createStore() {
store.devtoolsId = await getTabURL();
evalFunctionInWindow("initDevtools", []);
@@ -890,31 +885,6 @@ function expandNodes(node, blacklist = false) {
}
}
// This function transforms the env part of the details such that all env keys are not
// greyed out in the UI at their first occurence
function keepEnvLit(details) {
let alreadyMet = new Set();
for (let i = 0; i < details.env.children.length; i++) {
if (i < details.env.children.length - 1) {
alreadyMet.add(details.env.children[i].name);
} else {
let lastElement = details.env.children[i];
while (lastElement.children.at(-1).name === "[[Prototype]]") {
for (const [index, child] of lastElement.children.entries()) {
if (index < lastElement.children.length - 1) {
if (!alreadyMet.has(child.name)) {
child.keepLit = true;
alreadyMet.add(child.name);
}
} else {
lastElement = child;
}
}
}
}
}
}
// Fold the node given in entry and all of its children
function foldNodes(node) {
node.toggled = false;
@@ -33,11 +33,14 @@
* This process may seem long and indirect but is necessary. This applies to all window.top.postMessage methods in this file.
* More information in the docs: https://developer.chrome.com/docs/extensions/mv3/devtools/#evaluated-scripts-to-devtools
*/
window.top.postMessage({
source: "owl-devtools",
type: "NewIFrame",
data: addedNode.contentDocument.location.href,
});
window.top.postMessage(
{
source: "owl-devtools",
type: "NewIFrame",
data: addedNode.contentDocument.location.href,
},
"/"
);
}
}
});
@@ -117,15 +120,6 @@
length += element.length;
result.push(element);
}
for (const key of Object.getOwnPropertySymbols(obj)) {
if (length > 25) {
result.push("...");
break;
}
const element = key.toString() + ": " + this.serializeItem(obj[key]);
length += element.length;
result.push(element);
}
return "{" + result.join(", ") + "}";
},
map(obj) {
@@ -183,18 +177,24 @@
original_Complete.call(this, ...arguments);
const path = self.getComponentPath(this.node);
//Add a functionnality to the complete function which sends a message to the window every time it is triggered.
window.top.postMessage({
source: "owl-devtools",
type: "Complete",
data: path,
origin: { frame: self.frame },
});
if (self.recordEvents) {
window.top.postMessage({
window.top.postMessage(
{
source: "owl-devtools",
type: "Event",
data: self.eventsBatch,
});
type: "Complete",
data: path,
origin: { frame: self.frame },
},
"/"
);
if (self.recordEvents) {
window.top.postMessage(
{
source: "owl-devtools",
type: "Event",
data: self.eventsBatch,
},
"/"
);
self.eventsBatch = [];
}
};
@@ -207,17 +207,23 @@
const originalDelete = this.apps.delete;
this.apps.add = function () {
originalAdd.call(this, ...arguments);
window.top.postMessage({
source: "owl-devtools",
type: "RefreshApps",
});
window.top.postMessage(
{
source: "owl-devtools",
type: "RefreshApps",
},
"/"
);
};
this.apps.delete = function () {
originalDelete.call(this, ...arguments);
window.top.postMessage({
source: "owl-devtools",
type: "RefreshApps",
});
window.top.postMessage(
{
source: "owl-devtools",
type: "RefreshApps",
},
"/"
);
};
}
@@ -611,11 +617,14 @@
const path = this.getElementPath(target);
this.highlightComponent(path);
this.currentSelectedElement = target;
window.top.postMessage({
source: "owl-devtools",
type: "SelectElement",
data: path,
});
window.top.postMessage(
{
source: "owl-devtools",
type: "SelectElement",
data: path,
},
"/"
);
}
};
@@ -639,10 +648,13 @@
document.removeEventListener("mouseover", this.HTMLSelector, { capture: true });
document.removeEventListener("click", this.disableHTMLSelector, { capture: true });
document.removeEventListener("mouseout", this.removeHighlights, { capture: true });
window.top.postMessage({
source: "owl-devtools",
type: "StopSelector",
});
window.top.postMessage(
{
source: "owl-devtools",
type: "StopSelector",
},
"/"
);
};
// Returns the object specified by the path starting from the topParent object
@@ -748,9 +760,6 @@
child.contentType = "object";
child.content = this.serializer.serializeItem(Object.getPrototypeOf(parentObj), true);
child.hasChildren = true;
if (!oldTree && type === "env") {
child.toggled = true;
}
break;
case "set entries":
case "map entries":
@@ -827,8 +836,7 @@
break;
case obj instanceof Object:
child.contentType = "object";
child.hasChildren =
Object.keys(obj).length || Object.getOwnPropertySymbols(obj).length;
child.hasChildren = Object.keys(obj).length > 0;
break;
default:
child.contentType = typeof obj;
@@ -893,7 +901,7 @@
const children = [];
depth = depth + 1;
let obj = this.getObjectProperty(path);
let oldBranch = oldTree && this.getObjectInOldTree(oldTree, path, objType);
let oldBranch = this.getObjectInOldTree(oldTree, path, objType);
if (!obj) {
return [];
}
@@ -908,7 +916,7 @@
depth,
objType,
path,
oldBranch?.children[0],
oldBranch.children[0],
oldTree
);
children.push(mapKey);
@@ -918,7 +926,7 @@
depth,
objType,
path,
oldBranch?.children[1],
oldBranch.children[1],
oldTree
);
children.push(mapValue);
@@ -929,7 +937,7 @@
depth,
objType,
path,
oldBranch?.children[0],
oldBranch.children[0],
oldTree
);
children.push(setValue);
@@ -950,7 +958,7 @@
depth,
objType,
path,
oldBranch?.children[index],
oldBranch.children[index],
oldTree
);
if (child) {
@@ -965,7 +973,7 @@
depth,
objType,
path,
oldBranch?.children[index],
oldBranch.children[index],
oldTree
);
if (child) {
@@ -982,7 +990,7 @@
depth,
objType,
path,
oldBranch?.children[index],
oldBranch.children[index],
oldTree
);
if (entries) {
@@ -996,7 +1004,7 @@
depth,
objType,
path,
oldBranch?.children[index],
oldBranch.children[index],
oldTree
);
if (child) {
@@ -1031,7 +1039,7 @@
depth,
objType,
path,
oldBranch?.children[index],
oldBranch.children[index],
oldTree
);
if (child) children.push(child);
@@ -1064,14 +1072,14 @@
});
proto = Object.getPrototypeOf(proto);
}
if (obj.__proto__) {
if (!(obj.constructor.name === "Object")) {
prototype = this.serializeObjectChild(
obj,
{ type: "prototype", childIndex: children.length },
depth,
objType,
path,
oldBranch?.children.at(-1),
oldBranch.children.at(-1),
oldTree
);
children.push(prototype);
@@ -1446,11 +1454,8 @@
return;
}
}
const item = path.pop();
const key = path.pop().value;
const obj = this.getObjectProperty(path);
const key = item.hasOwnProperty("symbolIndex")
? Object.getOwnPropertySymbols(obj)[item.symbolIndex]
: item.value;
if (!obj) {
return;
}
@@ -1734,7 +1739,7 @@
owlStatus = -1;
}
}
window.postMessage({ source: "owl-devtools", type: "owlStatus", data: owlStatus });
window.postMessage({ source: "owl-devtools", type: "owlStatus", data: owlStatus }, "/");
}
if (!window.__OWL_DEVTOOLS__) {
@@ -1756,19 +1761,19 @@
if (value?.Fiber !== undefined) {
window.__OWL__DEVTOOLS_GLOBAL_HOOK__ = new OwlDevtoolsGlobalHook();
}
window.top.postMessage({ source: "owl-devtools", type: "FrameReady" });
window.top.postMessage({ source: "owl-devtools", type: "FrameReady" }, "/");
checkOwlStatus();
},
});
// Do note that the reload message is not sent on the top window so that it is not intercepted when originating
// from an iframe
window.postMessage({ source: "owl-devtools", type: "Reload" });
window.postMessage({ source: "owl-devtools", type: "Reload" }, "/");
} else if (
window.__OWL_DEVTOOLS__?.Fiber !== undefined &&
!window.__OWL__DEVTOOLS_GLOBAL_HOOK__
) {
window.__OWL__DEVTOOLS_GLOBAL_HOOK__ = new OwlDevtoolsGlobalHook();
window.postMessage({ source: "owl-devtools", type: "Reload" });
window.postMessage({ source: "owl-devtools", type: "Reload" }, "/");
}
// Listener that checks whether owl is available on the page and if it has the right version
window.addEventListener(
+9
View File
@@ -0,0 +1,9 @@
import type * as owl from "../../../src/runtime";
import type { JestChrome } from "jest-chrome/types/jest-chrome";
declare global {
interface Window {
owl: typeof owl;
browser: any;
chrome: JestChrome;
}
}
+15
View File
@@ -0,0 +1,15 @@
import { mount } from "../../../src";
import { makeTestFixture } from "../../../tests/helpers";
import { DevtoolsWindow } from "../src/devtools_app/devtools_window/devtools_window";
let fixture = makeTestFixture();
beforeEach(() => {
fixture = makeTestFixture();
});
describe("devtools", () => {
test("mounting the devtools", async () => {
await mount(DevtoolsWindow as any, fixture);
expect(fixture.querySelector(".status-message")!.textContent).toContain("There are no apps currently running.")
});
});
+28
View File
@@ -0,0 +1,28 @@
{
"testEnvironment": "jsdom",
"roots": [
"<rootDir>"
],
"setupFiles": [
"<rootDir>/../../../tests/mocks/mockEventTarget.js",
"<rootDir>/setup.ts"
],
"globals": {
"ts-jest": {
"tsconfig": "<rootDir>/tsconfig.json"
}
},
"transform": {
"^.+\\.[jt]s?$": "ts-jest"
},
"verbose": false,
"testRegex": "(/tests/.*(test|spec))\\.ts?$",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json",
"node"
]
}
+9
View File
@@ -0,0 +1,9 @@
import * as owl from "../../../src/runtime";
window.owl = owl;
import { chrome } from "jest-chrome";
window.chrome = chrome;
import { templates } from "../assets/templates";
for (const template in templates) {
owl.App.registerTemplate(template, templates[template as keyof typeof templates]);
}
+109
View File
@@ -0,0 +1,109 @@
{
/**
** Commented-out options have their default values.
**/
"include": [
"**/*.ts",
],
                                                              // "exclude": [],
// "files": [],                   // A list of relative or absolute file paths to include.
// "extends": "",                   // A string containing a path to another configuration file to inherit from.
// "references": [],                   // An array of objects `{"path": "./to/dirOrConfig"}` that specifies projects to reference.
// "compileOnSave": false,                   // Signals to the IDE to generate all files for a given tsconfig.json upon saving.
"compilerOptions": {
                                                            // Main options
"target": "es2019",                                         // Specify ECMAScript target version: 'es3' (default), 'es5', 'es2015', 'es2016', 'es2017','es2018' or 'esnext'.
"module": "es6",                                         // Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.
// "lib": ["esnext", "dom"],                 // Specify library files to be included in the compilation.
"allowJs": true,                  // Allow javascript files to be compiled.
// "checkJs": false,                 // Report errors in .js files.
// "outFile": "./",                 // Concatenate and emit output to single file.
"outDir": "dist",                                           // Redirect output structure to the directory.
// "rootDir": "./",                 // Specify the root directory of input files. Use to control the output directory structure with `--outDir`.
// "project": "",                 // Compile a project given a valid configuration file.
                                                            // Compilation options
// "composite": true,                 // Enable project compilation
// "diagnostics": false,                 // Show diagnostic information.
// "incremental": true,                 // Enable incremental compilation by reading/writing information from prior compilations to a file on disk.
// "isolatedModules": false,                 // Transpile each file as a separate module (similar to 'ts.transpileModule').
// "listEmittedFiles": false,                 // Print names of generated files part of the compilation.
// "listFiles": true,                 // Print names of files part of the compilation.
// "noErrorTruncation": false,                 // Do not truncate error messages.
// "preserveWatchOutput": false,                 // Keep outdated console output in watch mode instead of clearing the screen.
// "traceResolution": false,                 // Enable tracing of the name resolution process.
// "tsBuildInfoFile": ".tsbuildinfo",                 // Specify file to store incremental compilation information.
                                                            // Strict typechecking options
"strict": true,                                          // Enable all strict type-checking options.
// "noImplicitAny": true,                 // Raise error on expressions and declarations with an implied 'any' type.
// "noImplicitThis": true,                 // Raise error on 'this' expressions with an implied 'any' type.
// "strictBindCallApply": true,                 // Enable stricter checking of of the `bind`, `call`, and `apply` methods on functions.
// "strictFunctionTypes": true,                 // Disable bivariant parameter checking for function types.
// "strictNullChecks": true,                 // In strict null checking mode, the null and undefined values are not in the domain of every type and are only assignable to themselves and any.
// "strictPropertyInitialization": true,                 // Ensure non-undefined class properties are initialized in the constructor. This option requires `--strictNullChecks` be enabled in order to take effect.
// "alwaysStrict": true,                 // Parse in strict mode and emit "use strict" for each source file.
                                                            // Additional checks
// "allowUnreachableCode": false,                 // Do not report errors on unreachable code.
// "allowUnusedLabels": false,                 // Do not report errors on unused labels.
"forceConsistentCasingInFileNames": true,                   // Disallow inconsistently-cased references to the same file.
// "noStrictGenericChecks": false,                 // Disable strict checking of generic signatures in function types.
"noUnusedLocals": true,                                     // Report errors on unused locals.
"noUnusedParameters": false,                                // Report errors on unused parameters.
"noImplicitReturns": true,                                  // Report error when not all code paths in function return a value.
"noFallthroughCasesInSwitch": true,                         // Report errors for fallthrough cases in switch statement.
// "skipLibCheck": false,                 // Skip type checking of all declaration files (*.d.ts).
// "suppressExcessPropertyErrors": false,                 // Suppress excess property checks for object literals.
// "suppressImplicitAnyIndexErrors": false,                 // Suppress noImplicitAny errors for indexing objects lacking index signatures.
                                                            // Module resolution options
"moduleResolution": "node",                                 // Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6).
// "baseUrl": "./",                 // Base directory to resolve non-absolute module names.
// "paths": {},                 // A series of entries which re-map imports to lookup locations relative to the 'baseUrl'.
// "rootDirs": [],                 // List of root folders whose combined content represents the structure of the project at runtime.
// "typeRoots": [
// "./node_modules/@types",
// "./tools/devtools/tests"
// ],                 // List of folders to include type definitions from.
"types": [
"jest",
"node"
],                                                // Type declaration files to be included in compilation.
// "allowSyntheticDefaultImports": false                    // Allow default imports from modules with no default export. This does not affect code emit, just typechecking.
"esModuleInterop": true,                  // Emit '__importStar' and '__importDefault' helpers for runtime babel ecosystem compatibility and enable '--allowSyntheticDefaultImports' for typesystem compatibility.
// "maxNodeModuleJsDepth": 0,                 // The maximum dependency depth to search under node_modules and load JavaScript files. Only applicable with --allowJs.
// "preserveSymlinks": false,                 // Do not resolve the real path of symlinks.
"resolveJsonModule": true,                                  // Include modules imported with '.json' extension.
                                                            // Emit options
"declaration": true,                                        // Generates corresponding '.d.ts' file.
"declarationDir": "dist/types",                             // Output directory for generated declaration files.
// "declarationMap": false,                 // Generates a sourcemap for each corresponding '.d.ts' file.
// "emitBOM": false,                 // Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files.
// "emitDeclarationOnly": false,                 // Only emit ‘.d.ts’ declaration files.
// "importHelpers": false,                 // Import emit helpers from 'tslib'.
// "newLine": "LF",                 // Use the specified end of line sequence to be used when emitting files: "crlf" (windows) or "lf" (unix).”
// "noEmit": true,                 // Do not emit outputs.
// "noEmitHelpers": false,                 // Do not generate custom helper functions like __extends in compiled output.
// "noEmitOnError": false,                 // Do not emit outputs if any errors were reported.
// "noImplicitUseStrict": false,                 // Do not emit "use strict" directives in module output.
// "noResolve": false,                 // Do not add triple-slash references or module import targets to the list of compiled files.
"preserveConstEnums": false,                                 // Do not erase const enum declarations in generated code.
// "removeComments": false,                 // Remove all comments except copy-right header comments beginning with
// "experimentalDecorators": true,                 // Enables experimental support for ES7 decorators.
// "emitDecoratorMetadata": true,                 // Enables experimental support for emitting type metadata for decorators.
                                                            // Source map options
// "sourceMap": false,                 // Generates corresponding '.map' file.
// "sourceRoot": "",                 // Specify the location where debugger should locate TypeScript files instead of source locations.
// "mapRoot": "",                 // Specify the location where debugger should locate map files instead of generated locations.
// "inlineSourceMap": true,                 // Emit a single file with source maps instead of having a separate file.
// "inlineSources": true,                 // Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set.
                                                            // JSX options
// "jsx": "preserve",                 // Specify JSX code generation: 'preserve', 'react-native', or 'react'.
// "jsxFactory": "React.createElement",                 // Specify the JSX factory function to use when targeting react JSX emit, e.g. 'React.createElement' or 'h'.
                                                            // Other options
// "allowUmdGlobalAccess": true,                 // Allow accessing UMD globals from modules.
// "charset": "utf8",                 // The character set of the input files.
// "downlevelIteration": false,                 // Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'.
// "disableSizeLimit": false,                 // Disable size limitation on JavaScript project.
// "keyofStringsOnly": false,                 // Resolve 'keyof' to string valued property names only (no numbers or symbols).
// "noLib": false,                 // Do not include the default library file (lib.d.ts).
// "pretty": true,                 // Stylize errors and messages using color and context.
}
}